以MySQL为例,详解数据库索引原理及深度优化

一、摘要
本文以MySQL数据库为研究对象,讨论与数据库索引相关的一些话题 。特别需要说明的是,MySQL支持诸多存储引擎,而各种存储引擎对索引的支持也各不相同,因此MySQL数据库支持多种索引类型,如BTree索引,哈希索引,全文索引等等 。为了避免混乱,本文将只关注于BTree索引,因为这是平常使用MySQL时主要打交道的索引,至于哈希索引和全文索引本文暂不讨论 。
二、常见的查询算法及数据结构
为什么这里要讲查询算法和数据结构呢?因为之所以要建立索引,其实就是为了构建一种数据结构,可以在上面应用一种高效的查询算法,最终提高数据的查询速度 。
2.1 索引的本质
MySQL官方对索引的定义为:索引(Index)是帮助MySQL高效获取数据的数据结构 。提取句子主干,就可以得到索引的本质:索引是数据结构 。
2.2 常见的查询算法
我们知道,数据库查询是数据库的最主要功能之一 。我们都希望查询数据的速度能尽可能的快,因此数据库系统的设计者会从查询算法的角度进行优化 。那么有哪些查询算法可以使查询速度变得更快呢?
2.2.1 顺序查找(linear search )
最基本的查询算法当然是顺序查找(linear search),也就是对比每个元素的方法,不过这种算法在数据量很大时效率是极低的 。

  • 数据结构:有序或无序队列
  • 复杂度:O(n)
实例代码:
  •  
//顺序查找
int SequenceSearch(int a[], int value, int n)
{
int i;
for(i=0; i<n; i++)
if(a[i]==value)
return i;
return -1;
}
2.2.2 二分查找(binary search)
比顺序查找更快的查询方法应该就是二分查找了,二分查找的原理是查找过程从数组的中间元素开始,如果中间元素正好是要查找的元素,则搜素过程结束;如果某一特定元素大于或者小于中间元素,则在数组大于或小于中间元素的那一半中查找,而且跟开始一样从中间元素开始比较 。如果在某一步骤数组为空,则代表找不到 。
  • 数据结构:有序数组
  • 复杂度:O(logn)
实例代码:
  •  
//二分查找,递归版本
int BinarySearch2(int a[], int value, int low, int high)
{
int mid = low+(high-low)/2;
if(a[mid]==value)
return mid;
if(a[mid]>value)
return BinarySearch2(a, value, low, mid-1);
if(a[mid]<value)
return BinarySearch2(a, value, mid+1, high);
}
2.2.3 二叉排序树查找
二叉排序树的特点是:
  • 若它的左子树不空,则左子树上所有结点的值均小于它的根结点的值;
  • 若它的右子树不空,则右子树上所有结点的值均大于它的根结点的值;
  • 它的左、右子树也分别为二叉排序树 。
搜索的原理:
  • 若b是空树,则搜索失败,否则:
  • 若x等于b的根节点的数据域之值,则查找成功;否则:
  • 若x小于b的根节点的数据域之值,则搜索左子树;否则:
  • 查找右子树 。
  • 数据结构:二叉排序树
  • 时间复杂度:O(log2N)
2.2.4 哈希散列法(哈希表)
其原理是首先根据key值和哈希函数创建一个哈希表(散列表),燃耗根据键值,通过散列函数,定位数据元素位置 。
  • 数据结构:哈希表
  • 时间复杂度:几乎是O(1),取决于产生冲突的多少 。
2.2.5 分块查找
分块查找又称索引顺序查找,它是顺序查找的一种改进方法 。其算法思想是将n个数据元素”按块有序”划分为m块(m ≤ n) 。每一块中的结点不必有序,但块与块之间必须”按块有序”;即第1块中任一元素的关键字都必须小于第2块中任一元素的关键字;而第2块中任一元素又都必须小于第3块中的任一元素,依次类推 。
算法流程:
  1. 先选取各块中的最大关键字构成一个索引表;
  2. 查找分两个部分:先对索引表进行二分查找或顺序查找,以确定待查记录在哪一块中;然后,在已确定的块中用顺序法进行查找 。
这种搜索算法每一次比较都使搜索范围缩小一半 。它们的查询速度就有了很大的提升,复杂度为 。如果稍微分析一下会发现,每种查找算法都只能应用于特定的数据结构之上,例如二分查找要求被检索数据有序,而二叉树查找只能应用于二叉查找树上,但是数据本身的组织结构不可能完全满足各种数据结构(例如,理论上不可能同时将两列都按顺序进行组织),所以,在数据之外,数据库系统还维护着满足特定查找算法的数据结构,这些数据结构以某种方式引用(指向)数据,这样就可以在这些数据结构上实现高级查找算法 。这种数据结构,就是索引 。


推荐阅读