最近大佬优化了一条SQL,讲100万条的数据查询速度从27s降低到了0.8S,因此研究了下MySQL优化的原理和方式。下面将从Mysql中索引的本质,原理等方面介绍下MySQL中的索引原理。
1、MySQL中数据的存储方式;
mysql的数据在磁盘上的存储:
A、数据块:
由多个磁盘block组成的块,存储引擎负责管理数据块。
磁盘是block块设备,数据在磁盘上的存放也是按照块存放的。
mysql读取表到内存的时候,也必然是按照一块一块的方式读取。假设 要查询的表在和其他表在都在同一个块内。加载块的时候除了读取要查询的表,其他表也一并被读取出来。
当一个块内的部分表被删除时,这是就是形成了碎片。这样会降低装载到内存的速度。
所以会生成一个块头,记录一个快内表的大小,有无空闲空间,空闲空间的位置。
B、散列文件组织:
人为将表分成多个部分,每个部分称为桶。根据行中的某个或某些字段做使用散列函数做哈希运算,运算结果属于某个范围的放在指定的桶中。多个桶组成一个表。
桶有可能溢出。所以要选定一个合适散列函数,让行平均在各个桶中。
2、什么是MySQL的索引;
引用块内容
MySQL官方对索引的定义为:索引(Index)是帮助MySQL高效获取数据的数据结构。我们可以简单理解为:快速查找排好序的一种数据结构。Mysql索引主要有两种结构:B+Tree索引和Hash索引。我们平常所说的索引,如果没有特别指明,一般都是指B树结构组织的索引(B+Tree索引)。索引也是一种数据,需要占用物理空间。B+Tree索引索引的数据结构如图所示:
3、MySQL中索引【hash和BTree】的实现原理;
……等我研究下两种算法再确定。
4、两种索引【hash和BTree】的区别和缺点;
一、BTree
BTree索引是最常用的mysql数据库索引算法,因为它不仅可以被用在=,>,>=,<,<=和between这些比较操作符上,而且还可以用于like操作符,只要它的查询条件是一个不以通配符开头的常量,例如:
select from user where name like ‘jack%’;
select from user where name like ‘jac%k%’;
如果一通配符开头,或者没有使用常量,则不会使用索引,例如:
select from user where name like ‘%jack’;
select from user where name like simply_name;
二、Hash
Hash索引只能用于对等比较,例如=,<=>(相当于=)操作符。由于是一次定位数据,不像BTree索引需要从根节点到枝节点,最后才能访问到页节点这样多次IO访问,所以检索效率远高于BTree索引。
但为什么我们使用BTree比使用Hash多呢?主要Hash本身由于其特殊性,也带来了很多限制和弊端:
- Hash索引仅仅能满足“=”,“IN”,“<=>”查询,不能使用范围查询。
- 联合索引中,Hash索引不能利用部分索引键查询。
对于联合索引中的多个列,Hash是要么全部使用,要么全部不使用,并不支持BTree支持的联合索引的最优前缀,也就是联合索引的前面一个或几个索引键进行查询时,Hash索引无法被利用。- Hash索引无法避免数据的排序操作
由于Hash索引中存放的是经过Hash计算之后的Hash值,而且Hash值的大小关系并不一定和Hash运算前的键值完全一样,所以数据库无法利用索引的数据来避免任何排序运算。- Hash索引任何时候都不能避免表扫描
Hash索引是将索引键通过Hash运算之后,将Hash运算结果的Hash值和所对应的行指针信息存放于一个Hash表中,由于不同索引键存在相同Hash值,所以即使满足某个Hash键值的数据的记录条数,也无法从Hash索引中直接完成查询,还是要通过访问表中的实际数据进行比较,并得到相应的结果。- Hash索引遇到大量Hash值相等的情况后性能并不一定会比BTree高
对于选择性比较低的索引键,如果创建Hash索引,那么将会存在大量记录指针信息存于同一个Hash值相关联。这样要定位某一条记录时就会非常麻烦,会浪费多次表数据访问,而造成整体性能底下。
5、参考文章。
1、 mysql之mysql数据在磁盘的储存方式
2、索引的优缺点
3、什么是索引?Mysql目前主要的几种索引类型
4、MySQL的索引是什么?怎么优化?
5、深入理解MySQL索引原理和实现——为什么索引可以加速查询?
6、数据库索引系列四:索引算法Hash与BTree的区别
7、MySQL优化原理