mysql索引和查询优化

Posted Itzel_yuki

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了mysql索引和查询优化相关的知识,希望对你有一定的参考价值。

BTree索引:

1、对于组合索引,如果查询中有某个列是范围查询,则其右边所有列都无法使用索引优化查询

2、高性能索引,索引的列不能是表达式的一部分,也不能是函数的参数。应该养成简化where查询的习惯,始终将索引列单独放在符号的一侧。

3、前缀索引和索引的选择性:在创建前缀索引时,选择选择性更丰富的前缀长度。

4、mysql无法使用前缀索引做orderBy和group by ,也无法使用前缀索引做覆盖扫描。

5、组合索引(多列索引):经验法则:将选择性最高的列放到索引的最前面

6、innodb主键是聚簇索引,其他列索引是非聚簇索引。

7、在聚簇索引中随机插入或者更新主键值,会导致页分裂的问题,从而导致表占用更多的磁盘空间(数据存储不紧凑)

8、innodb中二级索引的叶子节点存储了主键的值,因此,当sql中仅涉及索引列和主键列时,不需要回表操作,直接索引覆盖了,using index

9、非聚簇索引的叶子节点存储主键值,而非指向行的指针,虽然会占用更多的空间,但好处是在innodb移动行时,无需更新二级索引中的这个‘指针’

9、聚簇索引的表设计,采用自增主键能保证数据是按照顺序写入的,对于表存储和读取性能会更好。采用UUID作为聚簇索引则会很糟糕,它使得聚簇索引的插入变得完全随机,从而导致页分裂和存储碎片;另一方面,相比自增主键,UUID字段更长,占用空间更多。

10、使用索引扫描做排序,只有当索引的列顺序和order by 子句的顺序完全一致,并且所有列的方向(正序或倒序)都一样时,mysql才能使用索引对结果排序。order by 子句和查找型查询的限制条件是一样的,需要满足索引的最左前缀要求,否则采用文件排序(using filesort)而无法使用索引排序(例外:前导列为常量时,可以不满足最左前缀的要求,可以将选择性很小的列作为前导列,查询时限制为常量来使用组合索引)

11、using where 表示 mysql服务器将存储引擎返回行以后在应用where条件过滤

12、in不是范围查询,而是多个等值条件查询。优化器将in中的值拆分为不同的组合,执行计划检查每种组合,当组合数超过一定数量后,执行计划不在进行评估,这将导致不能很好的使用索引。(不要滥用In查询)

查询优化

1、理想情况下,查询返回的行数和扫描的行数应该相同。

2、explain的type列反映了访问类型,从全表扫描,索引扫描,范围扫描,唯一索引扫描,常数引用,速度从慢到快,扫描行数从多到少。

3、mysql执行一条查询经过几个步骤(1)客户端发送一条查询给服务器;(2)服务器检查查询缓存,如果命中了缓存,则立刻返回存储在缓存中的结果。否则进行下一步;(3)服务器进行sql解析,预处理,再由优化器生成对应的执行计划;(4)mysql根据优化器生成的执行计划调用存储引擎的API来执行查询;(5)将查询结果返回给客户端。

4、mysql的查询优化器,会重新定义关联表的顺序。数据表的关联并不总是按照查询中指定的顺序进行的。

5、mysql的查询优化器,会优化count() min() max()查询,要找某一列的最小值,通常只要查询对应索引的最左端的记录,查询某一列的最大值,通常只需要查询对应索引最右端的记录。

6、mysql的查询优化器,当索引中的列包含所有查询中需要使用的列时,mysql就可以使用索引返回需要的数据,而无需回表查询。

7、mysql的查询优化器,会在表关联时进行等值传播。如果两个列的值通过等式关联,那么mysql能够把其中一列的where条件传递给另一列。

8、mysql的查询优化器,对于In()的比较,会将in列表中的数据进行排序,然后采用二分查找的方式来判断是否满足条件,查询时间复杂度为o(logn),比等价转换成or查询的时间复杂度o(n)要好,处理速度更快。

9、对某个查询执行explain extended后,再执行show warnings,就可以看到执行计划重构出的查询了。

10、mysql查询的关联查询优化器,会将多个关联表中扫描行数最少的表,放到关联查询的最前面,作为关联查询的驱动表。这样,第一个关联表只需要扫描很少的行,其余关联查询可以使用索引查询,速度更快。

11、orderby 子句中所有列都来自关联的第一个表时,mysql在关联处理第一个表的时候就会进行文件排序,using filesort;否则,mysql会先将关联结果存放到一个临时表,在所有的关联关系都结束后,在进行文件排序,这是在extra列会看到using temporary ;using filesort。

12、在mysql 5.6之前in +子查询会转换成 exist的相关子查询,导致外查询无法使用索引,需要全表扫描,当外表数据量大时,查询效率低,需要转换成关联查询(小表在前,大表在后的关联查询)。但mysql5.6及后,in+子查询会优化成 半连接查询,不用额外优化,详解见http://www.cnblogs.com/wxw16/p/6105624.html

13、当where子句中包含多个复杂的条件时,mysql能访问单个表的多个缩索引(index_merge),以合并和交叉过滤的方式来定位需要查找的行。

14、count(A)和count(B),表示统计一张表中A不为空的行数,B不为空的行数,而不是不同值得个数。

15、优化关联查询, 确保on和using 子句的列上有索引。确保group by 和order by 中的表达式只涉及一张表中列,这样mysql才有可能使用索引来优化这个过程。

16、尽可能使用关联查询代替子查询,因为,子查询结果需要创建临时表,而临时表的查询时没有索引的。

17、当使用group by的时候,结果会自动按照分组字段进行排序。如果不关心结果集的顺序,而这种默认排序又导致了需要文件排序,可以使用order by null来让mysql不再进行文件排序。

18、limit优化,limit和offset的问题,其实就是offset的问题,会导致Mysql扫描大量不需要的行,然后抛弃掉。如果可以保存上次取数据的位置,那么下次就可以直接从该位置进行扫描,这样就可以避免使用offset。 

以上是关于mysql索引和查询优化的主要内容,如果未能解决你的问题,请参考以下文章

sql优化

mysql---索引优化

MySQL 千万 级数据量根据(索引)优化 查询 速度

MySQL 千万 级数据量根据(索引)优化 查询 速度

带有子查询的 CTE 查询在小型索引表上很慢;如何在 MySQL 上进行优化?

MYSQL 优化,持续更新收藏