Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/mysql/60.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
使用临时变量优化不在查询中的mysql_Mysql - Fatal编程技术网

使用临时变量优化不在查询中的mysql

使用临时变量优化不在查询中的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上 有人能解释一下,这种方

我试图优化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

有人能解释一下,这种方法是否会优化查询

更新:如前所述,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

不幸的是,在这种情况下,索引是包含的,而不是独占的。它们不帮助
而不是
查询。一个on
word
可能仍然可以用来避免访问实际的表,并提供一些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')