MySQL에서 WHERE 절의 열 순서가 쿼리 성능에 영향을 줍니까?


38

가능한 결과 집합이 큰 특정 데이터베이스 쿼리에서 성능 문제가 있습니다.

문제의 쿼리 AND, WHERE 절에 세 가지가 있습니다.

조항의 순서가 중요합니까?

마찬가지로 ASI_EVENT_TIME 절을 먼저 넣으면 (절에서 대부분의 결과가 제거되므로).

쿼리에서 런타임이 향상됩니까?

질문:

SELECT DISTINCT  activity_seismo_info.* 
FROM `activity_seismo_info` 
WHERE 
    activity_seismo_info.ASI_ACTIVITY_ID IS NOT NULL  AND 
    activity_seismo_info.ASI_SEISMO_ID IN (43,44,...,259) AND 
    (
        activity_seismo_info.ASI_EVENT_TIME>='2011-03-10 00:00:00' AND 
        activity_seismo_info.ASI_EVENT_TIME<='2011-03-17 23:59:59'
    ) 

ORDER BY activity_seismo_info.ASI_EVENT_TIME DESC

쿼리 설명 :

+----+-------------+---------+-------+---------------------------+--------------+---------+------+-------+-----------------------------+ 
| id | select_type | table   | type  | possible_keys             | key          | key_len | ref  | rows  | Extra                       |
+----+-------------+---------+-------+---------------------------+--------------+---------+------+-------+-----------------------------+ 
|  1 | SIMPLE      | act...o | range | act...o_FI_1,act...o_FI_2 | act...o_FI_1 | 5       | NULL | 65412 | Using where; Using filesort |
+----+-------------+---------+-------+---------------------------+--------------+---------+------+-------+-----------------------------+

사용 :

PHP 5.2

MySQL 5.0.51a-3 우분투 5.4

프로 펠 1.3

심포니 1.2.5


ORDER BY는 아마도 너무 오래 걸린 것일 것입니다. "filesort 사용"은 매우 느릴 수 있습니다. ORDER BY를 사용하는 것보다 응용 프로그램 논리에서 주문을 많이하는 것을 발견했습니다.
maclema

나는이 같은 질문을 스택 오버 플로우에서 잠시 전에 (이 사이트 이전) 물었다. 내가받은 답변에 대한 링크를 확인하십시오. stackoverflow.com/questions/3805863/…
Scott

2
@maclema-응용 프로그램이 데이터베이스보다 훨씬 빠른 컴퓨터에서 실행되지 않는 한 응용 프로그램의 모든 정렬 논리의 무의미한 부담은 말할 것도없고 확실하지 않습니다. order by데이터베이스에 속합니다.
잭 더글러스

답변:


24

난 그렇게 생각하지 않아. 쿼리 최적화 프로그램은 충분히 영리해야합니다.

WHERE 절을 다시 정렬하여 EXPLAINS가 각 경우에 동일한 것을 알려줍니다.


이 쿼리를 최적화하기 위해 수행 할 수있는 작업 : ASI_EVENT_TIME에 인덱스가 있습니까? (이 쿼리를 사용하여 결과를 정렬 할 때이 쿼리에 대해 생각하는 것이 가장 중요합니다).

다른 두 필드 (ASI_SEISMO_ID 및 ASI_ACTIVITY_ID)에 인덱스가 있습니까?

테이블 구조를 게시하면 도움이됩니다.


이벤트 시간의 인덱스를 만들려고 생각한 적이 없습니다. 나는 내일 dev db에서 시도하고 눈에 띄는 차이가 있는지 확인합니다.
Patrick

@Patrick이 인덱스를 사용하는 다른 모든 쿼리가이 날짜를 내림차순으로 정렬한다고 가정하면 인덱스 키 (activity_seismo_info.ASI_EVENT_TIME)도 내림차순으로 정렬하려고합니다.
매트 M

@MattM 나는 당신이 색인 키를 주문할 수 있다는 것을 몰랐다. Awesome 인덱스 키를 주문하면 인덱스 키가없는 것보다 나쁘다는 점과 반대 방향으로 성능 순서를 손상시킬 수 있습니까?
Patrick

@ 패트릭 당신이 맞아요. 제 두뇌는 SQL Server에 갇혀 있습니다. MYSQL에서 정렬 순서를 지정할 수 있으며 구문 분석되지만 무시됩니다. 모든 인덱스는 MYSQL에서 오름차순으로 정렬됩니다. 혼란을 드려 죄송합니다.
매트 M

13

에서 문서 :

테이블에 다중 열 인덱스가 있으면 옵티마이 저가 인덱스의 가장 왼쪽 접두사를 사용하여 행을 찾을 수 있습니다. 예를 들어 (col1, col2, col3)에 3 열 인덱스가있는 경우 (col1), (col1, col2) 및 (col1, col2, col3)에 대한 검색 기능이 색인화됩니다.

열이 색인의 가장 왼쪽 접두사를 형성하지 않으면 MySQL은 색인을 사용할 수 없습니다.

따라서 복합 인덱스 의 열 순서와 동일해야합니다 .


4
테이블 에 왼쪽 열에서 열을 선택 하는 다중 열 인덱스가있는 경우 선택한 순서는 중요하지 않습니다. 따라서 인덱스 a, b, c가 WHERE c = 'foo' AND a = 'bar' AND b = 'foobar'있고 인덱스를 계속 사용할 수있는 경우에 사용할 수 있습니다.
texelate

10

아니, 상관 없어

옵티마이 저는 SQL을 구문 분석 한 직후 간단한 변환을 수행합니다.이 중 하나입니다.


8

푸와 바

와 같은 최적화

어디 바와 푸

하나,

같지 않은 # 1과 같지 않은 # 2가있는 곳

두 부품을 모두 최적화 할 수 없습니다. 예를 들어

1과 3 사이 그리고 b> 17 사이

INDEX (a, b) 또는 INDEX (b, a)를 제대로 사용할 수 없습니다

다르게 표현하기 위해 WHERE 절에서 '='테스트 AND '를 함께 사용한 다음 하나가 아닌'= '(IN, BETWEEN,> 등)를 처리 할 수 ​​있습니다. 하나만 효과적으로 최적화 할 수 없습니다.

귀하의 검색어에는 3 개의 조항이 있습니다.

결과적으로 INDEX (EVENT_TIME)이 가장 유용 할 것입니다. AND 중 하나에 도움이되고 ORDER BY에 대한 "파일 정렬"을 피하는 데 사용될 수 있습니다.

중복 행이 없으면 (도대체 왜 있을까요?) DISTINCT를 제거하십시오. 더 많은 노력이 필요합니다.

성능 관련 질문을 할 때는 SHOW CREATE TABLE 및 SHOW TABLE STATUS를 제공하십시오.

업데이트 ... 최신 버전 (예 : MySQL 5.7)은 경우에 따라 IN( list of constants )거의 같은 방식으로 처리 할 수 ​​있습니다 =. 안전하게 플레이하려면 다음 순서를 따르십시오 (각 부분은 선택 사항 임).

  1. 임의의 수의 =.
  2. 일부 INs.
  3. 최대 하나의 범위.

1

최적화 문서가 말하는 MySQL :

가독성을 높이면서 산술 연산 속도를 높이기 위해 쿼리를 다시 작성하고 싶을 수도 있습니다. 때문에 MySQL은 자동으로 비슷한 최적화를 수행 , 당신은 종종이 일을 피하고,보다 이해하기 쉽고 유지 보수 형태로 쿼리를 남길 수 있습니다. MySQL이 수행하는 일부 최적화는 다음과 같습니다.

  • ...

  • 조인의 각 테이블에 대해 테이블에 대한 빠른 WHERE 평가를 얻고 가능한 한 빨리 행을 건너 뛰 도록 더 간단한 WHERE 가 구성 됩니다 .

  • 옵티마이 저가 테이블 스캔을 사용하는 것이 더 효율적 이라고 생각 하지 않으면 각 테이블 인덱스가 쿼리 되고 최상의 인덱스가 사용 됩니다 . 한 번에, 최상의 인덱스가 테이블의 30 % 이상에 걸쳐 있는지에 따라 스캔이 사용되었지만, 고정 백분율은 더 이상 인덱스 사용 또는 스캔 사용 사이의 선택을 결정하지 않습니다. 옵티마이 저는 이제 더욱 복잡해졌으며 테이블 크기, 행 수 및 I / O 블록 크기와 같은 추가 요소를 기반으로 추정합니다.

이런 식으로 쿼리 최적화 프로그램이 쿼리에서 열을 사용한 HOW 순서를 생략하는 것이 합리적입니다 (MySQL뿐만 아니라 SQL은 선언적 언어 이며 원하는 방식이 아닌 원하는 작업을 수행해야 함).

그러나 쿼리에서 복합 키의 열에 대해 동일한 정렬을 유지하고 싶지만 yii2와 같은 일부 프레임 워크에서 ORM 또는 ActiveRecord를 사용하는 경우 불가피합니다. 관계 기준을 사용자 정의하는 것이 끝에 추가됩니다 "온"조건이지만 여전히 애플리케이션의 다른 부분에있는 QueryBuilders의 기능이 필요합니다.


-2

모든 당신의 WHERE / HAVING 절에서 사용되는 높은 선택성을 가지고있다 필드 (고유 값의 수 / 총 레코드 수> 10 % ~ 20 %) 해야 색인.

따라서 ASI_EVENT_TIME열에 가능한 값이 많은 경우 먼저 색인을 모두 만드십시오. 그런 다음 @ypercube가 말했듯이 다시 정렬하고 EXPLAIN이 알려주는 내용을 확인하십시오. 모두 동일해야합니다.

또한 인덱싱 SQL LIKE 필터를 살펴보십시오 . 대답이 필요한 것은 아니지만 인덱싱이 어떻게 작동하는지에 대해 배우게됩니다.

* 편집 : 색인 작성에 대한 자세한 내용은 주석에서 아래 제공된 링크를 참조하십시오.


8
-1 모든 열을 인덱싱하는 것이 가장 좋은 방법은 아닙니다. 모든 인덱스는 여러 가지 방법으로 비용이 발생합니다. 일반적으로 사용되는 선택성 및 빈도 순서로 여러 열로 구성되는 양호한 색인을 선택해야합니다. 이는 SQL 서버가 기울어 될 수 있지만 인덱스 정보는 여전히 유효 : sqlskills.com/BLOGS/KIMBERLY/post/... .
Eric Humphrey-lotsahelp

@Eric Humphrey +1 Kimberly 사이트에 대한 설명과 링크입니다.
Matt M

: 당신은 종종 선택 쿼리에 대한 성능 상처 컬럼에 인덱스를 가지고, 잘못 mysqlperformanceblog.com/2007/08/28/...을 . 경험 법칙을 사용해서는 안됩니다. 때로는 작동하지만 때로는 작동하지 않습니다.
sumar

맞습니다. 동의합니다. 그러나 이는 값 선택성이 낮은 경우에 유효합니다. Patrick (이 질문 작성자)이 사용하는 데이터 형식 (DATETIME)을 고려하면 인덱싱을 권장합니다. 몇 가지 가능한 날짜 만 사용할 때 이상한 상황이 없으면 일반적으로이 유형의 필드에는 상당히 큰 값 세트가 있습니다. *보다 명확하고 유효한 진술을 위해 위의 답변을 편집하겠습니다.
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.