mysql优化
分析效率
show status like “xxx” 查询一些msyql性能参数
- connections: 连接数据库服务端的次数
- slow_queries:慢查询次数
- com_select:查询次数
- com_insert:插入次数等
慢查询日志分析
MySQL的慢查询日志是MySQL提供的一种日志记录,用来记录在MySQL中响应时间超过阈值的语句,具体指运行时间超过long_query_time值的SQL,则会被记录到慢查询日志中(日志可以写入文件或者数据库表,如果对性能要求高的话,建议写文件)。默认情况下,MySQL数据库是不开启慢查询日志的
,long_query_time的默认值为10(即10秒,通常设置为1秒),即运行10秒以上的语句是慢查询语句。
修改my.cnf文件,增加或修改参数slow_query_log 和slow_query_log_file后,然后重启MySQL服务器,如下所示
slow_query_log =1
slow_query_log_file=/tmp/mysql_slow.log
优化查询
联合索引最左前缀原则
复合索引遵守「最左前缀」原则,查询条件中,使用了复合索引前面的字段,索引才会被使用,如果不是按照索引的最左列开始查找,则无法使用索引。 比如在(a,b,c)三个字段上建立联合索引,那么它能够加快a|(a,b)|(a,b,c)三组查询的速度,而不能加快b|(b,a)这种查询顺序。 另外,建联合索引的时候,区分度最高的字段在最左边。
不要在列上使用函数和进行运算
不要在列上使用函数,这将导致索引失效而进行全表扫描。 例如下面的 SQL 语句: select * from artile where YEAR(create_time) <= ‘2018’; 即使 date 上建立了索引,也会全表扫描,可以把计算放到业务层,这样做不仅可以节省数据库的 CPU,还可以起到查询缓存优化效果。
负向条件查询不能使用索引
负向条件有:!=、<>、not in、not exists、not like 等。 select * from artile where status != 1 and status != 2; 可以使用in进行优化: select * from artile where status in (0,3)
使用覆盖索引
所谓覆盖索引,是指被查询的列,数据能从索引中取得,而不用通过行定位符再到数据表上获取,能够极大的提高性能。
可以定义一个让索引包含的额外的列,即使这个列对于索引而言是无用的。
避免强制类型转换
当查询条件左右两侧类型不匹配的时候会发生强制转换,强制转换可能导致索引失效而进行全表扫描。 如果phone字段是varchar类型,则下面的SQL不能命中索引: select * from user where phone=12345678901; 复制代码可以优化为: select * from user where phone=‘12345678901’;
并不是所有的类型转换都会让索引失效。 数字和字符串比对时,是把字符串转为数字了。 例子:user表name和age都分别有索引。
explain select * from user where age ='5';//字符串转为数字了,刚好age是数字,依然能用上索引
explain select * from user where name =8; //此时name索引失效
范围列可以用到索引
范围条件有:<、<=、>、>=、between等。
范围列可以用到索引,但是范围列后面的列无法用到索引,索引最多用于一个范围列,如果查询条件中有两个范围列则无法全用到索引
更新频繁、数据区分度不高的字段上不宜建立索引
更新会变更B+树,更新频繁的字段建立索引会大大降低数据库性能。 「性别」这种区分度不大的属性,建立索引没有意义,不能有效过滤数据,性能与全表扫描类似。 区分度可以使用 count(distinct(列名))/count(*) 来计算,在80%以上的时候就可以建立索引。
避免使用or来连接条件
应该尽量避免在 where 子句中使用 or 来连接条件,因为这会导致索引失效而进行全表扫描,虽然新版的MySQL能够命中索引,但查询优化耗费的 CPU比in多。 Or的时候只有or前后都是索引才有效。
模糊查询
前导模糊查询不能使用索引,非前导查询可以。
分页优化
大的分页数据效率比较差,可以使用子查询先获得对于的Id,然后再查。或者通过id的返回。不过这些都是要id是有序的才行。
如果明确知道只有一条结果返回,limit 1 能够提高效率 虽然自己知道只有一条结果,但数据库并不知道,明确告诉它,让它主动停止游标移动。
旧版本中可以使用limit n,-1;来获取偏移量到最后的数据,新版本中不能这样了,官方建议使用一个较大的数字来实现。
插入的优化
- 如果要插入大量的数据可以在插入前暂停索引、唯一校验、外键检查。不过看存储引擎是否支持。
- load data infile比insert语句快。