mysql中的索引

索引

索引的出现其实就是为了提高数据查询的效率,就像书的目录一样。一本 500 页的书,如果你想快速找到其中的某一个知识点,在不借助目录的情况下,那我估计你可得找一会儿。同样,对于数据库的表而言,索引其实就是它的“目录”。

索引的常见模型

索引的出现是为了提高查询效率,但是实现索引的方式却有很多种。介绍下三种常见、也比较简单的数据结构,它们分别是哈希表、有序数组和搜索树。

1.哈希表

哈希表是一种以键 - 值(key-value)存储数据的结构,我们只要输入待查找的键即 key,就可以找到其对应的值即 Value。



优点:
查询、插入、删除时间复杂度O(1)。
缺点:
哈希表这种结构适用于只有等值查询的场景,无法处理排序的情况

2.有序数组

优点:
等值查询和范围查询时间复杂度O(logn)。
缺点:
插入、删除时间复杂度O(n)。

有序数组索引只适用于静态存储引擎。

3.二叉搜索树

特点:
在树中的任意一个节点,其左子树中的每个节点的值,都要小于这个节点的值。
右子树节点的值都大于这个节点的值。
查询、插入、删除时间复杂度O(logn)。

mysql中的索引

一、数据结构角度
1. B+树索引
B+ 树的特点(m叉树):

1.每个节点中子节点的个数不能超过 m,也不能小于 m/2。
2.根节点的子节点个数可以不超过 m/2,这是一个例外。
3.m 叉树只存储索引,并不真正存储数据,这个有点儿类似跳表。
4.通过链表将叶子节点串联在一起,这样可以方便按区间查找。
5.一般情况,根节点会被存储在内存中,其他节点存储在磁盘中。


  树可以有二叉,也可以有多叉。多叉树就是每个节点有多个子节点。
  一棵 100 万节点的平衡二叉树,树高 20。一次查询可能需要访问 20 个数据块。磁盘随机读一个数据块是很慢的,为了让一个查询尽量少地读磁盘,就必须让查询过程访问尽量少的数据块。那么,我们就不应该使用二叉树,而是要使用“N 叉”树。这里,“N 叉”树中的“N”取决于数据块的大小。
  以 InnoDB 的一个整数字段索引为例,这个 N 差不多是 1200。这棵树高是 4 的时候,就可以存 1200 的 3 次方个值,这已经 17 亿了。考虑到树根的数据块总是在内存中的,一个 10 亿行的表上一个整数字段的索引,查找一个值最多只需要访问 3 次磁盘。其实,树的第二层也有很大概率在内存中,那么访问磁盘的平均次数就更少了。

2.Hash索引

  InnoDB存储引擎会监控对表上各索引页的查询,如果监控到某个索引页被频繁查询,并诊断后发现如果为这一页的数据创建Hash索引会带来更大的性能提升,则会自动为这一页的数据创建Hash索引,并称之为自适应Hash索引。自适应Hash是通过缓冲池中B+树的页进行构建的,建立速度很快,不需要对整张表的数据都构建Hash索引,所以我们又可以把自适应Hash索引看成是索引的索引,。注意一点就是InnoDB只会对热点页构建自适应索引,且是由InnoDB自动创建和删除的,所以不能人为干预是否在一张InnoDB的表中创建Hash索引。


3. Full-Text全文索引

  通过数值比较、范围过滤等就可以完成绝大多数我们需要的查询,但是,如果希望通过关键字的匹配来进行查询过滤,那么就需要基于相似度的查询,而不是原来的精确数值比较。全文索引就是为这种场景设计的。
  like + % 就可以实现模糊匹配了,但like + % 在文本比较少时是合适的,对于大量的文本数据检索是非常慢的。全文索引在大量的数据面前,能比 like + % 快 N 倍,速度不是一个数量级,但是全文索引可能存在精度问题。全文索引的实现是倒排索引。

版本支持:
MySQL 5.6 及以后的版本,MyISAM 和 InnoDB 存储引擎均支持全文索引。
只有字段的数据类型为 char、varchar、text 及其系列才可以建全文索引。

二、从逻辑角度
  • 主键索引: 数据列不允许重复,不允许为NULL,一个表只能有一个主键。
  • 唯一索引: 数据列不允许重复,允许为NULL值,一个表允许多个列创建唯一索引。
  • 普通索引: 基本的索引类型,没有唯一性的限制,允许为NULL值。
  • 联合索引:联合索引指多个字段上创建的索引。遵循最左前缀原则。
  • 全文索引:是目前搜索引擎使用的一种关键技术。
三、从物理存储角度

1.聚簇索引
索引B+ Tree的叶子节点存储了整行数据的被称之为聚簇索引。

InnoDB的聚簇索引:

  1. 一个表只能有一个聚簇索引。InnoDB中会对主键建立聚簇索引。
  2. 如果你不指定主键,InnoDB会用一个具有唯一且非空值的索引来代替。
  3. 如果不存在这样的索引,InnoDB会定义一个隐藏的主键,然后对其建立聚簇索引。

2.非聚簇索引
索引B+ Tree的叶子节点只存储了主键的值被称之为非聚簇索引。

覆盖索引
  是指一个查询语句的执行只用从索引中就能够取得,不必从数据表中读取。也可以称之为实现了索引覆盖。 当一条查询语句符合覆盖索引条件时,MySQL只需要通过索引就可以返回查询所需要的数据,这样避免了查到索引后再返回表操作,减少I/O提高效率。
  因为非聚簇索引只存储了主键的值,所以如果希望通过索引查询主键之外的值的时候,需要通过索引查询到主键,再通过主键的索引查询到完整的数据。需要多查询一次。

索引失效

1.对索引字段做函数操作,可能会破坏索引值的有序性,因此就用不上索引了。
例如:

select count(*) from table where month(t_modified)=7;
select * from table where id + 1 = 10000;

2.隐式类型转换
例如:

select * from table where id=110717;
select * from table where CAST(id AS signed int) = 110717;

如果id 的字段类型是 varchar(32),索引也会失效。

3.隐式字符编码转换。
如果两张表字符集不同,一个是 utf8,一个是 utf8mb4,做关联查询的时候索引也会失效。

4.索引遵循最左前缀原则,是按以%开头的Like模糊查询,索引失效。

使用(B-Tree)索引时,有以下一些技巧和注意事项:

索引设计:

  • 主键建议使用自增主键
      表的主键一般都要使用自增 id,不建议使用业务 id ,是因为使用自增 id 可以避免页分裂。
      mysql 的InnoDB 引擎底层数据结构是 B+ 树,所谓的索引其实就是一颗 B+ 树,一个表有多少个索引就会有多少颗 B+ 树。然后 mysql 在底层又是以数据页为单位来存储数据的,一个数据页大小默认为 16k,当然你也可以自定义大小,也就是说如果一个数据页存满了,mysql 就会去申请一个新的数据页来存储数据。
      如果主键为自增 id 的话,mysql 在写满一个数据页的时候,直接申请另一个新数据页接着写就可以了。
      如果主键是非自增 id,为了确保索引有序,mysql 就需要将每次插入的数据都放到合适的位置上。当往一个快满或已满的数据页中插入数据时,新插入的数据会将数据页写满,mysql 就需要申请新的数据页,并且把上个数据页中的部分数据挪到新的数据页上。这就造成了页分裂,这个大量移动数据的过程是会严重影响插入效率的。
  • 索引字段尽量使用数字型(简单的数据类型)
    若只含数值信息的字段尽量不要设计为字符型,这会降低查询和连接的性能,并会增加存储开销。这是因为引擎在处理查询和连接时会逐个比较字符串中每一个字符,而对于数字型而言只需要比较一次就够了
  • 尽量不要让字段的默认值为NULL
    索引不会包含有NULL值的列,只要列中包含有NULL值都将不会被包含在索引中,复合索引中只要有一列含有NULL值,那么这一列对于此复合索引就是无效的。
    所以我们在数据库设计时尽量不要让字段的默认值为NULL,应该指定列为NOT NULL,除非你想存储NULL。你应该用0、一个特殊的值或者一个空串代替空值。
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 219,701评论 6 508
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 93,649评论 3 396
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 166,037评论 0 356
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,994评论 1 295
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 68,018评论 6 395
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,796评论 1 308
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,481评论 3 420
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 39,370评论 0 276
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,868评论 1 319
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 38,014评论 3 338
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 40,153评论 1 352
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,832评论 5 346
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,494评论 3 331
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 32,039评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 33,156评论 1 272
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 48,437评论 3 373
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 45,131评论 2 356