- 索引失效总结(复合索引)
- 单表查询时,保证where查询条件的顺序和个数与索引建立的顺序和个数要保持一致
- 最佳左前缀法则,即where的查询条件要从索引的列的最左列开始并且不跳过索引中的列
- 不在索引列上做任何操作(计算、函数、(自动or手动)类型转换),会导致索引失效而转向全表扫描。
- 存储引擎不能使用索引中范围条件右边的列,即where 范围查询条件后面的索引列失效
- 尽量使用覆盖索引(只访问索引的查询(索引列和查询列一致)),减少select*查询
- 查询条件中使用is null,is not null也无法使用索引
- like以通配符开头('%abc.... ')mysql索引失效会变成全表扫描的操作,只有写在最右边才会避免查询失效;2. 在生产过程中,必须要写两边百分号
对于 like 两边百分号的原因,比较推荐的方法是使用覆盖索引
- 字符串不加单引号索引失效
- 少用or,用它来连接时会索引失效
- mysql在使用不等于(!=或者<>)的时候无法使用索引,会导致全表扫描
- 一般性建议
- 对于单键索引,尽量选择针对当前query过滤性更好的索引
- 在选择组合索引的时候,当前Query中过滤性最好的字段在索引字段顺序中,位置越靠前越好。
- 在选择组合索引的时候,尽量选择可以能够包含当前query中的where字句中更多字段的索引
- 尽可能通过分析统计信息和调整query的写法来达到选择合适索引的目的
- 使用索引可加快数据检索速度,但为每个列都建立索引没有必要。因为索引自身也需要维护,并占用一定的资源,可以按照以下标准选择建立索引的列
- 频繁搜索、查询选择的列
- 经常排序、分组的列
- 经常用于连接的列(主键、外键)
在MySQL可以通过查询当前会话的last_query_cost的值来得到其计算当前查询的成本
- 索引优化总结
- 单列索引还是多列索引?
由于mysql只能用到你所有建立的索引中的唯一一个最优索引,所以如果建立多个单列索引,其实效率并不会高(虽然 mysql5.x以上的版本,会在查询时,做索引合并的优化,但仍不建议这么做)
- 索引可以优化查询,那么索引真的越多越好吗?
由于mysql的索引是表的数据的一部分,就像你手中的汉语词典一样,目录越庞大,可读性越差(查询性能越差)。而且,在insert,update,delete时,都要额外维护索引的成本,建立过多的索引可能意味着更差的写性能。
- 如何优化查询?
- 尽可能的让查询走索引,查询条件尽量避免出现 or
- 范围查询, col like '%xxx%'模糊查询,会导致范围|模糊查询 之后的条件索引失效
- 子查询使用关联查询替代
- 关联查询,用小表驱动大表
- 学会使用limit,limit会让你的查询提前返回需要的行,这点在排序的时候尤其有用(避免全部排序,只排序需要的列)
- 在多租户的系统里,千万别漏掉tenant_id这个辨识度最高的列(tenant_id建议放在最左边)
- 查询优化分析
- 观察,至少跑1天,看看生产的慢SQL情况。
- 开启慢查询日志,设置阈值,比如超过5秒钟的就是慢SQL,并将它抓取出来。
- explain+慢SQL分析
Explain能够告诉你这个查询在数据库中是一个什么样的执行计划来实现的。首先我们需要有个目标,通过不断调整尝试,再借助Explain来验证结果是否满足自己的需求,直到得到预期的结果。
- show profile分析
MySQL的Explain执行计划可以用来对Sql语句进行分析,是否进行全表扫描,是否用了索引,或者是sql语句先后执行计划,有没有用临时表等等,由此来进行Sql优化,而show Profile和Explain一样都是用来查看Sql语句分析的,但是形式不一样,show Profile用来分析当前会话语句执行的资源消耗情况,能清晰的知道sql执行过程,以及过程中消耗的时间。
- 进行SQL数据库服务器的参数调优。
- 查询优化原则
- 小表驱动大表,即小的数据集驱动大的数据集
- 查询优化思路
- 优化更需要优化的查询
- 定位优化对象的性能瓶颈
- 明确优化的目标
- 从Explain入手
- 多使用 profile
- 永远用小结果集驱动大结果集
- 尽可能在索引中完成排序
- 只取出自己需要的字段(Columns)
- 仅仅使用最有效的过滤条件
- 尽可能避免复杂的join
- OrderBy关键字排序优化
order by 子句,尽量使用index方式排序,避免使用file sort方式排序,尽可能在索引列上完成排序操作,遵照索引键的最佳左前缀法则。
会产生index方式排序:
- 排序字段使用索引列:ORDER BY 语句使用索引最左前列;
- 使用Where子句与Order By子句条件列组合满足索引最左前列;
排序字段不在索引列:mysql就要启动双路排序和单路排序
优化策略:
- 增大sort_buffer_size参数的设置
- 增大max_length_for_sort_data参数的设置
提高 Order By的速度:
- Order by时 select*是一个大忌只 Query需要的字段,这点非常重要。在这里的影响是:
- 当 Query的字段大小总和小于max_length_for_sort_data而且排序字段不是TEXT|BLOB类型时,会用改进后的算法——单路排序,否则用老算法一一多路排序。
- 两种算法的数据都有可能超出 sort buffer的容量,超出之后,会创建tmp文件进行合并排序,导致多次O,但是用单路排序算法的风险会更大一些所以要提高sort_buffer_size。
- 尝试提高 sort_buffer_ size
不管用哪种算法,提髙这个参数都会提高效率,当然,要根据系统的能力去提高,因为这个参数是针对每个进程的
- 尝试提高max_length_for_sort_data
提高这个参数,会增加用改进算法的概率。但是如果设的太高,数据总容量超出 sort_buffer_size的概率就增大,明显症状是高的磁盘ⅣO活动和低的处理器使用率
- group By关键字排序优化
- 应遵循索引键的最佳左前缀法则
- 当无法使用索引列,增大max_length_for_sort_data参数的设置 和增大sort_buffer_ size参数的设置
- where 高于having ,能写在where限定的条件就不要去having中限定了