我试图用Big-O表示法来理解数据库索引的性能。如果不了解它,我会猜测:
这一般是正确的吗?查询主键会不会比O(1)表现更差?我特别关注SQLite,但我有兴趣了解不同数据库之间的差异程度。
答案 0 :(得分:25)
大多数关系数据库将索引结构化为B树。
如果表具有聚类索引,则数据页将存储为B树的叶节点。从本质上讲,聚类索引就成了表格。
对于没有聚类索引的表,表的数据页存储在堆中。任何非聚集索引都是B树,其中B树的叶节点标识堆中的特定页面。
B树的最坏情况高度为O(log n),并且由于搜索取决于高度,因此B树查找的运行方式类似于(平均值)
O(log t n)
其中t是最小化因子(每个节点必须至少有 t -1个键,最多2 * t * -1个键(例如,2 * t *个子)。
这就是我理解它的方式。
当然,不同的数据库系统可能会使用不同的数据结构。
当然,如果查询不使用索引,则搜索是对包含数据页的堆或B树的迭代。
如果使用的索引可以满足查询,则搜索会便宜一些;否则,需要在内存中获取相应的数据页面。
答案 1 :(得分:5)
索引查询(唯一或不唯一)更典型地是O(log n)。非常简单,你可以认为它类似于排序数组中的二进制搜索。更准确地说,它取决于索引类型。但是,例如,b树搜索仍然是O(log n)。
如果没有索引,那么,是的,它是O(N)。
答案 2 :(得分:2)
如果您选择相同的列,则搜索
如果您需要来自其他“来源”(索引交集,书签/密钥查找等)的信息,因为索引是非覆盖的,那么您可以有O(n + log n)或O(log n + log n + log n)因为多个索引命中+中间排序。
如果统计数据显示您需要高百分比的行(例如,不是非常有选择性的索引),那么索引可能会被忽略并变为scan = O(n)
答案 3 :(得分:2)
其他答案给出了一个很好的起点;但我只想补充一点来获得O(1),主索引本身需要基于哈希(这通常不是默认选择);所以更常见的是对数(B树)。
你是正确的,二级索引通常具有相同的复杂性,但实际性能更差 - 这是因为索引和数据没有聚集,所以常量(磁盘搜索次数)更大。
答案 4 :(得分:2)
这取决于您的查询。
Column = Value
的条件允许使用基于散列的索引,该索引具有O(1)查找时间。但是,many databases, including SQLite, do not support them。<
,>
,<=
,>=
)的条件可以使用有序索引,通常使用二叉树实现,该索引具有O(log n)查找时间。由于您主要对SQLite感兴趣,因此您可能希望阅读其Query Optimizer Overview,其中更详细地解释了如何选择索引。