• Sql性能优化


    Mysql数据库优化是多方面的,原则是减少系统的瓶颈,减少资源的占用,增加系统的反应速度。例如,通过优化文件系统,提高磁盘I的读写速度;通过优化操作系统调度策略,提高MySQL在高负荷情况下的负载能力;优化表结构,索引、查询语句等使查询响应更快。

    在MySQL中,可以使用SHOW STATUS 语句查询一些MySQL的性能参数

    1 SHOW STATUS LIKE 'value';
    2 常用性能的参数如下:
    3     Connections:连接mysql服务器的次数 
    4     Uptime:MySQL服务器上线的时间
    5     SLow_queries:慢查询的次数
    6     Com_selet:查询操作的次数
    7     Com_insert:插入操作的次数
    8     Com_update:修改操作的次数 
    9     Com_delete:删除操作的次数

    利用EXPLAGIN分析查询语句/h2>

      EXPLAGIN语句的基本语法

     explain select * from tbl_order_goodsG

    1、id:select的查询序列号,值越大优先级越高,越先被执行

    2、select_type:select语句的类型。有几种取值

    (1)SIMPLE 简单查询,不包括连接查询和子查询

    (2)PRIMARY 主查询或者是最外层查语句询,不包括连接查询和子查询

    (3)UNION和UNION RESULT  UNION 表示连接查询的第二个或后面的查询语句,不依赖于外部查询的结果集。UNION RESULT表示UNION查询的结果集

    (4)dependent union 表示连接查询的第二个或后面的select语句,取决于外面的查询

    (5)subquery 表示子查询中的第一个select语句,不依赖于外部查询的结果集

    (6)dependent subquery 表示子查询中的第一个select语句,取决于外面查询的

    (7)derived 查询类型用于from字句里有子查询的情况。MySQL会递归执行这些子查询,把结果放在临时表里。

    4、type 表示表的连接类型

     3     system          表只有一行
     4     const           表最多只有一行匹配,通用用于主键或者唯一索引比较时
     5     eq_ref          每次与之前的表合并行都只在该表读取一行,这是除了system,const之外最好的一种,
     6                     特点是使用=,而且索引的所有部分都参与join且索引是主键或非空唯一键的索引
     7     ref             如果每次只匹配少数行,那就是比较好的一种,使用=或<=>,可以是左覆盖索引或非主键或非唯一键
     8     fulltext        全文搜索
     9     ref_or_null     与ref类似,但包括NULL
    10     index_merge     表示出现了索引合并优化(包括交集,并集以及交集之间的并集),但不包括跨表和全文索引。
    11                     这个比较复杂,目前的理解是合并单表的范围索引扫描(如果成本估算比普通的range要更优的话)
    12     unique_subquery 在in子查询中,就是value in (select...)把形如“select unique_key_column”的子查询替换。
    13                     PS:所以不一定in子句中使用子查询就是低效的!
    14     index_subquery  同上,但把形如”select non_unique_key_column“的子查询替换
    15     range           常数值的范围
    16     index           a.当查询是索引覆盖的,即所有数据均可从索引树获取的时候(Extra中有Using Index);
    17                     b.以索引顺序从索引中查找数据行的全表扫描(无 Using Index);
    18                     c.如果Extra中Using Index与Using Where同时出现的话,则是利用索引查找键值的意思;
    19                     d.如单独出现,则是用读索引来代替读行,但不用于查找
    20     all             全表扫描

    5、possible_keys:可能使用到的索引,如果是NULL,则没有相关的索引

    6、key:经过优化器评估最终使用的索引

    7、key_length:使用到的索引长度

    8、ref:引用到的上一个表的列

    9、rows:rows_examined,要得到最终记录索要扫描经过的记录数

    10、Extra:额外的信息说明

       10.1、Using index 
       mysql使用了覆盖索引,避免访问了镖的数据行,效率不错

     10.2、Using where 
      表示服务器在存储引擎收到行后将进行过滤。 

      10.3、Using temporary 
      Mysql对查询结果进行排序的时候使用了一张临时表。

      10.3、

      Using filesort  mysql会对数据使用一个外部的索引排序

      当出现Using temporary 和Using filesort时,需要对查询语句进行优化操作。

    如何使用索引查询

    1、使用like关键字查询语句

    在使用like关键字进行查询的查询语句中,如果匹配字符串的第一个字符为"%",索引不会起作用。只有"%"不再第一个位置,索引才会起作用

    2、使用多列索引查询语句

    一个索引可以包括16个字段。对于多列索引,只有查询条件中使用了这些字段中第一个字段时,索引才会被使用

    3、使用or关键字的查询语句

    查询条件中只有or关键字,且or前后的两个条件中的列都是索引时,查询中才使用索引。否则,查询将不使用索引。

    优化insert语句

    第一种:

    insert into tbl_shop_order (id,name)values(1,'小鸡炖蘑菇')要比insert into tbl_shop_order (id,name)value(1,'小鸡炖蘑菇')速度快。

    当一个文本文件载入一个表时,使用load data infile加载数据往往比使用很多insert语句效率至少提高20倍。

    例:数据库结构

    1  CREATE TABLE `t0` (
    2   `id` bigint(20) unsigned NOT NULL auto_increment,
    3   `name` char(20) NOT NULL,
    4   `age` tinyint(3) unsigned NOT NULL,
    5   `description` text NOT NULL,
    6   PRIMARY KEY  (`id`),
    7   UNIQUE KEY `idx_name` (`name`),
    8 update_time  timestamp not null
    9 ) ENGINE=MyISAM DEFAULT CHARSET=utf8

    s.txt文件内容

     1 "我爱你","20","相貌平常,经常耍流氓!哈哈"
     2 "李奎","21","相貌平常,经常耍流氓!哈哈"
     3 "王二米","20","相貌平常,经常耍流氓!哈哈"
     4 "老三","24","很强"
     5 "老四","34","XXXXX"
     6 "老五","52","***%*¥*¥*¥*¥"
     7 "小猫","45","中间省略。。。"
     8 "小狗","12","就会叫"
     9 "小妹","21","PP的很"
    10 "小坏蛋","52","表里不一"
    11 "上帝他爷","96","非常英俊"
    12 "MM来了","10","。。。"
    13 "歌颂党","20","社会主义好"
    14 "人民好","20","的确是好"
    15 "老高","10","学习很好"
    16 "斜三","60","眼睛斜了"
    17 "中华之子","100","威武的不行了"
    18 "大米","63","我爱吃"
    19 "苹果","15","好吃"
    View Code

    执行sql语句

    load data infile 'G:/s.txt' ignore into table t0 character set gbk fields terminated by ',' enclosed by '"' lines terminated by '
    '(`name`,`age`,`description`)set update_time=current_timestamp;

    第二种:对于myisam类型的表,可以通过insert into delayed语句提升执行速度。insert delayed into是客户端提交数据给mysql服务器,mysql服务器返回OK状态码给客户端,实际上,数据还没有被插入到表,而是存储在内存里面等待排队,当mysql服务器空闲时在执行插入。优点是速度快,缺点是,系统崩溃,数据会丢失

    第三种:锁表,加快插入数据速度

    1 lock tables tbl_shop_order write;
    2 insert into tbl_shop_order (id,name)values(1,'小鸡炖蘑菇');
    3 unlock tables;

    如果不加锁定表,每一次insert完成之后,索引缓冲区都会被写到磁盘上,加入锁定后索引缓冲区仅被写到磁盘上1次

    优化order by语句

    1、order by id/order by id索引优化(这应该是常识,大家都懂,id加索引)

    select * from tbl_shop_order where id=10
    select * from tbl_shop_order  order by id

    2、order by id +limit 组合的索引优化

    select * from tbl_shop_order  where name='天王盖地虎'  order by id

    只对id添加索引,效率不是很高,更加高效的方法就是建一个联合索引(name,id)

    3、不要对where和order by 的选项使用表达式或者函数

    4、order by 的字段混合使用asc和desc(估计没人这么干过)

    select * from tbl_shop_order order by id desc,name asc;此方法不应该使用索引

    5、where字句使用的字段和order by的字段不一致

    select * from tbl_shop_orde where id=1 order by name;此方法不应该使用索引

    6、对不同的关键字使用order by 排序

    select * from tbl_shop_orde order by id,name;此方法不应该使用索引

    优化group by语句

    使用grouo by语句时,默认情况,mysql会对符合的结果自动排序。通过扫描整个表并创建一个新的临时表,表中美工组的所有行应为连续,然后使用该临时表来找到组并应用累计行数。

    group by 优先于order by
    group by是分组查询,一般与聚会函数配合使用

    通过使用 order by null禁止排序,从而可以节省耗损

    explain select wm_order_platform,count(*) as c from tbl_shop_order group by wm_order_id order by null;

    优化嵌套查询

    1、使用用join代替子查询(避免了创建临时表)

    2、两张表关联时,大表关联小表,这样速度更快

    优化or 条件

    使用or条件语句,如果要使用索引,则or直接的每个条件都必须使用到索引,如果没有,考虑添加索引。

    explain select * from tbl_shop_order where id=1 or wm_order_id=2;

    优化插入记录的速度

    插入记录时,影响插入速度的主要是索引,唯一性教研,一次插入记录条数等。

    1、禁用索引

    对于非空表,插入记录时,mysql会根据表的索引队插入的记录建立索引,如果要插入大力的数据,建立索引会降低插入记录的速度。可以在插入记录之前禁用索引,插入完成之后在开启索引

    alter table tbl_shop_order DISABLE KEYS;(tbl_shop_order 表名)

    开启索引

    alter table tbl_shop_order ENABLE KEYS;

    2、禁用唯一性检查

    SET UNIQUE_CHECK=0;(禁用)
    load ...
    SET UNIQUE_CHECK=1;(开启)

    3、批量插入

    insert into tbl_shop_order (id,name)values(1,'小鸡炖蘑菇'),values(1,'小鸡炖蘑菇'),values(1,'小鸡炖蘑菇'),values(1,'小鸡炖蘑菇');

    4、使用load命令批量导入

    以下是针对myisam存储引擎的表

    alter table t0 disable keys;
    load ....
    alter table t0 enablekeys;

    以下是针对innoDB存储引擎的表

    1、禁用唯一性检查

    set unique_checks=0
    load ....
    set unique_checks=1

    2、禁用外键检查

    set foreign_key_checks=0
    load ....
    set foreign_key_checks=1

    3、禁止自动提交

    set autocommit=0
    load ....
    set autocommit=1

    优化数据库结构

    1、将字段很多的表分解成多个表

    2、增加中间表(对于经常联合查询的表,可以建立中间表以提高查询效率)

    3、增加冗余字段(设计数据库时应尽量遵循范式理论的规约,尽可能减少冗余字段。但是适当的增加冗余字段,可以提高查询速度)

    分析表

    分析表主要是分析关键字的分布

    analyze table t0;

    table:表名 

    op:执行的操作 .analyze表示进行分析操作

    msg_type:信息类型。通常为状态(status),信息(info),注意(note),警告(warning)和错误(error)

    msg_text:显示信息

    analyz table分析表的过程中,数据库系统会自动对表加一个只读锁。分析期间只能读,不能改、增加。analyz table可以分析mysiam和innoDB

    检查表

    检查表主要是检查表是否存在错误

    check table 可以坚持mysiam和innodb类型的表是否存在错误。对与myisam类型的表check table语句会更新关键字统计数据。而且check table可以坚持师徒是否有错误

    check table t0

    优化表

    优化表主要是消除删除或者更新造成的空间浪费

    optilmize table语句来优化表

    optilmize table只能优化表中的varchar,blob或text类型的字段

    optilmize table语句可以消除删除和更新造成的文件碎片。optilmize table在执行过程中也会给表加上只读锁

    本文乃《MySQL技术精粹->架构、高级特性、性能优化与集群实战》读书笔记!

  • 相关阅读:
    NOI2018:屠龙勇士
    Hello world!
    bzoj5月月赛订正
    codeforces906 D
    bzoj2728 [HNOI2012]与非
    bzoj3884上帝与集合的正确用法
    bzoj2817[ZJOI2012]波浪
    2017多校联合赛1[题解]
    论如何优雅的用bitset来求四维偏序
    bzoj1488[HNOI2009]图的同构
  • 原文地址:https://www.cnblogs.com/xb88/p/8505331.html
Copyright © 2020-2023  润新知