[SQL] 왜 IN 조건은 SQL에서 "="보다 느린 것입니까?
SQL왜 IN 조건은 SQL에서 "="보다 느린 것입니까?
이 SELECT 쿼리가 마무리 180 초 정도 걸립니다 질문을 확인 (질문 자체에 대한 의견을 확인). IN은 하나의 값과 비교 될 수 있지만, 여전히 시간 차이는 엄청나 다. 왜 그렇게입니까?
해결법
-
==============================
1.요약 :이 MySQL의에서 알려진 문제와 MySQL의 5.6.x.에 고정 IN을 사용하여 하위 쿼리가 잘못 따라 하위 쿼리 대신 독립적 인 하위 쿼리로 indentified 때 문제로 인해 누락 최적화하는 것입니다.
요약 :이 MySQL의에서 알려진 문제와 MySQL의 5.6.x.에 고정 IN을 사용하여 하위 쿼리가 잘못 따라 하위 쿼리 대신 독립적 인 하위 쿼리로 indentified 때 문제로 인해 누락 최적화하는 것입니다.
원래 쿼리에 EXPLAIN 실행할 때이 반환합니다 :
1 'PRIMARY' 'question_law_version' 'ALL' '' '' '' '' 10148 'Using where' 2 'DEPENDENT SUBQUERY' 'question_law_version' 'ALL' '' '' '' '' 10148 'Using where' 3 'DEPENDENT SUBQUERY' 'question_law' 'ALL' '' '' '' '' 10040 'Using where'
당신이 투표를 변경 = 때 당신이 얻을 :
1 'PRIMARY' 'question_law_version' 'ALL' '' '' '' '' 10148 'Using where' 2 'SUBQUERY' 'question_law_version' 'ALL' '' '' '' '' 10148 'Using where' 3 'SUBQUERY' 'question_law' 'ALL' '' '' '' '' 10040 'Using where'
이에 포함 된 쿼리의 행에 한 번 서브 쿼리는 한 번만 실행되는 반면, 각 따라 하위 쿼리가 실행됩니다. MySQL을 할 수 때로는 최적화 따라 하위 쿼리 경우가 아니라 그 여기에 가입 변환 할 수 있지만 조건이있다.
지금 이것은 물론 잎의 MySQL이 생각하는 이유의 문제는 IN 버전은 종속 서브 쿼리 할 필요가있다. 나는 도움에 쿼리의 단순화 된 버전이 조사를 만들었습니다. 나는 두 테이블 'foo는'와 (내가 외래 키 제약 조건을 생성하지 않았지만) 전자는 단지 id 컬럼을 포함하고, 후자는 ID와 푸 ID가 모두 포함 '줄'을 만들었습니다. 그럼 1000 개 행이 두 테이블을 채워 :
CREATE TABLE foo (id INT PRIMARY KEY NOT NULL); CREATE TABLE bar (id INT PRIMARY KEY, foo_id INT NOT NULL); -- populate tables with 1000 rows in each SELECT id FROM foo WHERE id IN ( SELECT MAX(foo_id) FROM bar );
이 간단한 쿼리는 이전과 같은 문제가있다 - 내부 선택이 종속 하위 쿼리로 취급되고 더 최적화 행에 한 번 실행되도록 내부 쿼리를 일으키는 원인이 수행되지 않습니다. 쿼리를 실행하는 데 거의 1 초 걸립니다. =에 IN을 변경하면 다시 쿼리가 거의 즉시 실행할 수 있습니다.
나는 테이블을 채우는 데 사용되는 코드는 경우에 사람이 결과를 재현하고자, 다음과 같습니다.
CREATE TABLE filler ( id INT NOT NULL PRIMARY KEY AUTO_INCREMENT ) ENGINE=Memory; DELIMITER $$ CREATE PROCEDURE prc_filler(cnt INT) BEGIN DECLARE _cnt INT; SET _cnt = 1; WHILE _cnt <= cnt DO INSERT INTO filler SELECT _cnt; SET _cnt = _cnt + 1; END WHILE; END $$ DELIMITER ; CALL prc_filler(1000); INSERT foo SELECT id FROM filler; INSERT bar SELECT id, id FROM filler;
-
==============================
2.= 대 NOT IN에 대해, 조인 대 그것은 하위 쿼리 a.k.a 내부 쿼리에 관하여, 개미 이유는 해당 게시물에서 설명합니다. MySQL의 버전 5.4은보다 효율적인 형태로 일부 하위 쿼리를 다시 작성할 수 있습니다 향상된 최적화를 소개 suppposed된다.
= 대 NOT IN에 대해, 조인 대 그것은 하위 쿼리 a.k.a 내부 쿼리에 관하여, 개미 이유는 해당 게시물에서 설명합니다. MySQL의 버전 5.4은보다 효율적인 형태로 일부 하위 쿼리를 다시 작성할 수 있습니다 향상된 최적화를 소개 suppposed된다.
당신이 할 수있는 최악의 일은, 소위 상관 하위 쿼리를 사용하는 것입니다 http://dev.mysql.com/doc/refman/5.1/en/correlated-subqueries.html
-
==============================
3.SQL 최적화는 항상 당신이 그 (것)들을 할 기대하지 않습니다. 나는 확실히 그보다 더 좋은 대답은 거기에 있지 않다. 당신이 계획 출력을 EXPLAIN 검토해야하고, 시간이 소요되는 곳을 찾기 위해 쿼리를 프로파일하는 이유입니다.
SQL 최적화는 항상 당신이 그 (것)들을 할 기대하지 않습니다. 나는 확실히 그보다 더 좋은 대답은 거기에 있지 않다. 당신이 계획 출력을 EXPLAIN 검토해야하고, 시간이 소요되는 곳을 찾기 위해 쿼리를 프로파일하는 이유입니다.
-
==============================
4.그것은 흥미로운하지만 문제는 준비된 문으로 해결 될 수있다 (확실하지가 모두 적합한 경우), 예컨대 :
그것은 흥미로운하지만 문제는 준비된 문으로 해결 될 수있다 (확실하지가 모두 적합한 경우), 예컨대 :
mysql> EXPLAIN SELECT * FROM words WHERE word IN (SELECT word FROM phrase_words); +----+--------------------+--------------+... | id | select_type | table |... +----+--------------------+--------------+... | 1 | PRIMARY | words |... | 2 | DEPENDENT SUBQUERY | phrase_words |... +----+--------------------+--------------+... mysql> EXPLAIN SELECT * FROM words WHERE word IN ('twist','rollers'); +----+-------------+-------+... | id | select_type | table |... +----+-------------+-------+... | 1 | SIMPLE | words |... +----+-------------+-------+...
그러니 그냥 다음을 실행, 저장 프로 시저의 문을 준비합니다. 여기에 아이디어는 :
SET @words = (SELECT GROUP_CONCAT(word SEPARATOR '\',\'') FROM phrase_words); SET @words = CONCAT("'", @words, "'"); SET @query = CONCAT("SELECT * FROM words WHERE word IN (", @words, ");"; PREPARE q FROM @query; EXECUTE q;
from https://stackoverflow.com/questions/3417074/why-would-an-in-condition-be-slower-than-in-sql by cc-by-sa and MIT license
'SQL' 카테고리의 다른 글
[SQL] COUNT (*) 대 수 (1) 대 수 (PK) : 더 나은 무엇입니까? [복제] (0) | 2020.03.16 |
---|---|
[SQL] SQL 쿼리와 가까운 위도 / 경도 찾기 (0) | 2020.03.16 |
[SQL] 어떻게 두 테이블에 MySQL에 합류? (0) | 2020.03.16 |
[SQL] 다중 부분 식별자는 바인딩 수 없습니다 (0) | 2020.03.15 |
[SQL] 오라클 SQL에서 날짜 비교 (0) | 2020.03.15 |