创建高性能的索引 2

高性能的索引策略

独立的列

以下两个错误的语句,需要始终将索引列单独放在比较符号的一侧

SELECT actor_id FROM dskils.actor WHERE actor.id + 1 = 5;

SELECT ... WHERE TO_DAYS(CURRENT_DATE) - TO_DAYS(date_col) <= 10;

前缀索引和索引的选择性

有时候需要索引很长的字符列,这会让索引变得大且慢.一个策略是前面提到过的模拟哈希索引.但有时候还不够

  通常可以索引开始的部分字符,这样可以大大节约索引空间,提高索引效率.但是这样也会降低索引的选择性(cardinality).索引的选择性越高查询效率越高,唯一索引的选择性最高为1.

  一般情况下,某个列前缀的选择性也是足够高的,足以满足查询性能.但是对于 BLOB,TEXT 或者很长的 VARCHAR 类型的列,必须使用前缀索引,因为MySQL 不允许索引这些列的完整长度.

  诀窍在于要选择足够长的前缀索引以保证较高的选择性,同事又不能太长(节约空间).前缀应该足够长,以使得前缀索引的选择性接近于索引的整个列.

计算合适的前缀长度的另外一个方法就是计算完整列的选择性,并使前缀的选择性接近于完整列的选择性。下面展示如何计算完整列的选择性:

多列索引

选择合适的索引列顺序

当不需要考虑排序和分组时,最好将选择性最高的列放到索引的最前列.具体的可以测试得出.

聚簇索引

聚簇索引并不是一种单独的索引类型,而是一种数据存储方式.InnoDB 的聚簇索引实际上在同一结构中保存了 B-Tree 索引和数据行.

当表有聚簇索引时,他的数据行实际上存放在索引的叶子页中.术语"聚簇"表示数据行和相邻的兼职紧凑的存储在一起.因为无法同时把数据行存放在两个不同的地方,所以一个表只有一个聚簇索引(不过覆盖索引可以模拟多个聚簇索引的情况).

聚集的数据有以下重要的优点:

  • 可以把相关的数据保存在一起.
  • 数据访问更快.因为聚簇索引将索引和数据存放在用一个 B-Tree 中.
  • 使用覆盖索引扫描的查询可以直接使用节点中的主键值

也有以下缺点:

  • 聚簇索引可以提高 I/O 的性能.如果将数据全部放在内存中将没有使用聚簇索引的必要.
  • 插入速度严重依赖插入顺序.
  • 更新聚簇索引的代价很高.
  • 基于聚簇索引的表在插入新行,或者主键被更新需要移动行的时候可能面临叶分裂的问题.叶分裂会导致表占用更多的磁盘空间
  • 聚簇索引可能导致全表扫描变慢
  • 二级索引可能比想象的更大
  • 二级索引访问需要两次索引查找,而不是一次

覆盖索引

如果索引的叶子节点中已经包含要查询的数据,那么还有什么必要再回表查询呢?如果一个索引包含(或者说覆盖)所有需要查询的字段的值,我们就称为覆盖索引.

覆盖索引有以下优点:

  • 索引条目通常远小于数据行大小,所以如果只需要读取索引,就极大的减少数据访问量。这对MyISAM尤其正确,因为MyISAM能压缩索引以变得更小.
  • 因为索引是按照顺序存储的(单页),所以对于I/O密集型的范围查询会比随机从磁盘读取每一行数据的I/O要少很多
  • 由于InnoDB的聚簇索引,覆盖索引对InnoDB特别有用。InnoDB的二级索引在叶子节点中保存了行的主键值,所以如果二级主键能够覆盖查询,则可以避免对主键索引的二次查询

覆盖索引必须要存储索引列的值,而哈希索引、空间索引、和全文索引都不能存储列的值,所以MySQL只能使用B-Tree索引做覆盖索引.

当发起一个索引覆盖的查询时,在EXPLAIN的Extra列可以看到Usingindex的信息,另外需要注意触发覆盖索引的条件

使用索引来做排序

MySQL 有两种方式可以生成有序的结果:通过排序操作;或者按索引顺序扫描;如果 EXPLAIN 出来的 type 的值为 index, 则说明 MYSQLS使用了索引扫描来做排序.

  • 排序操作: 将查找出来的结果使用排序算法进行排序
  • 按索引顺序扫描:ORDER BY语句后跟着一个被索引的列,如此一来索引的顺序就是索引对应记录的顺序,这样直接顺着索引一直往下读取记录即可得到有序的结果。
  • 随机IO操作会大大拖慢执行速度,导致按照索引扫描的执行速度反而要比排序操作要慢。因此,在考虑使用按照索引扫描的方式去获得有序结果,那么设计索引时必须要考虑索引覆盖的情况

只有当索引的列顺序和 ORDER BY 字句的顺序完全一致,并且所有列的排列方向(倒序或者正序)都一样, MySQL 才能够使用索引来对结果做排序.如果查询需要关联多张表时,则只有当 ORDER BY 子句引用的字段全部为第一个表时,才能使用索引做排序.ORDER BY子句和查找型查询的限制是一样的:需要满足索引的最左前的要求;否则, MySQL 都需要执行排序操作,从而无法利用索引排序.

有一种例外,ORDER BY后跟的字段可以不满足最左前缀原则:当前导量为常量的时候。这样可以弥补索引的不足.

压缩(前缀)索引

MyISAM 使用前缀压缩来减少索引的大小,从而让更多的索引可以放入内存,默认只压缩字符串.

MyISAM 压缩每一个索引块的方法是先保存索引块中的第一个值,然后将其他值和第一个值进行比较得到相同前缀的字节数和剩余的不同后缀部分,把这部分存储起来即可.

压缩快可以使用更少的空间,代价是某些操作可能更慢.

冗余和重复索引

MySQL 允许在相同的列上创建多个索引,无论是有意的还是无意的.MySQL 需要单独维护重复的索引,并且优化器在优化查询的时候也需要逐个的进行查询考虑,这会影响性能.

重复索引是指在相同的列上按照相同的顺序创建的相同类型的索引.

冗余索引通常发生在为表添加新索引的时候.例如有索引(A,B),又添加(A),或者(A,ID),因为 InnoDB 主键列已经包含在二级索引中.

大多数时候都不需要冗余索引,但是如果扩展索引会导致已有的索引变得太大从而影响查询性能,可以新建索引.

未使用的索引

可以使用工具帮助定位未使用的索引.例如 Percona Toolkit中的 pt-index-usage,该公布工具不仅可以读取查询日志并且对日志中的每条查询进行 EXPALIN 操作.

索引和锁

索引可以让查询锁定更少的行.虽然 InnoDB 的行锁效率很高,内存使用很少,但是锁定行的时候任然会带来额外的开销;其次锁定超过需要的行会增加锁争用并减少并发性.

InnoDB 只有在访问行的时候才会对其加锁,而索引能减少 InnoDB 访问的行数,从而减少锁的数量.但着只有当 InnoDB 在存储引擎层能够过滤掉所有不需要的行时才有效.否则数据传输到服务器层以后, MySQL服务器才能应用 WHERE 子句,这是已经无法避免行锁定了,只有到适当的时候才会释放.

InnoDB 在二级索引上使用共享(读)锁,但访问主键索引需要排他(写)锁.这消除了使用覆盖索引的可能性,并且使得 SELECT FOR UPDATE 比 LOCK IN SHARE MODE或非锁定查询要慢得多.

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 199,340评论 5 467
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 83,762评论 2 376
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 146,329评论 0 329
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 53,678评论 1 270
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 62,583评论 5 359
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 47,995评论 1 275
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,493评论 3 390
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,145评论 0 254
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,293评论 1 294
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,250评论 2 317
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,267评论 1 328
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 32,973评论 3 316
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,556评论 3 303
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,648评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,873评论 1 255
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,257评论 2 345
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 41,809评论 2 339

推荐阅读更多精彩内容