MySQL
성능 튜닝
수색…
통사론
동일한 SELECT에서 DISTINCT와 GROUP BY를 사용하지 마십시오.
OFFSET을 통해 페이지 매김을하지 마십시오. "중단 한 부분을 기억하십시오."
WHERE (a, b) = (22,33)은 전혀 최적화되지 않습니다.
UNION 뒤에 ALL 또는 DISTINCT를 명시 적으로 말하면 - 더 빠 른 ALL 또는 느린 DISTINCT 중에서 선택하십시오.
SELECT *를 사용하지 마십시오. 특히 필요하지 않은 TEXT 또는 BLOB 열이있는 경우. tmp 테이블과 전송에 오버 헤드가 있습니다.
GROUP BY와 ORDER BY가 정확히 같은 목록을 가질 수있을 때 더 빠릅니다.
FORCE INDEX를 사용하지 마십시오. 그것은 오늘 도움이 될지 모르지만, 아마 내일 다치게 할 것입니다.
비고
ORDER BY, LIKE, REGEXP 등에 관한 토론을 참조하십시오. 참고 : 링크 및 기타 주제로 편집해야합니다.
올바른 색인 추가
이것은 거대한 주제이지만, 가장 중요한 "성과"문제이기도합니다.
초보자를위한 주된 교훈은 "복합"색인을 배우는 것입니다. 다음은 간단한 예입니다.
INDEX(last_name, first_name)
다음과 같이 우수합니다.
WHERE last_name = '...'
WHERE first_name = '...' AND last_name = '...' -- (order in WHERE does not matter)
그러나를 위해 아닙니다
WHERE first_name = '...' -- order in INDEX _does_ matter
WHERE last_name = '...' OR first_name = '...' -- "OR" is a killer
캐시를 올바르게 설정하십시오.
innodb_buffer_pool_size
는 사용 가능한 RAM의 약 70 % 여야합니다.
비효율적 인 구조는 피하십시오.
x IN ( SELECT ... )
JOIN
으로 변신하다
가능한 경우 OR
피하십시오.
WHERE DATE(x) = ...
와 같은 함수에서 인덱스 된 열을 '숨기지 마십시오.'; WHERE x = ...
로 재 공식화 WHERE x = ...
일반적으로 적합한 데이터 정렬을 사용하여 WHERE LCASE(name1) = LCASE(name2)
를 피할 수 있습니다.
"페이지 설정"에 OFFSET
을 사용하지 말고 대신 '중단 한 부분을 기억하십시오'.
SELECT * ...
피하십시오 (디버깅하지 않는 한).
Maria Deleva, Barranka, Batsu에 대한 참고 사항 : 이것은 장소 소유자입니다. 전체 예제를 빌드 할 때 이러한 항목을 제거하십시오. 당신이 할 수있는 것들을 해본 후에 나는 나머지 부분을 정교하게 그리고 / 또는 던질 것입니다.
제외 어
다음은 실적 향상에 도움이되지 않는 몇 가지 사항입니다. 오래된 정보 및 / 또는 순진함에서 비롯된 것입니다.
- InnoDB는 MyISAM이 더 좋을 것 같지 않은 지점으로 개선되었습니다.
-
PARTITIONing
은 성능상의 이점을 거의 제공하지 않습니다. 그것은 심지어 성능을 해칠 수 있습니다. - 설정
query_cache_size
보다 큰 1 억 것은 일반적으로 성능이 저하됩니다. -
my.cnf
에서 값을 많이 늘리면 '스와핑'이 발생할 수 있습니다. 이는 심각한 성능 문제입니다. - "접두어 인덱스"(예 :
INDEX(foo(20))
)는 일반적으로 쓸모가 없습니다. -
OPTIMIZE TABLE
은 거의 쓸모가 없습니다. (그리고 그것은 테이블을 잠그는 것을 포함한다.)
색인 있음
작은 테이블이 아닌 쿼리의 속도를 높이는 가장 중요한 방법은 적절한 인덱스를 만드는 것입니다.
WHERE a = 12 --> INDEX(a)
WHERE a > 12 --> INDEX(a)
WHERE a = 12 AND b > 78 --> INDEX(a,b) is more useful than INDEX(b,a)
WHERE a > 12 AND b > 78 --> INDEX(a) or INDEX(b); no way to handle both ranges
ORDER BY x --> INDEX(x)
ORDER BY x, y --> INDEX(x,y) in that order
ORDER BY x DESC, y ASC --> No index helps - because of mixing ASC and DESC
기능을 숨기지 마십시오.
일반적인 실수는 함수 호출 내에서 인덱싱 된 열을 숨기는 것입니다. 예를 들어, 이것은 인덱스에서 도움을받을 수 없습니다.
WHERE DATE(dt) = '2000-01-01'
대신 INDEX(dt)
주어지면 INDEX(dt)
사용할 수 있습니다.
WHERE dt = '2000-01-01' -- if `dt` is datatype `DATE`
이것은 DATE
, DATETIME
, TIMESTAMP
및 심지어 DATETIME(6)
(마이크로 초) 동안 작동합니다.
WHERE dt >= '2000-01-01'
AND dt < '2000-01-01' + INTERVAL 1 DAY
또는
일반적으로 OR
최적화를 죽입니다.
WHERE a = 12 OR b = 78
INDEX(a,b)
사용할 수 없으며 "인덱스 병합"을 통해 INDEX(a), INDEX(b)
를 사용하거나 사용하지 않을 수 있습니다. 인덱스 병합은 아무 것도없는 것보다 낫지 만 간신히.
WHERE x = 3 OR x = 5
로 바뀌다
WHERE x IN (3, 5)
그 안에 x
가있는 색인을 사용할 수 있습니다.
하위 쿼리
하위 쿼리는 여러 가지 형식으로 제공되며 최적화 가능성이 다릅니다. 먼저, 하위 쿼리는 "상관 관계"또는 "상관 관계 없음"중 하나 일 수 있습니다. 상관 관계 란 서브 쿼리 외부의 값에 의존한다는 의미입니다. 이것은 일반적으로 각 외부 값에 대해 하위 쿼리 를 다시 평가 해야 함을 의미합니다.
이 상관 관계가있는 부질의는 종종 꽤 좋다. 참고 : 최대 1 개의 값을 반환해야합니다. LEFT JOIN
보다는 반드시 빠르지는 않지만 대체로 유용합니다.
SELECT a, b, ( SELECT ... FROM t WHERE t.x = u.x ) AS c
FROM u ...
SELECT a, b, ( SELECT MAX(x) ... ) AS c
FROM u ...
SELECT a, b, ( SELECT x FROM t ORDER BY ... LIMIT 1 ) AS c
FROM u ...
이것은 일반적으로 상관 관계가 없습니다.
SELECT ...
FROM ( SELECT ... ) AS a
JOIN b ON ...
FROM-SELECT
에 관한주의 사항 :
- 1 행을 반환하면 좋습니다.
- 좋은 패러다임 (다시 "1 row")은 하위 쿼리가
( SELECT @n := 0 )
, 나머지 변수 나 쿼리에서 사용할 @variable을 초기화하는 것입니다. - 그것은 많은 행을 반환하고이 경우
JOIN
도( SELECT ... )
많은 행이 다음 효율성은 끔찍한 될 수 있습니다. 5.6 이전에는 색인이 없었기 때문에CROSS JOIN
이되었습니다. 5.6+는 임시 테이블에서 최상의 인덱스를 추론 한 다음 생성하여SELECT
끝내면 버립니다.
JOIN + GROUP BY
비효율적 인 쿼리로 이어지는 일반적인 문제는 다음과 같이됩니다.
SELECT ...
FROM a
JOIN b ON ...
WHERE ...
GROUP BY a.id
먼저 JOIN
은 행 수를 확장합니다. GROUP BY
그것을 a
의 행 수만큼 되 돌린다.
이 폭발 - 함몰 문제를 해결하기위한 좋은 선택은 없을 것입니다. 한 가지 가능한 옵션은 JOIN
을 SELECT
의 상관 된 하위 쿼리로 변환하는 것입니다. 이것은 또한 GROUP BY
제거합니다.