前言
索引对于良好的查问性能至关重要,尤其是当表的数据量越来越大时。数据量小时,还看不出来索引施展的重要作用。在理论开发时,千万不要鄙视和疏忽了索引的重要性。有时候,一个“最优”的索引甚至比一个“良好”的索引,查问性能要好两个数量级。
索引基础知识
很多人都喜爱将索引比作字典的目录。咱们想要查某个字时,先在目录里查找这个字的页码(索引扫描),而后间接翻到那一页,就找到了那个字。没有目录(字典)时,咱们只能一页一页地翻(全表扫描),这样的话性能毋庸置疑地很慢。
索引能够蕴含一列或队列的值,即单值索引和复合索引。创立复合索引时,须要留神列的程序,因为 MySql 索引遵循左前缀匹配准则。另外须要留神的是,创立一个蕴含 2 列的复合索引和两个 1 列的索引,成果是不一样的。下文将会解释这点。
索引类型
索引是在存储引擎层实现的,而不是服务器层。不同的存储引擎可能反对不同的索引类型。
B-Tree 索引
InnoDB 引擎默认的索引数据结构。
Hash 索引
MySql 中 Memory 引擎反对。
全文索引
相似搜索引擎查找关键词干的事。
InnoDB 能够有 ” 伪哈希索引 ”,在 B -Tree 索引的根底上进行哈希查找,取代原先的按键值查找。
比方 URL 很长,用作索引列会很慢,能够用 CRC_URL(url)后的列值(整型)作为索引,能晋升性能。这里的 CRC_URL()就相当于一个哈希函数。
高性能的索引策略
1. 独立的列
所谓独立的列,指的是不要将索引列作为表达式的一部分或函数的参数。如下是两个谬误例子:
select actorname from actor wher actorid + 1 = 5;
select xxx from xxx where TO_DAYS(CURRENT_DATE) – TODATS(date_col) <= 7;
下面 actorid 和 date_col 上建设的索引,将无奈被 MySql 自动识别并应用。因而咱们尽量不要这么做。
2. 前缀索引和索引选择性
有时候很长的列间接作为索引的话,性能会比较慢,这时咱们须要应用前缀索引,例如下面提到的 CRC_URL。但这还不够,须要思考选择性。所谓选择性,指的是区分度。即应用索引查问时,可能过滤掉的行数。区分度越高,过滤掉的记录数越多,这样索引的成果才好。惟一索引领有最好的区分度,因为没有反复的列值。而像性别这种列,不适宜作为索引列,因为就 2 种值,男 / 女(maybe 还有人妖?),这样只能过滤一半记录。
3. 复合索引
留神,复合索引并不是在多个列上独自的建单列索引,因为这往往并不能很好地晋升性能。
5.x 版本的 MySql 会采纳索引合并策略,即上面的 sql 语句上,actorid 和 filmname 列上各有一个单列索引。
select xxx from actor where actorid = 1 or filmname = ‘TiTanNic’
mysql 会将这 2 个索引合并,生成并应用这个新的索引 idx_actorid_filmname。但这往往意味着咱们设计的索引并不优,可用思考合并成一个合乎索引 key(actorid, filmname)。
4. 建设适合程序的复合索引
将区分度更高的列放在后面,这样通常是比拟好的准则,因为这样能过滤掉更多的列。换句话说,就是计算候选列的值散布,值散布数量越多,区分度也就越高,应该把它放在后面。能够用如下的 sql 计算各个列的区分度。
select count(distinct col1)/count(*) as discrimination1,
count(distinct col2)/count(*) as discrimination2,
count(*) from A;
5. 防备某些非凡值导致的索引列性能慢
这里的非凡值,比方利用的管理员,游客用户,这些列值往往领有的记录数很大,从而区分度很小,应用索引查问时简直不能过滤掉行数。这种案例的解决办法,通常能够在应用程序端做非凡解决,辨别出这种非凡值,禁止这种非凡值直接参与查问。
汇集索引
汇集索引实际上并不是一种索引类型,而是一种数据存储形式。汇集索引指的是数据行和索引键值严密地寄存在一起,索引键值的程序大小和数据行的程序大小统一。一个表只能有 1 个汇集索引,默认是主键列作为汇集索引。如果没有定义主键,InnoDB 会抉择一个惟一的非空索引代替。如果也没有这样的索引,InnoDB 会隐式地创立一个主键来作为汇集索引。
汇集索引的长处:
1. 能够将相干数据保留在一起。比方电子邮箱的表,能够依据用户 ID 来汇集数据,这样只须要从磁盘读取少许的数据页就能获取某个用户的所有邮件。如果是非汇集索引,则每封邮件都可能导致一次磁盘 I /O。
2. 访问速度更快。索引和数据保留在同一个 B -Tree 结点中,因而从汇集索引中获取数据比非汇集索引更快。
汇集索引示例图:
一般索引实例图:
笼罩索引
通常索引的工作形式时,先在索引上查找到指标数据的指针,再回表去查问指针指向的数据行。如果咱们要查问的列恰好在索引列中,即被索引列笼罩到了,那么就不须要回表操作了,间接返回索引中的数据即可,这样可能大大晋升性能。