2012-02-21 3 views
3

내가 MySQL의에 절하지 최적화하기 위해 노력했다 : sent_question 테이블과 word 테이블 사이에 관계가 없습니다최적화 MySQL의 NOT 임시 변수

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); 

: 나는 다음과 같은 쿼리에서 결국 어떻게 일부 . 또한 색인을 correct_option_word_id에 둘 수 없습니다.

누군가가 설명해주십시오.이 방법으로도 쿼리를 최적화 할 수 있습니까?

업데이트 : here과 같이 NOT IN과 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 | 
+----+--------------------+---------------+------+-------------------------+-------------------------+---------+-------+------+-------------+ 
+0

'sent_question'과'word' 사이에 관계가 있습니까? 원래 검색어는 무엇입니까? –

+0

@MarcusAdams'sent_question' 테이블과'word' 테이블 사이에 관계가 없습니다. 또한'correct_option_word_id'에 인덱스를 둘 수 없습니다. –

+0

원본 쿼리에 대해'EXPLAIN' 결과를 보여주십시오. –

답변

1

을 시도해보십시오 모두 NOT INLEFT JOIN/IS NULL 방법은 equally efficient은, 그러나, 불행하게도, 더 빠른 옵션이 없습니다 있습니다, 느린 것 (NOT EXISTS).

아시다시피
SELECT * 
FROM word 
    WHERE 
    word_id NOT IN (SELECT correct_option_word_id FROM sent_question WHERE msisdn='abc') 

는, MySQL은 먼저 하위 쿼리를 수행하고 NOT IN 절에 설정된 반환 된 결과를 사용합니다 :

여기에 간단한 쿼리가 있습니다. 그런 다음 word에있는 모든 행을 검색하여 word_id이 각 행의 목록에 있는지 확인합니다.

이 경우 불행히도 색인은 포괄적이며 배타적이지 않습니다. 그들은 NOT 쿼리에 도움이되지 않습니다. A covering index on word은 잠재적으로 여전히 실제 테이블에 액세스하지 못하게하고 IO 혜택을 제공하지만 기존의 "조회"의미에서는 사용되지 않습니다. 그러나 word 테이블의 모든 열을 반환하므로 큰 인덱스를 가질 수 없습니다.

여기에서 사용되는 가장 중요한 색인은 서브 쿼리에 대한 sent_question.msisdn의 색인입니다. 해당 색인이 정의되어 있는지 확인하십시오. (msisdn, correct_option_word_id)에있는 다중 열 "포괄"색인이 가장 좋을 것입니다.

디자인을 공유하는 경우 최적화를위한 디자인 솔루션을 제공 할 수 있습니다.

+0

원본 '최대 최적화'쿼리에 대한 설명 결과를 추가했습니다. –

+0

@ djaqeel, 고마워, 나는 나의 대답을 더 많은 정보로 업데이트했다. 귀하의 질의에 심각한 오류는 없지만 커버 인덱스가 도움이 될 수 있습니다. –

+0

설명해 주셔서 감사합니다. 나는 "당신이 언급 한 것과 같이 내 쿼리가 정확히 끝났음을 알았습니다."라고 물어 보려고합니다. 나는 어딘가에서 NOT IN 절의 하위 쿼리가 모든 행에 대해 실행된다는 것을 읽습니다. 사실입니까? –

0

나는 그것이 전혀 작동합니다 의심한다.

SELECT * 
FROM word AS w 
LEFT JOIN sent_question AS sq 
ON w.word_id = sq.correct_option_word_id AND sq.msisdn='abc' 
WHERE sq.correct_option_word_id IS NULL 
0

당신은 그 권리에있어이 간단한 쿼리가

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