mysql索引总结

B-Tree索引

适用于全键型、键值范围、键前缀查找

全值匹配

匹配最左前缀

匹配列前缀

匹配范围值

精确匹配某一列并范围匹配另外一列

只访问索引的查询

限制

不是按照索引的最左列开始查找,无法使用索引

不能跳过索引中的列(只能使用一部分)

如果查询中某一列是范围查找,则其右边所有列无法使用索引优化查找。

哈希索引

基于哈希表实现,只有精确匹配索引所有列的查询才有效。

哈希索引将所有的哈希码存储在索引中,同时在哈希表中保存指向每个数据行的指针。

限制:

哈希索引只包含哈希值和行指针,而不存储字段值,所以不能使用索引中的值来避免读取行;

数据不是按照索引顺序存储的,所以无法用于排序;

不支持部分索引列匹配查找,因为哈希索引始终是使用索引列的全部内容计算哈希值的;

只支持等值比较查询;不支持任何范围查找;

当存在很多哈希冲突时,存储引擎必须遍历链表中所有行指针,逐行进行比较,直到找到所有服务条件的行。(不同的索引列可能存在相同的哈希值)

索引的优点

1.大大减少了服务器需要扫描的数据量

2.帮助服务器避免排序和临时表

3.可以将随机I/O变为顺序I/O

高性能索引策略

1.独立的列

指索引列不能是表达式的一部分,也不能是函数的参数。

不是独立的列不能使用索引

2.前缀索引和索引选择性

选取索引开始的部分字符,可以节省索引空间,从而提升索引效率,单会降低索引选择性。

索引选择性=不重复的索引值/数据表的记录总数    (当为1时最高,例唯一索引)

BLOB、TEXT或比较长的VARCHAR类型的列,必须使用前缀索引(mysql不支持太长的索引)

选择的标准

前缀的基数应该接近于完整列的基数

例:

select count(*) as cnt,city from city_demo group by city order by cnt dest limit 10;

select count(*) as cnt,left(city,3) as pref from city_demo group by pref order by cnt dest limit 10;

前缀的选择性尽量接近完整列的选择性

select count(distinct city)/count(*) from city_demo;

select count(distinct left(city,3))/count(*) as sel3,

count(distinct left(city,4))/count(*) as sel4,

count(distinct left(city,5))/count(*) as sel5

from city_demo;o

前缀索引的缺点

无法在order by 和group by 中使用

无法用于覆盖扫描

常见应用场景

很长的十六进制唯一ID

3.选择合适的索引顺序

经验法则:将选择性最高的列放在索引最前列。

4.聚簇索引

并不是一种单独的索引类型,而是一种数据存储方式。

InnerDB的聚簇索引实际是在同一结构中保存了B-Tree索引和数据行。

一个表只能有一个聚簇索引,因为无法同时将数据行存储在两个不同的地方。

如果没有主键,InnerDB会选择一个唯一的非空索引代替。如果没有这样的索引,InnoDB会隐式定义一个主键来作为聚簇索引。

优点:

可以把相关数据保存在一起,可减少查询时的磁盘I/O

数据访问更快

使用覆盖索引扫描的查询可以直接使用页节点中的主键值

缺点:

插入速度严重依赖于插入顺序

更新聚簇索引列的代价很高,因为会强制InnerDB将每个被更新的行移动到新的位置

基于聚簇索引插入新行可能导致页分裂问题,从而导致表占用更多的磁盘空间

可能会导致全表扫描变慢(行比较稀疏,或页分裂导致数据存储不连续的情况)

二级索引(非聚簇索引)可能比想象中的更大,因为二级索引的叶子节点中包含了引用行的主键列

二级索引访问需要两次索引查找,而不是一次。

最好避免随机的聚簇索引,特别是对于I/O密集型的应用。如果用UUID主键插入行不仅花费时间更长,索引占用的空间也更大。

顺序的主键什么时候会造成更坏的结果?

高并发时,InnoDB按主键顺序插入会造曾明显的争用。主键的上界会成为热点。冰法插入可能导致间隙锁竞争。另一个热点是AUTO_INCREMENT锁机制。

5.覆盖索引

定义:覆盖所有需要查询的字段的值的索引

优势:

1.索引条目通常远小于数据行大小,所以如果只需要读取索引,MySQL就会极大地减少数据访问量。

2.索引如果按顺序存储时,对于I/O密集型的范围查询会比随机从磁盘读取每一行数据的I/O少很多

3.InnoDB的二级索引在叶子节点中保存了行的主键值,所以如果二级主键能够覆盖查询,则可以避免对主键索引的二次查询

覆盖索引不需要存储索引列的值

6.使用索引扫描来做排序

两种方式可以生成有序的结果:通过排序操作;按索引顺序扫描。

扫描索引本身很快,但如果索引不恩能够覆盖查询所需的全部列,会出现回表查询,属于随机I/O,这种情况通常比顺序的全表扫描慢,尤其是在I/O密集型的工作负载时。

只有索引列的顺序与order by 子句的顺序完全一致,并且所有列的排序方向都一样时,才能使用索引进行排序。

如果多表联合查询,只有order by子句引用的字段都是第一张表时,才能使用索引做排序。

7.压缩(前缀压缩)索引

主要针对MyISAM引擎

索引块中第一个值”perform“,第二个值”performance“,那么第二个值的前缀压缩后存储的是类似”7,ance"这样的形式。MyISAM对行指针也采用类似的前缀压缩方式。

对于CPU密集型应用,扫描需要随机查找,压缩索引会导致查询慢上几倍。但因为压缩索引一般只需要十分之一的磁盘空间,所以如果是I/O密集型应用,对某些查询带来的好处会比成本多很多。

8.冗余和重复索引

重复索引:在相同的列上按照相同的顺序创建的相同类型的索引。

冗余索引,如果创建了索引(A,B),在创建索引(A)就是冗余索引。但是创建(B,A),(B)都不属于冗余索引。

其他不同类型的索引(如哈希,全文)也不会是B-Tree索引的冗余索引。

如果ID索引是主键,则索引(A,ID)也是冗余索引。因为InnoDB的主键列包含在二级索引中了

9.未使用的索引

利用Percona Server 或 MariaDB中先打开userstates服务器变量,然后让服务器运行一段时间,再通过查询INFORMATION_SCHEMA.INDEX_STATISTICS就可以查到每个索引的使用频率。

还可以使用Percona Toolkit中的pt-indax-usage,该工具可以读取查询日志,并且对日志的每条查询进行explain操作,然后打印出关于索引和查询的报告。

10.索引和锁

索引可以让查询呢锁定更少的行。

锁定超过需要的行会增加锁争用并减少并发性。

InnoDB只有在访问行的时候才会对其加锁,而索引能减少InnoDB访问行数,从而减少锁的数量。但只有当InnoDB在存储引擎层能够过滤掉所有不需要的行时才有效。如果索引无法过滤掉无效的行,那么在InnoDB检索到数据并返回给服务器层以后,MySql服务器才能应用where子句。这时已经无法避免行锁定了,已经锁住的行要到适当的时候才能释放。MYSQL5.1以后的版本,InnoDB可以在服务器端过滤掉行后就释放锁。但之前的版本只有到事务提交之后才能释放锁。

InnoDB在二级索引上使用共享(读)锁,但访问主键索引需要排他(写)锁。这消除了使用覆盖索引的可能性,并且使得select for update 比 lock in share mode或非锁定查询要慢很多。

索引案例学习

1.支持多种过滤条件

联合索引把范围查找的放在最后面

2.避免多个范围查找

最好是将范围查询转化成等值比较

3.优化排序

文件排序对小数据集是很快的

偏移量增大后,查询速度会明显变慢。可以通过反范式化、预先计算、缓存解决。还可以通过限制用户翻页数量限制。还可以通过延迟关联进行优化。(先使用覆盖索引查出主键,再通过主键查出需要的行)

如何判断索引是否合理?

判断响应时间

找出消耗最长时间或给服务器带来最大压力的查询,检查schema、sql、索引结构,判断是否有查询扫描了太多行,是否做了很多额外的排序或者使用了临时表,是否使用了随机I/O访问数据,或者是有太多回表查询哪些不再索引中的列的操作。

选择索引和编写利用索引查询的三个原则:

1.单行访问很慢;

2.按顺序访问范围数据很快;

3.索引覆盖查询很快。

mysql中大多数情况会使用B-Tree索引。其他类型索引大多只适用于特殊的目的。

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

推荐阅读更多精彩内容