使用临时变量优化不在查询中的mysql
我试图优化mysql中的NOT IN子句:我在下面的查询中得到了一些结果:使用临时变量优化不在查询中的mysql,mysql,Mysql,我试图优化mysql中的NOT IN子句:我在下面的查询中得到了一些结果: SELECT @i:=(SELECT correct_option_word_id FROM sent_question WHERE msisdn='abc'); SELECT * FROM word WHERE @i IS NULL OR word_id NOT IN (@i); sent\u question表和word表之间没有关系。而且我不能将索引放在正确选项\u word\u id上 有人能解释一下,这种方
SELECT @i:=(SELECT correct_option_word_id FROM sent_question WHERE msisdn='abc');
SELECT * FROM word WHERE @i IS NULL OR word_id NOT IN (@i);
sent\u question
表和word
表之间没有关系。而且我不能将索引放在正确选项\u word\u id
上
有人能解释一下,这种方法是否会优化查询
更新:如前所述,notin和LEFT JOIN/IS NULL两种方法的效率几乎相同。这就是为什么我不想使用LEFT-JOIN/IS-NULL方法
更新2:
解释原始查询的结果:
EXPLAIN SELECT * FROM word WHERE word_id NOT IN (SELECT correct_option_word_id FROM sent_question WHERE msisdn='abc');
+----+--------------------+---------------+------+-------------------------+-------------------------+---------+-------+------+-------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+--------------------+---------------+------+-------------------------+-------------------------+---------+-------+------+-------------+
| 1 | PRIMARY | word | ALL | NULL | NULL | NULL | NULL | 10 | Using where |
| 2 | DEPENDENT SUBQUERY | sent_question | ref | fk_question_subscriber1 | fk_question_subscriber1 | 48 | const | 1 | Using where |
+----+--------------------+---------------+------+-------------------------+-------------------------+---------+-------+------+-------------+
我怀疑它会起作用 试一试
尝试一下这个简单的查询
SELECT
sent_question.*,
word.word_id AS foundWord
FROM sent_question
LEFT JOIN word
ON word.word_id = sent_question.correct_option_word_id
WHERE sent_question.msisdn='abc'
// GROUP BY sent_question.correct_option_word_id // This shouldn't be needed but included for completion
HAVING foundWord IS NULL
您是对的,
NOT in
和LEFT JOIN/IS NULL
方法都是空的,但是不幸的是,没有更快的选项,只有较慢的选项(不存在
)
以下是您的查询,简化:
SELECT *
FROM word
WHERE
word_id NOT IN (SELECT correct_option_word_id FROM sent_question WHERE msisdn='abc')
正如您所知,MySQL将首先执行子查询,并为notin
子句使用返回的结果集。然后,它将扫描word
中的所有行,查看每行的列表中是否有word\u id
不幸的是,在这种情况下,索引是包含的,而不是独占的。它们不帮助而不是查询。一个onword
可能仍然可以用来避免访问实际的表,并提供一些IO好处,但它不会用在传统的“查找”意义上。但是,由于您要返回word
表中的所有列,因此可能无法使用如此大的索引
这里使用的最重要的索引是子查询的sent\u question.msisdn
索引。确保已定义该索引。最好在(msisdn,correct\u option\u word\u id)
上使用多列“覆盖”索引
如果您分享您的设计,我们可能会提供一些优化设计解决方案。发送的问题与word
之间有关系吗?原始查询是什么?@MarcusAdams在sent\u question
表和word
表之间没有关系。而且我无法将索引放在正确选项\u word\u id
上。请显示原始查询的解释结果。感谢解释。看起来word
表上根本没有任何索引。有关详细信息,请查看我的更新答案。我已为原始“优化”查询添加了解释结果,请查看。@djaqeel,谢谢,我已用更多信息更新了我的答案。您的查询没有什么严重错误,但是覆盖索引可能会有所帮助。谢谢您的解释。我不敢问“你确定我的问题最终会像你提到的那样结束吗?”?我在某处读到,子查询in NOT in子句对每一行都执行。这是真的吗?如果子查询引用了主查询中的一列,它将对每一行执行。在这种情况下,它不会引用主查询,因此不会对每一行执行。
SELECT *
FROM word
WHERE
word_id NOT IN (SELECT correct_option_word_id FROM sent_question WHERE msisdn='abc')