MySQL优化之创建高性能索引

优化第一步,创建高性能索引

索引基础

  1. 索引可以包含一个或多个列的值,如果索引包含多个列,那么列的顺序也十分重要,因为MySQL只能高效地使用索引的最左前缀列。

  2. ORM工具能够产生符合逻辑的、合法的查询,除非只是生成非常基本的查询,否则它很难生成适合索引的查询。

  3. 在MySQL中,索引是在存储引擎层而不是服务器层实现的,所以,并没有统一的索引标准:不同存储引擎的索引的工作方式并不一样,也不是所有的存储引擎都支持所有类型的索引。

  4. B-Tree意味着所有的值都是按顺序存储的,并且每一个叶子页到根的距离相同,能够加快访问数据的速度,从索引的根节点开始进行搜索,适用于全键值、键值范围或键前缀查找。

  5. B-Tree索引的限制:

    • 如果不是按照索引的最左列开始查找,则无法使用索引
    • 不能跳过索引中的列
    • 如果查询中有某个列的范围查询,则其右边所有列都无法使用索引优化查找
  6. 哈希索引(hash index)基于哈希表实现,只有精确匹配索引所有列的查询才有效,只有Memory引擎显式支持哈希索引。

  7. 哈希索引的限制:

    • 哈希索引只包含哈希值和行指针,而不存储字段值,所以不能使用索引中的值来避免读取行
    • 哈希索引数据并不是按照索引值顺序存储的,所以也就无法用于排序
    • 哈希索引也不支持部分索引列匹配查找,因为哈希索引始终是使用索引列的全部内容来计算哈希值的
    • 只支持等值比较查询,不支持任何范围查询
    • 访问哈希索引的数据非常快,除非有很多哈希冲突
    • 如果哈希冲突很多的话,一些索引维护操作的代价也会很高
  8. 空间数据索引(R-Tree),MyISAM表支持空间索引,可以用作地理数据存储,开源数据库系统中对GIS的解决方案做得比较好的是PostgreSQL的PostGIS。

  9. 全文索引,适用于MATCH AGAINST操作,而不是普通的WHERE条件操作。

索引优点

  1. 三个优点:
    • 索引大大减少了服务器需要扫描的数据量
    • 索引可以帮助服务器避免排序和临时表
    • 索引可以将随机I/O变为顺序I/O
  2. 索引三星系统:
    • 索引将相关的记录放到一起则获得一星
    • 如果索引中的数据顺序和查找中的排序一致则获得二星
    • 如果索引中的列包含了查询中需要的全部列则获得三星

高性能索引策略

  1. 独立的列:如果查询中的列不是独立的,则MySQL不会使用索引。“独立的列”是指索引列不能是表达式的一部分,也不能是函数的参数
  2. 前缀索引和索引选择性:
    • 通常可以索引开始的部分字符,可以大大节约索引空间,但也会降低索引的选择性
    • 索引的选择性是指,不重复的索引值(也称为基数,cardinality)和数据表的记录总数(#T)的比值,范围从1/#T到1之间,选择性越高则查询效率越高,因为选择性高的索引可以让MySQL在查找时过滤掉更多的行
    • MySQL无法使用前缀索引做ORDERY BY和GROUP BY,也无法做覆盖扫描
  3. 选择合适的索引列顺序:
    • 正确的索引列顺序依赖于使用该索引的查询,并且同时需要考虑如何更好地满足排序和分组的需要
    • 在一个多列B-Tree索引中,索引列的顺序意味着索引首先按照最左列进行排序,其次是第二列
    • 将选择性最高的列放到索引最前列
  4. 聚簇索引(并不是一种单独的索引类型,而是一种数据存储方式)
    • 最好避免随机的(不连续且值的分布范围非常大)聚簇索引,特别是对于I/O密集型的应用
  5. 覆盖索引:如果一个索引包含(或者说覆盖)所有需要查询的字段的值,就称为覆盖索引
    • 覆盖索引必须要存储索引列的值
  6. 如果EXPLAIN出来的type列的值为“index”,则说明MySQL使用了索引扫描来做排序
  7. 压缩(前缀)索引,默认只压缩字符串,减少索引大小,对于CPU密集型应用,因为扫描需要随机查找,压缩索引在MyISAM上要慢好几倍
  8. 重复索引是指在相同的列上按照相同的顺序创建的相同类型的索引,应该避免这样创建重复索引
  9. 索引可以让查询锁定更少的行

维护索引和表

  1. CHECK TABLE检查表是否损坏,ALTER TABLE innodb_tb1 ENGINE=INNODB;修复表
  2. records_in_range()通过向存储引擎传入两个边界值获取在这个范围大概有多少条记录,对于innodb不精确
  3. info()返回各种类型的数据,包括索引的基数
  4. 可以使用SHOW INDEX FROM命令来查看索引的基数
  5. B-Tree索引可能会碎片化,这会降低查询的效率