数据库索引及其 Big-O 表示法
Posted
技术标签:
【中文标题】数据库索引及其 Big-O 表示法【英文标题】:Database indexes and their Big-O notation 【发布时间】:2011-06-09 08:05:35 【问题描述】:我试图用 Big-O 表示法来理解数据库索引的性能。在不了解的情况下,我猜想:
查询主键或唯一索引将为您提供 O(1) 的查找时间。 查询非唯一索引也会给出 O(1) 时间,尽管“1”可能比唯一索引慢 (?) 对没有索引的列进行查询会产生 O(N) 的查找时间(全表扫描)。这通常正确吗?查询主键的性能会比 O(1) 更差吗?我特别关心的是 SQLite,但我也想知道这在不同数据库之间的差异程度。
【问题讨论】:
【参考方案1】:大多数关系数据库将索引构造为 B 树。
如果表有聚簇索引,则数据页存储为 B 树的叶节点。本质上,聚簇索引变成了表。
对于没有聚集索引的表,表的数据页存储在堆中。任何非聚集索引都是 B 树,其中 B 树的叶节点标识堆中的特定页面。
B-tree 的最坏情况高度是 O(log n),由于搜索依赖于高度,B-tree 查找运行在类似(平均而言)
O(logt n)
其中 t 是最小化因子(每个节点必须至少有 t-1 个键和最多 2*t* -1 个键(例如,2*t* 个子节点)。
我是这么理解的。
当然,不同的数据库系统可能在底层使用不同的数据结构。
当然,如果查询不使用索引,那么搜索就是对包含数据页的堆或 B 树的迭代。
如果使用的索引可以满足查询,则搜索会便宜一些;否则,需要后备来获取内存中的相应数据页。
【讨论】:
【参考方案2】:索引查询(唯一或不唯一)通常为 O(log n)。非常简单,您可以将其视为类似于排序数组中的二进制搜索。更准确地说,它取决于索引类型。但是,例如,b-tree 搜索仍然是 O(log n)。
如果没有索引,那么,是的,是O(N)。
【讨论】:
【参考方案3】:如果您选择搜索的相同列,则
Primary 或 Unqiue 将为 O(log n):这是一个 b-tree 搜索 非唯一索引也是 O(log n) + 一点:这是一个 b-tree 搜索 无索引 = O(N)如果您需要来自另一个“来源”(索引交集、书签/键查找等)的信息,因为索引是非覆盖的,那么您可以使用 O(n + log n) 或 O(log n + log n + log n) 因为多次索引命中 + 中间排序。
如果统计数据显示您需要高 % 的行(例如,不是非常有选择性的索引),那么该索引可能会被忽略并变成扫描 = O(n)
【讨论】:
【参考方案4】:其他答案提供了一个很好的起点;但我只想补充一点,要获得 O(1),主索引本身需要基于哈希(这通常不是默认选择);所以更常见的是对数(B-tree)。
您是正确的,二级索引通常具有相同的复杂性,但实际性能更差——这是因为索引和数据没有聚集,因此常数(磁盘搜索次数)更大。
【讨论】:
【参考方案5】:这取决于您的查询是什么。
Column = Value
形式的条件允许使用基于散列的索引,其查找时间为 O(1)。但是,many databases, including SQLite, do not support them。
使用关系运算符(<
、>
、<=
、>=
)的条件可以使用有序索引,通常使用二叉树实现,其查找时间为 O(log n)。
不能使用索引的更复杂的表达式需要 O(n) 时间。
由于您主要对 SQLite 感兴趣,您可能需要阅读它的 Query Optimizer Overview,它更详细地解释了如何选择索引。
【讨论】:
以上是关于数据库索引及其 Big-O 表示法的主要内容,如果未能解决你的问题,请参考以下文章