支持范围内的子线性查询的数据库

时间:2013-09-18 18:50:41

标签: database

是否存在支持连续值范围内的高效查询/索引的数据库技术?例如,考虑以下数据集

Name      Age
Alice     25
Bob       35
Charlie   26
Diane     39
Edward    19
...       ...

现在想象一下,我想查询二十多岁的所有人的姓名。我可以在许多数据库系统中表达这个查询。是否有任何系统支持这种有效/次线性查询?通过子线性我的意思是它不需要查看表/数据库中的每个条目,但可以通过查看其他一些数据结构来快速选择相关的行。我正在寻找像索引这样的东西,而不是有序和连续的数据。我要过滤的特定有序/连续列的类型为Datetime。

请注意,我不是在寻找解决此问题的查询。我正在寻找一个示例数据库系统,它支持对有序连续数据进行有效(次线性)过滤。

如果不存在这样的系统,我也很乐意了解该领域的研究/论文。

3 个答案:

答案 0 :(得分:2)

如果您的意思是“高效”和“次线性”,如“非全表扫描”,那么任何主要关系数据库都可以在您的列上放置索引时执行此操作。

整数列和时间戳列都可以完全用于此,因为它们的排序非常简单,并且列的宽度是固定的并且很小 - 因此索引非常有效。

由于索引通常是btree索引(或其变体),因此默认情况下会对索引进行排序。范围查询只是意味着:选择适当的子树并完成。使用此条件遍历树是次线性的。

示例:使用PostgreSQL:

> select count(*) from objects;
34215157
Time: 4423,262 ms

> explain select * from objects where objects_pkey between 42 and 42000;
                                 QUERY PLAN                                      
-------------------------------------------------------------------------------------
 Index Scan using objects_pkey on objects  (cost=0.00..1920.84 rows=40292 width=288)
   Index Cond: ((objects_pkey >= 42) AND (objects_pkey <= 42000))

> select count(*) from objects where objects_pkey between 42 and 42000;
 count 
-------
 41959
Time: 15,403 ms

这意味着:表格很大,不适合内存。使用整数列的索引扫描受两个条件(意味着:高效访问)的约束。获取~40k行只需要15ms。

BTW:你要求的这种访问是a)没什么新鲜或令人兴奋的,b)确切地说,这种查询关系数据库的诞生和调整大约有三十年了。

答案 1 :(得分:2)

如果这是一个非常大的数据仓库事实表,其上有一个时间组件,通过它可以有效地查询数据(例如,DATE_OF_SALE),那么常见的实现将是一个分区的关系数据库表那个价值。

在Oracle中,这通常是范围分区,因此我将解决内部实现的方式。

常规未分区表可以被认为是一组列和表元数据(表名,列名和数据类型等)以及存储实际数据的“物理”数据段。全表扫描要求为高水位线下的每个块读取该数据段。

分区将表分成多个段,每个段在逻辑上受约束以保存特定的数据集。这可以是由特定列(分区键)的值列表定义的集合,应用于列的散列函数的结果,或者在这种情况下是列的值范围。

查询优化器检测分区键列上是否存在谓词,并尝试隔离可能包含候选数据的最小分区集。然后可以通过专用于每个分区的索引扫描或访问它们。这称为分区修剪,由于消除了大量数据集,因此可以更快地扫描数据。

在更多工程化系统中,例如Oracle的Exadata,可以有一些结构存储连续数据块的列的最大值和最小值,大小在低兆字节范围内。在这种情况下,对表或分区的完全扫描可以通过消除候选行存在于其中的可能性来消除对这些数据块集的扫描。 Oracle将这些结构称为存储索引。

因此,对Oracle重型方法表示道歉,但其他关系数据库和非关系数据库中存在类似的实现,并且它们可以提供比索引更高的性能。

顺便提一下,索引的一个问题是表的数据没有隐式组织,因此20%的表数据的索引扫描很可能不如数据的完整扫描效率低由于表的数据段重复单块访问。一些RDBMS允许设置行的物理顺序 - PostgreSQL允许通过索引列对表进行聚类,这样就可以按索引的顺序对表进行一次性重写,从而改进基于索引的访问,直到由于添加了新行或更新现有行,数据变得杂乱无章。

答案 2 :(得分:-1)

MySQL是一个可以执行高效查询的数据库系统。例如要让所有人都二十多岁,您可以使用以下查询:
    SELECT Name FROM my_table WHERE年龄介于20和29之间;