MySQL索引

MySQL索引-背后的数据结构和算法


摘要

MySQL支持诸多存储引擎,当时各种存储引擎对索引的支持也是不相同的,所以MySQL是支持多种索引类型的,BTree索引,哈希索引,全文索引,这里专注与BTree索引

第一部分数据结构和算法Mysql索引的数理基础

第二部分结合MyISAM和Inno引擎讨论聚集索引、非聚集索引及覆盖索引

第三部分最大索引性能

 

第一部分

索引是什么

MySQL官方对索引的定义:索引(Index)是帮助MySQL高效获取数据的数据结构

数据库最基本的功能是什么,数据库查询。我们都希望查询的速度越快越好,所以设计者会优化查询算法。大家都学过不少的查询算法,但是我们都知道不同的查询算法所依赖的条件是不一样的,它们基于不同的数据结构。

最容易想到的一种方法是顺序查找(linear search),时间复杂度O(n)。这个办法在处理大数据的时候是很差劲的,耗时太长。随着计算机科学的发展,有更多基于特定数据结构的优秀的查找算法出现了。

二分查找(被检索数据要求有序),二叉树查找(基于二叉查找树)。

但是数据本身的组织结构不可能完全满足各种数据结构(例如,理论上不可能同时将两列都按顺序进行组织),所以,在数据之外,数据库系统还维护着满足特定查找算法的数据结构,这些数据结构以某种方式引用(指向)数据,这样就可以在这些数据结构上实现高级查找算法。这种数据结构,就是索引。

磁盘IO与预读

简单介绍一下磁盘IO和预读,磁盘读取数据靠的是机械运动,每次读取数据花费的时间可以分为寻道时间、旋转延迟、传输时间三个部分,寻道时间指的是磁臂移动到指定磁道所需要的时间,主流磁盘一般在5ms以下;旋转延迟就是我们经常听说的磁盘转速,比如一个磁盘7200转,表示每分钟能转7200次,也就是说1秒钟能转120次,旋转延迟就是1/120/2 = 4.17ms;传输时间指的是从磁盘读出或将数据写入磁盘的时间,一般在零点几毫秒,相对于前两个时间可以忽略不计。那么访问一次磁盘的时间,即一次磁盘IO的时间约等于5+4.17 = 9ms左右,听起来还挺不错的,但要知道一台500 -MIPS的机器每秒可以执行5亿条指令,因为指令依靠的是电的性质,换句话说执行一次IO的时间可以执行40万条指令,数据库动辄十万百万乃至千万级数据,每次9毫秒的时间,显然是个灾难。

磁盘IO是非常高昂的操作,计算机操作系统做了一些优化,当一次IO时,不光把当前磁盘地址的数据,而是把相邻的数据也都读取到内存缓冲区内,因为局部预读性原理告诉我们,当计算机访问一个地址的数据的时候,与其相邻的数据也会很快被访问到。每一次IO读取的数据我们称之为一页(page)。具体一页有多大数据跟操作系统有关,一般为4k或8k,也就是我们读取一页内的数据时候,实际上才发生了一次IO

任何一种数据结构都不是凭空产生的,一定会有它的背景和使用场景,我们现在所需要的这个数据结构是要用来干嘛。每次查找数据时把磁盘IO次数控制在一个很小的数量级,最好是常数数量级。

那为什么不用搜索树呢?lgN的时间复杂度很不错啊,复杂度模型是基于每次相同的操作成本来考虑的,数据库实现比较复杂,数据保存在磁盘上,而为了提高性能,每次又可以把部分数据读入内存来计算,因为我们知道访问磁盘的成本大概是访问内存的十万倍左右,所以简单的搜索树这里是不适用的。

原文地址:https://www.cnblogs.com/QuixoteY/p/10848932.html