这张桌子的最佳索引&查询?

时间:2012-05-22 15:56:41

标签: sql sqlite

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

该表名为" lexicon"。定义是:

_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&lt; RSET。

提前致谢...

3 个答案:

答案 0 :(得分:3)

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

您可以尝试在lsetrsetfrequency的每个组合上创建索引,以找到最佳情况,但必须然后才能拥有真实数据你的餐桌 - (lsetrsetfrequency
- (rsetlsetfrequency
- (lsetfrequencyrset
- (rsetfrequencylset
- (frequencylsetrset
- (frequencyrsetlset

首先使用frequency的优势在于它已经为您的ORDER BYLIMIT条款做好了准备。

但是,如果词典中的每个单词恰好具有不同的频率,则索引中的第二个和第三个字段将变得毫无价值。 (数据统计数据重要的原因示例。)

哪个字段会最快限制您的记录也很重要。如果lset < x过滤器将设置缩小为原始大小的0.01%,请将该过滤器放在索引中。

但在所有可能的情况下,过滤lset < X and rset > y根本不可能完全索引。

答案 1 :(得分:2)

如果SQLite在这方面表现得与其他DBMS相似,那么你需要一个综合索引......

{lset, rset DESC, frequency DESC}

...按此特定顺序并使用这些特定的DESC条款。

有关升序/降序索引的更多信息,请查看this article


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

(由于群集索引已涵盖所有字段,因此无法为此类索引执行此操作。)

答案 2 :(得分: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)范围的(可能是数千个)行,然后使用filesort来查找具有最高频率的(@Num)字。

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

根据有多少行属于该范围,它可能表现良好也不太好。但我没有看到进一步优化这种查询的简单方法。