1

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

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

查询本身(无论WHERE子句中的 fk 数量如何)需要 0.04 秒才能运行,相对于我所有其他需要大约 0.0003 秒的查询来说,这是一个很长的时间。我EXPLAIN QUERY PLAN反对上述声明并收到以下内容:

# | selectid | order | from | detail 
1   0   0   0   SCAN TABLE kd2_character AS kd2c USING INTEGER PRIMARY KEY (~1000000 rows)
2   0   1   1   SEARCH TABLE krad_components AS kcom USING COVERING INDEX idx_krad_components (kanji_fk=? AND radical_fk=?) (~9 rows)
3   0   0   0   EXECUTE LIST SUBQUERY 1
4   0   0   0   USE TEMP B-TREE FOR ORDER BY

我很确定脚本需要很长时间,因为最初的SCAN TABLE. 如果是这样,我该如何摆脱它?我认为创建索引kd2_characer.id会有所帮助,但它对执行时间没有任何明显影响。

如何改进此查询?有没有更好的方法来构建 my GROUP BY,因为它可能是SCAN?

4

1 回答 1

0

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

对于这个特定的查询,SQLite 估计kd2_character在循环中使用 as the outer table 更快(因为您有一个单一的索引可用于在kanji_fkradical_fk列中进行查找)。这可能是真的,也可能不是。

尝试运行一次ANALYZE以获得更准确的估计。

您可以使用CROSS JOIN强制 SQLite 使用特定的连接顺序;检查这是否有所不同:

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

(如果数据库的内容最终会发生变化,从而使另一个连接顺序更快,那么这种优化是危险的。)

于 2013-09-17T06:46:02.803 回答