【发布时间】:2013-12-03 01:32:11
【问题描述】:
我确定我一定是在做一些愚蠢的事情,但通常情况下我无法弄清楚它是什么。
我正在尝试运行此查询:
SELECT `f`.`FrenchWord`, `f`.`Pronunciation`, `e`.`EnglishWord`
FROM (`FrenchWords` f)
INNER JOIN `FrenchEnglishMappings` m ON `m`.`FrenchForeignKey`=`f`.`id`
INNER JOIN `EnglishWords` e ON `e`.`id`=`m`.`EnglishForeignKey`
WHERE `f`.`Pronunciation` = '[whatever]';
当我运行它时,发生的事情对我来说似乎很奇怪。我得到了很好的查询结果,大约 0.002 秒内有 2 行。
但是,我的 CPU 也出现了巨大的峰值,SHOW PROCESSLIST 显示该查询的两个相同进程,状态为“复制到磁盘上的 tmp 表”。这些似乎一直在无休止地运行,直到我杀死它们或系统冻结。
所涉及的表都不大 - 每个表在 100k 到 600k 行之间。 tmp_table_size 和 max_heap_table_size 都是 16777216。
编辑:EXPLAIN 上的声明给出:
+edit 将发音的 keylen 缩减为 112
+----+-------------+-------+--------+-------------------------------------------------------------+-----------------+---------+----------------------------+------+----------------------------------------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+-------------+-------+--------+-------------------------------------------------------------+-----------------+---------+----------------------------+------+----------------------------------------------+
| 1 | SIMPLE | f | ref | PRIMARY,Pronunciation | Pronunciation | 112 | const | 2 | Using where; Using temporary; Using filesort |
| 1 | SIMPLE | m | ref | tmpindex,CombinedIndex,FrenchForeignKey,EnglishForeignKey | tmpindex | 4 | dict.f.id | 1 | Using index |
| 1 | SIMPLE | e | eq_ref | PRIMARY,id | PRIMARY | 4 | dict.m.EnglishForeignKey | 1 | |
+----+-------------+-------+--------+-------------------------------------------------------------+-----------------+---------+----------------------------+------+----------------------------------------------+
如果有人能指出可能导致这种情况的原因,我将不胜感激。 我真正不明白的是 MySQL 正在做什么 - 如果查询完成,那么它肯定不需要做任何其他事情?
更新
感谢所有回复。我从他们所有人身上学到了一些东西。在听从 nrathaus 的建议后,这个查询大大加快了。我向包含 unhex( md5 ( Pronunciation ) ) 的 FrenchWords 添加了一个 PronunciationHash binary(16) 列。使用 16 的 keylen 进行索引(而 Pronunciation 上的 varchar 索引为 600+),现在查询速度要快得多。
【问题讨论】:
-
你的索引是什么?您是否尝试过在此语句中使用说明?
-
谢谢。 FrenchWord、Pronunciation、EnglishWord、FrenchForeignKey、EnglishForeignKey 的索引。 FrenchWords 和 EnglishWords 上的 id 是主要的。编辑后的答案包括解释。
-
在没有任何聚合函数的情况下,您对 GROUP BY 子句的使用显得不合适。
-
我使用
GROUP BY因为FrenchWord 在该表中不是唯一的,在这种情况下,我只想查看每个FrenchWord 一次(其他时候他们需要根据其他列分开。我应该以不同的方式处理?
标签: mysql sql codeigniter join sql-order-by