导致索引失效应该避免的情况:
- 最佳左前缀法则:(带头大哥不能死,中间兄弟不能断)
- 不在索引列上做任何操作(计算、函数、类型转换)
- 存储引擎不能使用索引中范围条件右边的列
- 尽量使用覆盖索引(只访问索引的查询(索引列和查询列一致)),减少select *的使用
- MySQL在使用不等于( != 或 <> )的时候无法使用索引会导致全表扫描
- is null , is not null 也无法使用索引
- like以通配符开头( ‘%a’ )时,MySQL索引失效,导致全表扫描
- 字符串不加单引号
- 用or来连接时,也会导致索引失效
一般建议:
- 对于单键索引,尽量选择针对当前查询过滤性更好的索引
- 在选择组合索引的时候,当前查询中过滤性最好的字段在索引字段顺序中,位置越靠前越好(因为这样做在每一次过滤后会过滤掉大多数据,方便之后再次过滤或进行范围查找,提高效率)
- 在选择组合索引的时候尽量选择可以能够包含当前查询where条件语句中的更多字段的索引
- 尽可能通过分析explain信息与调整查询语句的写法来达到选择合适索引的目的
查询截取分析
- 观察
- 开启慢查询日志,设置阙值,比如超过5秒的就是慢SQL,将它抓取出来
- explain 、慢SQL分析
- show profile 查询SQL在MySQL服务器里面执行的细节和生命周期情况
- SQL数据库服务器的参数调优(max_length_for_sort_data和sort_buffer_size)
查询优化
1. 永远小表驱动大表
即小的数据集驱动大的数据集
exists与in
2. order by 优化
2. group by 优化
group by 实质上是先排序后分组,符合最佳左前缀原则
where高于having,能写在where限定的条件就不要写在having中了
慢查询日志
- 默认情况下,MySQL数据库没有开启慢查询日志,开启此功能会影响性能,调优时需要手动设置
# 查看是否开启:slow_query_log_file 表示 记录慢查询日志的文件
show variables like '%slow_query_log%';
# 开启,只对当前数据库生效,重启后失效
set global slow_query_log=1;
# 查看判断慢查询时间阙值
show variables like 'long_query_time%';
show global variables like 'long_query_time%';
# 设置阙值,如果使用第一条查询阙值的语句需要重新连接或重开一个会话才能看到修改值
set global long_query_time=3;
- 日志分析工具 mysqldumpslow
Show Profile
MySQL 提供的可以用来分析当前会话中语句执行的资源消耗情况,默认关闭
# 查看是否开启
show variables like 'profiling';
# 开启,只对当前数据库生效,重启后失效
set profiling=on;
# 查看执行语句的id
show profiles;
# 查看报告单,即执行细节分析表,#{id}来自上述查询结果中你想要查看的SQL语句的id
show profile cpu,block io for query #{id};
较为严重的情况:
- converting HEAP to MyISAM 查询结果集太大,内存不够用了,开始往磁盘上搬了
- Creating tmp table 创建临时表(拷贝数据到临时表,用完再删除)
- Copying to tmp table on disk 把内存中临时表复制到磁盘
- locked
全局查询日志(生产环境下一定不开启)
- 配置启用
在my.cnf中设置如下:
# 开启
general_log=1
# 记录日志文件的路径
general_log_file=/path/logfile
# 输出格式
log_output=FILE
- 编码启用
# 开启
set global general_log=1;
set global log_output='TABLE';
# 查看
select * from mysql.general_log
批量插入数据的脚本
创建存储过程:create procedure p_name(参数列表)
调用存储过程:call p_name(参数列表)