我有一个必须尽快运行的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。
提前致谢...
答案 0 :(得分:3)
这将取决于您的数据统计数据。
您可以尝试在lset
,rset
和frequency
的每个组合上创建索引,以找到最佳情况,但必须然后才能拥有真实数据你的餐桌
- (lset
,rset
,frequency
)
- (rset
,lset
,frequency
)
- (lset
,frequency
,rset
)
- (rset
,frequency
,lset
)
- (frequency
,lset
,rset
)
- (frequency
,rset
,lset
)
首先使用frequency
的优势在于它已经为您的ORDER BY
和LIMIT
条款做好了准备。
但是,如果词典中的每个单词恰好具有不同的频率,则索引中的第二个和第三个字段将变得毫无价值。 (数据统计数据重要的原因示例。)
哪个字段会最快限制您的记录也很重要。如果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是否会在每个实例上达到最佳指数。
根据有多少行属于该范围,它可能表现良好也不太好。但我没有看到进一步优化这种查询的简单方法。