Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/sql/79.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Sql 此表的最佳索引&;查询_Sql_Sqlite - Fatal编程技术网

Sql 此表的最佳索引&;查询

Sql 此表的最佳索引&;查询,sql,sqlite,Sql,Sqlite,我有一个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 ? 从lexic

我有一个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 ?

从lexicon WHERE lset>中选择单词、频率?而rset如果SQLite在这方面的行为与其他DBMS类似,那么您将需要在

{lset, rset DESC, frequency DESC}
…按此特定顺序和这些特定的
DESC
子句

请查看以获取有关升序/降序索引的更多信息


是的,正如@DanielRenshaw所提到的,您可以在索引末尾包含
word
,纯粹是为了允许。这就是所谓的“覆盖”指数


(因为聚类索引已经覆盖了所有字段,所以对于这样一个索引来说,这样做没有任何意义。)

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

您可以尝试在
lset
rset
frequency
的每个组合上创建索引,以找到最佳情况,但您必须在表中有真实数据。
-(
lset
rset
频率

-(
rset
lset
频率

-(
lset
frequency
rset

-(
rset
frequency
lset

-(
frequency
lset
rset

-(
frequency
rset
lset

拥有
频率
的优势在于,它已经为您的
订购依据
限制
条款做好了准备

但是如果你词典中的每个单词的频率都不一样,那么索引中的第二个和第三个字段就会变得一文不值。(一个说明数据统计为何重要的示例。)

它还关系到哪个字段将限制您最快的记录。如果
lset
过滤器将集合缩小为原始大小的
0.01%
,请将该过滤器放在索引的第一位

但很有可能,过滤
lsety
根本不可能很好地索引。

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

它将使用索引识别属于
(@LeftSide,@RightSide)
范围的行(可能有数千行),然后使用文件排序查找频率最高的(@Num)字

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


根据该范围内的行数,它的性能可能会从好到不好。但我认为没有一种简单的方法可以进一步优化这种查询

和往常一样,这要看情况了!在这种情况下,
lset
rset
谓词的选择性至关重要。仅
lset>?
就可能返回比
rsetGreat问题更多或更少的记录数。我应该提到lset和rset是表示树结构的嵌套集值。因此,lset和rset的所有值都是相互唯一的,并且在1-2*N的范围内完美地分布(其中N是表中的行数)。@Barry:你(也)的意思是,以下内容总是正确的吗?:
lset@ypercube:在任何给定的行中,是的。实际上,lset(lset,rset)
组合是
唯一的
?值得注意的是,如果Sqlite的行为与其他DBMS类似,添加
word
作为索引中的最后一列将使索引覆盖所有必需字段,并避免在其他地方查找该列。如果这个索引将表聚集在一起,这将没有帮助。@DanielRenshaw-同意。查找不在索引中的数据字段类似于添加额外的联接<编码>在索引上加入索引blah JOIN theIndex.PK=theTable.PK上的表
。因此,在索引中包含必要的字段可以消除此开销。(除了在聚集索引中,表是索引。)@Dems我不确定SQLite是否支持这一点,但在“大”DBMS中,您可以混合索引组件的“方向”,所以
lset>?及rset@BrankoDimitrijevic-没错。但它仍然没有人们所希望的那么有帮助。例如,假设
lset
rset
都是从
0
99
的整数。
lset=0
的索引项下面将有100个
rset
项。对于通过搜索条件的每个
lset
(平均50%,天真吗?),需要另一个索引查找来检查
rset
谓词(1个lset查找,50个rset查找)。它的效果不如
lset>x和lset
。特别是当考虑到
lset
rset
可能具有大量合法价值时。非常感谢您的回复。我只是在我的问题中添加了一些原本应该包含的额外信息(对不起)。该表表示树结构,lset/rset是嵌套集对,因此:1。在任何给定的行中,lsetThanks用于查询优化。我现在明白了,rset并不是真正必要的。我按照您的建议更新了查询并为表编制了索引,但仍然不够快。正如你所做的那样,我怀疑它无法进一步优化。好消息:我使用了错误的索引(列的顺序错误),正确排列后,查询速度提高了5-10倍。我想现在它已经足够快了@巴里:我在dba.se上发布了一个相关问题:。请随意关注并在那里发表评论。
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
(lset, frequency, word)