【发布时间】:2020-11-13 16:05:56
【问题描述】:
我最近将一个复杂的查询重写为带有子查询的 CTE 查询,部分原因是为了了解有关窗口函数的更多信息。新的很慢;对于只有几千行的索引表,在快速硬件上大约需要 0.5 秒。我不确定如何解释EXPLAIN;它似乎表明,正如我所料,没有多少行并且有索引。我需要在这里做什么?
这是在 MySQL 上运行的;这个查询是由 SQLAlchemy 生成的,但我最初是用 SQL 手工编写了它的核心,然后才将它移植过来。这样做的目的是在单词列表中查找附近的单词,并排除相关主题。
WITH rowlist AS (
SELECT
word.id AS id,
word.word AS word,
word.part_of_speech AS part_of_speech,
row_number() OVER (
ORDER BY
word.stripped_word,
(
SELECT
min(quotations.date) AS min_1
FROM
quotations
WHERE
quotations.word_id = word.id
)
) AS rownumber
FROM
word
WHERE
word.deleted IS NULL
AND NOT (
EXISTS (
SELECT
1
FROM
word_subject AS word_subject_1,
word_subject
WHERE
word_subject_1.word_id = word.id
AND word_subject_1.subject_id = 12
)
)
)
SELECT
rowlist.rownumber AS rowlist_rownumber
FROM
rowlist
WHERE
rowlist.id = 392
EXPLAIN 是:
*************************** 1. row ***************************
id: 1
select_type: PRIMARY
table: <derived2>
type: ALL
possible_keys: NULL
key: NULL
key_len: NULL
ref: NULL
rows: 1543
Extra: Using where
*************************** 2. row ***************************
id: 2
select_type: DERIVED
table: word
type: ref
possible_keys: deleted
key: deleted
key_len: 6
ref: const
rows: 1543
Extra: Using index condition; Using where; Using temporary
*************************** 3. row ***************************
id: 4
select_type: MATERIALIZED
table: word_subject_1
type: ref
possible_keys: word_id,subject_id
key: subject_id
key_len: 4
ref: const
rows: 503
Extra: Using index
*************************** 4. row ***************************
id: 4
select_type: MATERIALIZED
table: word_subject
type: index
possible_keys: NULL
key: word_id
key_len: 8
ref: NULL
rows: 2415
Extra: Using index; Using join buffer (flat, BNL join)
*************************** 5. row ***************************
id: 3
select_type: DEPENDENT SUBQUERY
table: quotations
type: ref
possible_keys: word_id
key: word_id
key_len: 5
ref: db.word.id
rows: 4
Extra:
5 rows in set (0.001 sec)
【问题讨论】:
-
样本数据、期望的结果和对逻辑的解释会有所帮助。
order by中窗口函数的子查询是非常不正统的。 -
此数据库保存 OED 风格词典的记录,其中每个单词都有_many 引用。此查询的目的是生成围绕特定单词的单词列表。单词的顺序是按字母顺序排列的(“stripped_word”是标准化为小写且没有标点符号/空格的单词),如果单词相同,则按报价表中最早的报价,因此是原始 order_by 中的子查询。
标签: mysql sql query-optimization common-table-expression