Mysql索引原理和基本优化

Mysql索引的基本原理

索引的目的就是提高查询效率,其基本原理就是通过不断的缩小数据的范围来筛选出最终想要的结果。但是对于数据库这样一种数据存储结构非常复杂,同时查询方式又相当灵活的系统来说这样看似简单的问题也会变得异常复杂。以前数据结构课程学过很多优化查找性能的数据结构,比如搜索树,其查找时间复杂度是lgN,但是搜索树的时间复杂度是所有数据均在内存中,这样查找操作的耗时主要在cpu,所以才关注它的时间复杂度。但是数据库中的数据都存放在磁盘上,而一次磁盘的IO操作相当于40万次cpu操作,也就是说数据库的性能瓶颈在IO上面,所以除了优化查询的时间复杂度以外很重要的一点是控制IO操作的次数。由于IO操作相当昂贵,所以操作系统也作了优化,即根据局部性原理,每次IO操作都会加载磁盘个上这块数据所在的整个页,至于具体一页有多大的数据,取决于特定的操作系统,一般是4K到8K。也就是说我们多次读取一页的数据实际上才发生了一次IO操作。

有一种数据结构就是考虑了上述种种需求,利用了种种原理设计出来的,就是mysql的索引所使用的数据结构: B+树。

B+树

浅蓝色的块就是一个磁盘快,其中包含数据项和指针,如磁盘块1中包含数据项1735,和指针 P1,P2,P3, P1指向所有小于17的数据所在的磁盘块,P2指向17和35之间的数据所在的磁盘快,P3指向大于35的磁盘块。真实的数据只存储在叶子节点中,非叶子节点只存储指引搜索方向的数据项和指针,不存储真实数据。如果要查询90,那么首先将磁盘快1加载到内存中,根据磁盘块1的数据项和指针确定90应该在磁盘块4中查找,于是从把磁盘快4加在到内存中,再次将搜索范围缩小至磁盘快11,此时返现磁盘快11已经是叶子节点,因此对磁盘块11中的数据做二分查找,最终返回查找结果,总计发生三次IO。实际上数据库实现时会把靠近树根的几层节点常驻内存,不需要发生IO操作,之后的三层B+树可以表示上百万的数据,如果上百万的数据查询只需要三次IO操作,性能提高将是巨大的。

从这个图可以看出B+树的搜索性能取决于树的高度,而在数据量一定,磁盘块个数一定的情况下树的高度则取决于每个磁盘块中存储的数据个数,又在磁盘块大小一定的情况下,每个磁盘块中存储的数据个数则取决于数据的大小。由于B+树中非叶子节点不存储真实数据,只存储指明真实数据方向的数据项和指针,指针大小一定,所以数据项越小,一个磁盘快中存储的数据项就越多,而这个数据项的大小则就是索引类型的大小,也就是说优化查询的第一步就是减小索引的长度。

B+树的数据项是复合数据结构,这也就是组合索引实现的原理,对于复合数据B+树将会先按照第一列的数据划分不同的数据块,指示方向,第一列相同时再依次按照剩下的列划分数据块,指示方向。比如一个复合数据项(name,age,gender),查询(bob,22,F)的时候,B+树会优先比较name来确定下一步的搜索方向。如果name相同则依次比较agegender,那么如果要查询(22,F)这样的数据会发生什么呢?我们的辛辛苦苦建立的这些数据项和指针就完全起不到任何作用了,因为只有name相同的情况下才会按照age来划分数据块,并且指示搜索方向。现在name都不知道,我们就更不知道age,gender的方向了。

从这个数据结构也可以看出,只有当查询具体值的时候指示数据范围的数据项和数据位置的指针才能被高效利用,如果按照范围来查询,可能会垮多个块,当初利用B+树来减少IO次数的思想到此也就不再适用了,反而可能会增加复杂度。因此对于范围查询,mysql只会根据索引进行一次范围查询然后不再利用剩下的索引。

关于优化

在弄清楚了mysql索引的原理之后,优化也就有根有据了。主要有以下几点原则:

  • 最左匹配原则, 对于组合索引,mysql会从左到右使用索引进行匹配,直至遇到范围查询(<,>,between,like)就停止索引匹配,在匹配到的数据中进行全扫描。例如对于复合索引(a,b,c,d)查询a=1 and b=2 and c >3 and d=4,其中d是用不到索引的,要想这个查询使用到索引,可以将索引调整为(a,b,d,c)
  • 索引字段尽量小,这样可以减小搜索树的高度,从而提高查询效率。
  • 索引字段的区分度尽量大,如果索引字段重复性相当高,索引的存在甚至可能会降低查询效率。
  • 索引不能参与计算,可以看出叶子节点的数据项和指针指示的都是最终数据本身的方向,如果参与计算之后计算的结果不一定和最终数据本身方向相同,因此不会遇到索引。
  • 尽量扩展索引,而不是新增索引,一是因为新增索引存储成本更高,而且mysql对每个查询只会用到一个索引(uinion查询除外),因此合适的组合索引查询效率比多个单值索引效率要高。
  • 对于join操作,永远小结果集驱动大结果集 ,第一次锁定小的结果集本身查询效率可能就高一点,而且这个结果集在后面的过滤中区分度页更高,同时小的结果集内存占用也更小。
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 204,921评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 87,635评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 151,393评论 0 338
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,836评论 1 277
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,833评论 5 368
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,685评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,043评论 3 399
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,694评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 42,671评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,670评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,779评论 1 332
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,424评论 4 321
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,027评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,984评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,214评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,108评论 2 351
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,517评论 2 343

推荐阅读更多精彩内容