2

我有一个必须尽快运行的 sqlite 查询。查询相当简单,但我不知道索引表以获得最佳性能的最佳方法。

该表称为“词典”。定义是:

_id integer primary key
word text
frequency integer
lset integer
rset integer

查询是:

SELECT word,frequency FROM lexicon WHERE lset>? AND rset<? ORDER BY frequency DESC LIMIT ?

我已经索引了所有单独的列,但我怀疑复合索引可能更好,但是什么组合呢?lset 和 rset 上的索引应该是升序还是降序?

编辑: lset 和 rset 是表示树结构的嵌套集合值。因此 lset 和 rset 的所有值都是相互唯一的,并且是完美分布的。此外,在任何给定的行中 lset < rset。

提前致谢...

4

3 回答 3

3

这将取决于您的数据统计。

您可以尝试在和的每个组合上创建索引lset以找到最佳情况,但您的表中必须有真实数据。 - ( , , ) - ( , , ) - ( , , ) - ( , , ) - ( , , ) - ( , , ) rsetfrequency
lsetrsetfrequency
rsetlsetfrequency
lsetfrequencyrset
rsetfrequencylset
frequencylsetrset
frequencyrsetlset

拥有 first 的好处frequency是它已经为你的ORDER BYandLIMIT子句做好了准备。

但是,如果您的词典中的每个单词碰巧有不同的频率,那么索引中的第二个和第三个字段将变得毫无价值。 (一个为什么你的数据统计很重要的例子。)

哪个字段将最快地限制您的记录也很重要。如果lset < x过滤器减少了0.01%原始大小的集合,则将该过滤器首先放在索引中。

但很可能,过滤lset < X and rset > y根本不可能很好地索引。

于 2012-05-22T16:04:10.813 回答
2

如果 SQLite 在这方面的行为与其他 DBMS 相似,那么您将需要一个复合索引...

{lset, rset DESC, frequency DESC}

...按照这个特定的顺序和这些特定的DESC条款。

查看这篇文章以获取有关升序/降序索引的更多信息。


是的,正如@DanielRenshaw 提到的,您可以word在索引的末尾包含,纯粹是为了允许index-only scan。这称为“覆盖”索引。

(由于聚簇索引已经涵盖了所有字段,所以没有为这样的索引这样做的目的。)

于 2012-05-22T16:03:37.770 回答
1

您的查询(名称略有变化):

SELECT word,frequency 
FROM lexicon 
WHERE lset > @LeftSide 
  AND rset < @RightSide 
ORDER BY frequency DESC 
LIMIT @Num

您正在使用嵌套集模型,因此可以将其重写为:

SELECT word,frequency 
FROM lexicon 
WHERE lset > @LeftSide          --- both `lset` here
  AND lset < @RightSide         --- and here
ORDER BY frequency DESC 
LIMIT @Num

他们也可以是两者rset。只要您的数据不违反嵌套集模型,两者都将起作用并给出相同的结果。因此,您的查询可能需要 3 列上的覆盖索引:

(lset, frequency, word)

它将使用索引来识别落入该(@LeftSide,@RightSide)范围的(可能数千)行,然后使用文件排序来查找频率最高的(@Num)单词。

在某些情况下,索引(frequency DESC, lset, word)可能会更好(它确实取决于参数值),所以如果您也有该索引,那就太好了。但我无法回答 SQLite 是否会在每个实例上达到最佳索引峰值。

根据落入该范围的行数,它的性能可能会好到不好。但我没有看到一种简单的方法来进一步优化这种查询。

于 2012-05-22T17:42:40.597 回答