索引让我失望-我如何优化这个SQLite查询?

索引让我失望-我如何优化这个SQLite查询?,sqlite,Sqlite,我需要一些帮助来优化以下查询: SELECT kd2c.id as _id, kd2c.literal as kanji FROM kd2_character as kd2c JOIN krad_components as kcom ON kcom.kanji_fk = kd2c.id WHERE kcom.radical_fk IN (1, 2, 3, etc...) GROUP BY kd2c.id HAVING count(distinct kcom.radical_fk) = <n

我需要一些帮助来优化以下查询:

SELECT
kd2c.id as _id,
kd2c.literal as kanji
FROM
kd2_character as kd2c
JOIN krad_components as kcom ON kcom.kanji_fk = kd2c.id
WHERE kcom.radical_fk IN (1, 2, 3, etc...)
GROUP BY kd2c.id HAVING count(distinct kcom.radical_fk) = <number of integers in WHERE clause>
ORDER BY kd2c.freq IS NULL ASC, kd2c.freq, kd2c.id
我敢肯定,由于最初的
扫描表
,脚本需要很长时间。如果是这样的话,我怎样才能摆脱它呢?我原以为在
kd2_characer.id
上创建索引会有所帮助,但对执行时间没有任何明显的影响


如何改进此查询?是否有更好的方法按组织我的
组,因为它可能是
扫描的源?

当SQLite连接两个表时,它使用嵌套循环连接,即它遍历一个表的所有记录,并在另一个表中查找相应的记录。 如果第一个表的许多记录在必须联接之前被某个
WHERE
条件过滤掉,并且如果第二个表的联接列上有索引,则这会更快

对于这个特定的查询,SQLite估计使用
kd2_character
作为循环中的外部表更快(因为您有一个索引,可以用于
kanji_fk
radial_fk
列中的查找)。 这可能是真的,也可能不是真的

试着跑一次以获得更准确的估计

您可以通过使用强制SQLite使用特定的联接顺序;检查这是否有区别:

...
FROM krad_components AS kcom
CROSS JOIN kd2_character AS kd2c ON kcom.kanji_fk = kd2c.id
WHERE ...

(如果数据库的内容最终发生更改,从而使其他连接顺序更快,则此优化是危险的。)

连接更改为
交叉连接对执行时间没有明显影响-唯一更改的是额外的“使用临时B树进行分组”<我在整个数据库上运行了
ANALYZE`。就像你说的,“(~1000000行)”变成了更准确的“(~13108行)”。感谢您指出这一点,了解更现实的数字更有用。一些进一步的测试表明,正是顺序造成了经济放缓。我用
kd2_character.id
kd2_character.freq
创建了一个新索引,但查询仍然需要使用B树进行排序。
...
FROM krad_components AS kcom
CROSS JOIN kd2_character AS kd2c ON kcom.kanji_fk = kd2c.id
WHERE ...