数据库索引允许查询从数据库中有效地检索数据。索引与特定的表有关,并且由一个或多个键组成,一个表可以有多个索引。键是我们要在索引中查找的值的花哨术语。键的取值基于表里的列(字段)。通过将键与索引进行比较,可以找到一个或多个具有相同值的数据库记录。
由于索引极大地加快了数据检索的速度,因此为每个表定义正确的索引至关重要。对于小型数据库,丢失索引不会引起注意,但是请放心,一旦表的数据量增加,查询所需的时间就会更长。
索引的力量
我曾经在一个数据库上工作,该数据库需要大约八天的时间才能完成一系列操作。通过查看运行时间最长的查询,并通过查询计划生成器运行它们,我们意识到数据库可以从新索引中受益。优化器估计查询成本将从300,000次操作减少到30次!我们实施了该索引,并将整个操作从八天缩短到了两个小时。不用说,我们非常高兴获得性能提升。
示例说明
使用索引最直接的示例就是看书时的索引。使用起来非常简单。只需扫描您感兴趣的主题或章节,记下并翻到书中的对应页面即可。
该索引的关键是我们引用的主题词。索引条目由键和页码组成。键是按字母顺序排列的,这使我们真正轻松地扫描索引,查找条目,记下页面,然后将书翻至正确的页面。
假设有一个替代方案。没有索引的书可能在每页底部列出主题词。使用这种类型的系统,要查找您感兴趣的主题,就必须翻阅整本书。对于上百页的书,这使得查找主题真的很慢!直到书到最后,您可能才能找到想查找的主题。
索引的功能在于,您可以或多或少地直接访问您想要查看的图书页面。实际上,这节省了数小时的页面翻转!
卡片组
假设您有一副52张牌:总共4组花色,每一组从A到K。如果纸牌随机排列,我请您挑选出红心8,为此,您将单独翻动每张纸牌,直到找到这张牌为止。平均而言,您将需要经过一半的牌,即26张牌。
现在,改为考虑将牌按花色分为四堆,每堆随机洗牌。现在,如果我要您挑选出红心8,则首先从4组花色中找到红心,平均需要2次操作,然后从红心花色中翻阅13张牌。平均来说,需要七次翻转才能找到,因此总共需要翻转九次(2+7)。这比仅扫描整副牌要快17次翻转(26-9)。
我们可以更进一步,将各个堆分成两组(一组A到6,另一组7到K)。在这种情况下,平均搜索量将减少到6。
这就是索引的力量。通过对键上的数据进行分离和排序,我们可以使用分组的方法来大大减少查找数据所需的翻转次数。
B +树索引由数据库使用
用于存储数据库索引的结构称为B +树。 B +树的工作方式类似于我们之前提到的卡片分类策略。在B +树中,键值被分为许多较小的堆。顾名思义,这些堆(在技术上称为节点)以树状方式连接。使B +树自从出现之后就一直广泛使用的原因是,对于树中的每个节点,都非常容易与您查询的值进行比较,然后分支到下一个节点。每个枝干的选择都大大减少了您需要扫描的条目数量,实际上搜索的平均次数记录数的指数次数O(log n)。
这样,通过遍历节点,进行比较,就可以仅通过几次简单的节点扫描,从成千上万条记录中找到需要的值。希望此图有助于说明这一想法
在上面的示例中,您需要检索与键值15对应的记录。为此,进行了以下比较:
- 确定15小于40,因此遍历“To Values <40”分支。
- 由于15大于10但小于30,因此遍历“To Values> = 10 and <16 branch”
使用B +树结构,可以在树中表示成千上万条记录,而该树在其分支内的级别相对较少。由于查找次数与树的高度直接相关,因此必须确保所有分支的高度均相等。这样可以将数据分布在整个树上,从而更有效地查找任何范围内的数据。
由于数据会在数据库中不断更新,因此B +树保持平衡非常重要。每次添加,删除或更新键记录时,需要专门的算法将数据和键值从一个块移到另一个块,以确保树的任何一个部分都不比另一个部分高。
Ref: https://www.essentialsql.com/what-is-a-database-index/