8.2.1.2 MySQL WHERE절 최적화 방법
이 섹션에서는 WHERE
절 처리에서 실행 가능한 최적화에 대해 설명합니다. 예를 들어 SELECT
문을 사용하고 있습니다 만, DELETE
및 UPDATE
문에서 WHERE
절에도 같은 최적화를 적용합니다.
MySQL 최적화 노력은 계속되고 있으므로, MySQL이 실행 최적화 모두를 여기에서 설명하고있는 것은 아닙니다.
가독성을 희생해서 산술 연산을 빠르게하도록 쿼리를 다시 작성하고자 쉽습니다. MySQL은 같은 최적화를 자동으로 실행하기 때문에 많은 경우에이 작업을 피할 수 쿼리를 이해하기 쉽고 유지 보수하기 쉬운 형태로 남겨 둘 수 있습니다. MySQL에 의해 실행되는 최적화의 일부를 보여줍니다.
불필요한 괄호 삭제 :
((a AND b) AND c OR (((a AND b) AND (c AND d)))) -> (a AND b AND c) OR (a AND b AND c AND d)
상수 계산 :
(a <b AND b = c) AND a = 5 -> b> 5 AND b = c AND a = 5
상수 조건 제거 (상수 계산을 위해 필요합니다) :
(B> = 5 AND B = 5) OR (B = 6 AND 5 = 5) OR (B = 7 AND 5 = 6) -> B = 5 OR B = 6
인덱스에서 사용되는 상수 표현은 한 번만 계산됩니다.
WHERE
를 사용하지 않는 단일 테이블의COUNT(*)
는MyISAM
테이블과MEMORY
테이블의 테이블 정보에서 직접 검색됩니다. 이것은 하나의 테이블로 사용 된 경우NOT NULL
식으로도 실행됩니다.잘못된 정수식의 조기 탐지. MySQL은 일부
SELECT
문을 실행 불가능하다는 것을 신속하게 감지하고 행을 반환하지 않습니다.GROUP BY
또는 집계 함수 (COUNT()
,MIN()
등)를 사용하지 않으면HAVING
은WHERE
와 병합됩니다.결합의 각 테이블에 대해 테이블의 빠른
WHERE
평가를하고 가능한 한 빨리 줄을 건너 뛰려면 더 단순한WHERE
이 구축됩니다.쿼리 내의 다른 모든 테이블의 전에 먼저 모든 상수 테이블을 읽습니다. 상수 테이블은 다음 중 하나입니다.
빈 테이블 또는 행의 테이블.
PRIMARY KEY
또는UNIQUE
인덱스의WHERE
절에서 사용되는 테이블. 여기에서 모든 인덱스 부분이 상수 식과 비교되고NOT NULL
로 정의됩니다.
다음 테이블은 모든 상수 테이블로 사용됩니다.
SELECT * FROM T WHERE
primary_key
= 1; SELECT * FROM t1, t2 WHERE t1.primary_key
= 1 AND t2.primary_key
= t1.id;테이블을 결합하는 최적의 결합의 조합은 모든 가능성을 시도하여 찾을 수 있습니다.
ORDER BY
와GROUP BY
절의 모든 컬럼이 동일한 테이블에있는 경우 결합 할 때 먼저 해당 테이블이 선택됩니다.ORDER BY
절과 다른GROUP BY
절이있는 경우 또는ORDER BY
또는GROUP BY
에 결합 큐의 첫 번째 테이블과 다른 테이블의 컬럼이 포함되어있는 경우, 임시 테이블이 만들어집니다.SQL_SMALL_RESULT
옵션을 사용하면 MySQL에서는 인 메모리 임시 테이블이 사용됩니다.최적화가 테이블 스캔을 사용하는 것이 더 효율적이라고 판단하지 않는 한, 각 테이블 인덱스가 쿼리 된 최적의 인덱스가 사용됩니다. 일단 스캔은 최적의 인덱스가 테이블의 30 % 이상에 걸쳐 여부에 따라 사용되고있었습니다 만, 고정 비율에 따라 인덱스를 사용하거나 스캔을 사용할지의 선택이 결정됩니다 없어졌습니다. 현재 최적화는 복잡하고 테이블 크기, 줄, I / O 블록 크기 등의 추가 요인에 따라 추정합니다.
경우에 따라 MySQL은 데이터 파일을 참조하지 않고 인덱스에서 행을 읽을 수 있습니다. 인덱스에서 사용하는 모든 컬럼이 숫자 인 경우 쿼리의 해결에 인덱스 트리 만 사용됩니다.
각 행이 출력되기 전에
HAVING
절에 맞지 않는 것은 생략됩니다.
매우 빠른 쿼리의 몇 가지 예 :
SELECT COUNT (*) FROMtbl_name
; SELECT MIN (key_part1
), MAX (key_part1
) FROMtbl_name
; SELECT MAX (key_part2
) FROMtbl_name
WHEREkey_part1
=constant
; SELECT ... FROMtbl_name
ORDER BYkey_part1
,key_part2
, ... LIMIT 10; SELECT ... FROMtbl_name
ORDER BYkey_part1
DESC,key_part2
DESC ... LIMIT 10;
MySQL은 인덱스 설정된 컬럼이 수치이기 때문에 인덱스 트리만을 사용하여 다음 쿼리를 해결합니다.
SELECTkey_part1
,key_part2
FROMtbl_name
WHEREkey_part1
=val
; SELECT COUNT (*) FROMtbl_name
WHEREkey_part1
=val1
ANDkey_part2
=val2
; SELECTkey_part2
FROMtbl_name
GROUP BYkey_part1
;
다음 쿼리는 개별 정렬 경로를 사용하지 않고 인덱스를 사용하여 정렬 된 순서로 행을 가져옵니다.
SELECT ... FROMtbl_name
ORDER BYkey_part1
,key_part2
, ...; SELECT ... FROMtbl_name
ORDER BYkey_part1
DESC,key_part2
DESC ...;