索引是存储引擎用于快速找到记录的一种数据结构。索引优化是对查询性能优化的最有效手段。索引能够轻易将查询性能提高几个数量级。创建一个最优的索引经常需要重写查询。

5.1索引基础

在MySQL中,存储引擎首先在索引中找到对应值,然后根据匹配的索引记录找到对应的数据行。

索引可以包含一个或多个列的值。如果索引包含多个列,那么列的顺序也十分重要,因为MySQL只能高效地使用索引的最左前缀列。

5.1.1索引的类型

索引有很多类型,可以为不同的场景提供更好的性能。在MySQL中,索引是在储存引擎层而不是服务器层实现的。

B-Tree索引:B-Tree通常意味着所有的值都是按顺序储存的,并且每一个叶子页到根的距离相同。

储存引擎以不同的方式使用B-Tree索引,性能也各有不同,各有优劣。MyISAM使用前缀压缩技术使得索引更小,但InnoDB则按照原数据格式进行储存。MyISAM索引通过数据的物理位置引用被索引的行,而InnoDB则根据主键引用被索引的行。

B-Tree对索引是顺序组织存储的,所以很适合查找范围数据。

B-Tree索引适用于全键值、键值范围或键前缀查找。其中键前缀查找只适用于根据最左前缀的查找。

可以使用B-Tree索引的查询类型:

全值匹配:指的是和索引中所有的列进行匹配。

匹配最左前缀:只使用索引的第一列。

匹配列前缀:也可以匹配某一列的开头部分。

匹配范围值:也只使用了索引的第一列。

精确匹配某一列并范围匹配另外一列:即第一列全匹配,第二列范围匹配。

只访问索引的查询:即查询只需要访问索引,而无须访问数据行。

因为索引树中的节点是有序的,所以除了按值查找之外,还可以用于查询中的ORDER BY操作。

下面是一些关于B-Tree索引的限制:

如果不是按照索引的最左列进行查找,则无法使用索引。

不能跳过索引中的列。

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

所以索引列的顺序非常重要,在优化性能的时候,可能需要使用相同的列但顺序不同的索引来满足不同类型的查询需求。

哈希索引(hash index): 基于哈希表实现,只有精确匹配索引所有列的查询才有效。对于每一行数据,存储引擎都会对所有的索引列计算一个哈希码(hash code),哈希码是一个较小的值,并且不同键值的行计算出的哈希码也不一样。哈希索引将所有的哈希码存储在索引中,同时在哈希表中保存指向每个数据行的指针。

在MySQL中,只有Memory引擎显式支持哈希索引。如果多个列的哈希值相同,索引会以链表的方式存放多个记录指针到同一个哈希条目中。

因为哈希索引只需要存储对应的哈希值,所以索引的结构十分紧凑,这也让哈希索引查找的速度非常快。

哈希索引的限制:

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

哈希索引无法用于排序。

哈希索引也不支持部分索引列匹配查找,因为哈希索引始终是使用索引列的全部内容计算哈希值的。例如在数据列 (A,B)上建立哈希索引,如果查询只有数据列A,则无法使用该索引。

哈希索引只支持等值比较查询,包括 =, IN(), <=>(注意<>和<=>是不同的操作)。也不支持任何范围查询。

访问哈希索引的数据非常快,除非有很多哈希冲突(不同的索引列却有相同的哈希值)。

如果哈希冲突很多的话,一些索引维护操作的代价也会很高。

因为这些限制,哈希索引只适用于某些特定的场合。而一旦适合哈希索引,则它带来的性能提升将非常显著。

创建自定义哈希索引:如果存储引擎不支持哈希索引,则可以创建自定义的哈希索引。

思路很简单:在B-Tree上创建一个伪哈希索引。这和真正的哈希索引不是一回事,因为还是使用B-Tree进行查找,但是它使用哈希值而不是键本身进行索引查找。需要做的就是在查询的WHERE子句中手动指定使用哈希函数,可以使用CRC32做哈希,不要使用SHA1()和MD5()作为哈希函数(因为这两个函数计算出来的哈希值是非常长的字符串,会浪费大量空间,比较时也会比较慢)。

如果数据表非常大,CRC32()会出现大量的哈希冲突(当索引有93000条记录时出现冲突的概率是1%),则可以考虑自己实现一个简单的64位哈希函数,对这个函数的要求是返回整数。一个简单的办法是可以使用MD5()函数返回值的一部分作为自定义哈希函数,还可以使用如FNV64()函数作为哈希函数,这是移植自Percona Server 的函数,可以以插件的方式在任何MySQL版本中使用,生成的哈希值是64位,速度快,且冲突比CRC32()要少得多。

处理哈希冲突:当使用哈希索引进行查询时,必须在WHERE子句中包含常量值,例如:

mysql>SELECt id FROM url WHERE url_ctc = CRC32("http://www.mysql.com") AND url="http://www.mysql.com";

5.2索引的优点

最常见的B-Tree索引,按照顺序存储数据,所以MySQL可以用来做ORDER BY和GROUP BY操作。因为数据是有序的,所以B-Tree也就会将相关的列值都存储在一起。最后,因为索引中存储了实际列的值,所以某些查询只使用索引就能够完成全部查询。

三大优点:

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

2. 索引可以帮助服务器避免排序和临时表

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

总的来说,只有当索引帮助存储引擎快速地找到记录带来的好处大于其带来的额外工作时,索引才是有效的。对于非常小的表,大部分情况下简单的全表扫描更高效。对于中到大型的表,索引就非常有效。但对于特大型的表,建立和使用索引的代价将随之增长。

5.3高性能的索引策略

5.3.1独立的列

如果查询中的列不是独立的,则MySQL就不会使用索引。“独立的列”是指索引的列不能是表达式的一部分,也不是函数的参数。

mysql>SELECT actor_id FROM sakila.actor WHERE actor_id + 1 =5;

mysql>SELECt ... WHERE TO_DAYS(CURRENT_DATE) - TO_DAY(date_col) <= 10;

5.3.2前缀索引和索引选择性

有时候需要索引很长的字符列,这会让索引变得大且慢。一个策略是前面提到过的模拟哈希索引。但有时候这样做还不够,通常可以索引开始的部分字符,这样可以大大节约索引空间,从而提高索引效率,但这样会降低索引的选择性。索引的选择性是指,不重复的索引值(也称为基数,cardinality)和数据表的记录总数(#T)的比值,范围从1/#T到1之间。索引的选择性越高则查询效率越高。唯一索引的选择性是1,这是最好的索引选择性,性能是最好的。

5.3.3多列索引

一个常见错误就是,为每个列创建独立索引,或者按照错误的顺序创建多列索引。

在多个列上创建索引大部分情况下并不能提高MySQL的查询性能。

例如,表film_actor在字段film_id和actor_id上各有一个单列索引。但对于下面的查询,这两个单列索引都不是好的选择:

mysql>SELECT film_id,actor_id FROM sakila.film_actor

->WHERE actor_id = 1 OR film_id = 1;

在MySQL 5.0 和更新的版本中,查询能同时使用这两个单列索引进行扫描,并将结果进行合并。这种算法有三个变种:OR条件的联合(union),AND条件的相交(intersection),组合前两种情况的联合和相交。通过EXPLAIN中的Extra可以看到这一点:

mysql>EXPLAIN SELECT film_id,actor_id FROM sakila.film_actor

->WHERE actor_id = 1 OR film_id = 1\G;

********************1. row****************************

...

...

Extra: Using union(PRIMARY,idx_fk_film_id),Using where

索引合并策略有时候是一种优化的结果,但实际上更多时候说明表上的索引建得很糟糕。

当出现服务器对多个索引做相交操作时(通常有多个AND条件),通常意味着需要一个包含所有相关列的多列索引,而不是多个独立的单列索引。

当服务器需要多个索引做联合操作时(通常有多个OR操作),通常需要耗费大量的CPU和内存资源在算法的缓存、排序和合并操作上。

(未完待续)

如果您觉得阅读本文对您有帮助,欢迎转载本文,但是转载文章之后必须在文章页面明显位置保留此段声明,否则保留追究法律责任的权利。

mysql fnv算法_《高性能MySQL》读书笔记之创建高性能的索引相关推荐

  1. mysql join 算法_【MySQL】之join算法详解

    在阿里巴巴的java开发手册有这么一条强制规定:超过三个表禁止join,需要join的字段,数据类型保持绝对一致,多表关联查询时,要保证被关联的字段需要有索引. 为什么尽量避免使用join?如果使用j ...

  2. 《增强现实:原理、算法与应用》读书笔记(5)运动恢复结构(上)初始化、相机位姿估计、集束调整

    <增强现实:原理.算法与应用>读书笔记(5)运动恢复结构(上)初始化.相机位姿估计.集束调整 运动恢复结构(SfM)是一种从运动的相机拍摄的图像或视频序列中自动地恢复出相机运动轨迹以及场景 ...

  3. 《增强现实:原理、算法与应用》读书笔记(1)基础矩阵、本质矩阵与单应性矩阵

    <增强现实:原理.算法与应用>读书笔记(1) 入坑增强现实,学长让我先把这本书看懂,看了一小半,确实有很多对数学要求挺高的地方,所以打算写个读书笔记,分享一些体会. 第三章:实景的三维结构 ...

  4. 《增强现实:原理、算法与应用》读书笔记(10)视觉惯性SLAM

    <增强现实:原理.算法与应用>读书笔记(10)视觉惯性SLAM 单目视觉SLAM系统存在一定的局限性,它非常依赖相机的成像质量,在图像质量不佳的时候则难以正常工作.即使图像质量很好,缺乏尺 ...

  5. 《增强现实:原理、算法与应用》读书笔记(7)稠密深度估计

    <增强现实:原理.算法与应用>读书笔记(7)稠密深度估计 增强现实技术除了要恢复相机参数和场景的稀疏结构,有时候为了更好地处理遮挡关系和合成阴影,还需要恢复出场景的稠密三维结构.因此,稠密 ...

  6. Spring读书笔记——bean创建(下)

    有关Spring加载bean系列,今天这是最后一篇了,主要接上篇对于从Spring容器中获取Bean的一些细节实现的补充. <Spring读书笔记--bean加载>--Spring如何加载 ...

  7. mysql数据库算法_数据库:MySQL索引背后的数据结构及算法原理【转】

    原文:http://blog.codinglabs.org/articles/theory-of-mysql-index.html 摘要 本文以MySQL数据库为研究对象,讨论与数据库索引相关的一些话 ...

  8. 《Mysql》必知必会读书笔记

    Mysql知识汇总 1.基本操作知识: 用root用户登录:mysql -u root -p; 创建数据库:create database bank(库名); 退出:quit; 创建用户gp,并赋予b ...

  9. 《MySQL是怎么运行的》读书笔记

    MySQL是怎样运行的 第一章 初识MySQL 总结 第二章 MySQL启动选项和系统变量 总结 第三章 字符集与比较规则(排序规则) 总结 第四章 InnoDB记录的存储结构 总结 第五章 Inno ...

最新文章

  1. 入职第一天,老板竟然让我优化5亿数据量,要凉凉?
  2. python3 sys.stdin.readline input 区别
  3. EditPlus正则表达式
  4. Flutter Dart 安装在window系统
  5. 一个Quake2的世界浏览器DEMO(附源码)
  6. 7怎么把中文改为英文_windows10系统英文版本,如何更改为中文版本
  7. python读写磁盘扇区数据_C++-如何直接读取Windows磁盘扇区的数据?
  8. shiro框架的学习
  9. Webpack 5 配置手册(从0开始)
  10. oracle时间差转换成小时分钟,oracle 时间差 具体到天:小时:分
  11. java两个数最大公约数和最小公倍数_java中请给出例子程序:找出两个数的最大公约数和最小公倍数...
  12. 本科生毕业论文(设计)撰写规范
  13. 对不起,我被裁员了。
  14. 【Linux】VirtualBox设置静态ip
  15. 获取中国节假日信息api
  16. nodeBB项目开发中遇到的错误(nodeBB系列二)
  17. PPT在线转换成视频的步骤
  18. 最小生成树 | Prim算法 Kruskal算法 |C语言
  19. 面向对象三大特性(继承)
  20. I2C 专题(一)I2C 简介

热门文章

  1. python整数类型-Python整数类型(int)详解
  2. python手册中文版apk-用 Python 完成 Android apk 的编译打包
  3. python语言属于-python属于哪种语言
  4. python趣味编程10例-Python趣味编程100题
  5. python安装numpy-python及numpy安装
  6. 在python中、下列代码的输出是什么-python期末考试试题汇总
  7. python怎么学最快-人工智能Python开发怎么学才能最快入门
  8. python 语言-python是一门什么样的语言?
  9. hdu1.3.4 排序
  10. synchronize和lock的区别 synchionzie与volatile的区别