b

7.4 SELECT ( 7.4.1 SELECT 처리순서 ~ 7.4.2 GROUP BY, ORDER BY) 본문

RealMysql

7.4 SELECT ( 7.4.1 SELECT 처리순서 ~ 7.4.2 GROUP BY, ORDER BY)

dev.bistro 2012. 12. 9. 16:23


7.4 SELECT  


7.4.1 SELECT의 처리 순서

 1) 대부분의 처리 순서  - 드라이빙 테이블 - 드리븐 테이블1 - 드리븐 테이블2  - GROUP BY - DISTINCT - HAVING - ORDER BY - LIMIT


 2) 아주 예외적인  - 드라이빙 테이블 - ORDER BY - 드리븐 테이블1 - 드리븐 테이블2 - LIMIT

    (첫 테이블 읽어, 오더링 후 나머지 테이블을 읽는 경우로, 주로 GROUP BY없이 ORDER BY만 사용된 쿼리에서 볼 수 있다)


 3) 이외의 처리 순서가 필요하다면, 서브 쿼리를 사용해야 한다. (LIMIT를 GROUP BY 전에 실행 하는것처럼, 하지만 임시 테이블이 사용되므로 주의할 것)


7.4.2 GROUp BY, ORDER BY의 인덱스 사용

  1) 기본 규칙 

   a) 인덱스 컬럼의 값 자체를 변환하지 않고 그대로 사용 (인덱스는 값을 B-tree에 정렬해서 저장하기 때문)

      SELECT * FROM salaries WHERE salary * 10 > 15000 은 인덱스를 이용하지 못하는 사례이다.

   =>SELECT * FROM salaries WHERE salary > 1500으로 변경하면 인덱스를 이용할 수 있는 최적의 사례이다.

   이렇게 튜닝이 힘들땐, 미리 계산된 값을 컬럼에 추가하고 그 칼럼에 인덱스를 생성하는 것이 좋다. 


   b) type이 일치해야 한다. (암시적인 형 변환이 아닌, 명시적으로 일치해야한다)

     문자열 비교보다, 숫자의 비교가 빨라서 mySQL 옵티마이저는 숫자 타입에 우선권을 부여한다. 

     varchar age , where age = 2 => type:index 풀 인덱스

     int age, where age = '2'  => type:ref, 인덱스 사용 (옵티마이저의 효과!)



 2) WHERE절의 인덱스 사용

   WHERE 절에서 각 조건이 명시된 순서는 중요하지 않고, 그 칼럼에대한 조건이 있는지 없는지가 더 중요하다.-and로만 이용될때이다.(5.3.7, B-tree참조)

   A='value1' or B='value2'는 옵티마이저는 풀 스캔을 이용 할 것이다. (A에 인덱스, B는 인덱스 없고)

   (풀 스캔+인덱스 레인지 스캔) 보다는 (풀 스캔) 1번이 더 빠르기 때문이다. 

   A='value1' and B='value2' 였다면 A의 인덱스를 이용 했을 것이다.



 3) GROUP BY절의 인덱스 사용

   * GROUP BY 절의 명시된 칼럼의 순서가 인덱스 구성 칼럼 순서와 같으면 GROUP BY 절은 인덱스를 사용할 수 있다.

   * GROUP BY절에 명시된 컬럼중 하나라도 인덱스에 없으면 전혀 인덱스를 이용 할 수 없다.

   * 인덱스 뒤쪽의 컬럼이 GROUP BY에 없어도 사용가능하지만, 인덱스 앞에 있는 칼럼이 GROUP BY에 없다면 사용 불가.

     예제)     인덱스 : C1, C2, C3, C4     GROUP BY : C1, C2, C3

    인덱스를 이용하지 못하는 경우

      GROUP BY C2, C1 (순서 불일치)

      GROUP BY C1, C3, C2 (순서 불일치)

      GROUP BY C1, C3 (COL2가 GROUP BY에서 나오지 않았다)

      GROUP BY C1, C2,C3,C4,C5 (GROUP BY 마지막의 C5가 인덱스에 없다) 

    인덱스를 사용 할 수 있는 경우

      GROUP BY C1 

      GROUP BY C1,C2

      GROUP BY C1,C2,C3

      GROUP BY C1,C2,C3,C4

      WHERE COL1='상수' ... GROUP BY COL2, COL3 (WHERE가 상수로 앞쪽의 인덱스 칼럼을 비교하기 때문에 GROUP BY에 없어도 인덱스 사용 가능)

      WHERE COL1='상수' AND COL2='상수' ... GROUP BY COL3

 4) ORDER BY 절의 인덱스 사용

   MySQL에서는 GROUp BY, ORDER BY의 처리가 흡사해서 인덱스 사용 여부도 GROUP BY와 거의 흡사하다. 추가 조건은

    * ASC, DESC 옵션이 인덱스와 같거나, 또는 정반대의 경우에만 사용 가능하다. (MySQL인덱스가 모두 오름차순일때, ORDER BY 절의 모든 칼럼이 오름차순or내림차순일때만 사용) 


 5) WHERE, ORDER BY(또는 GROUP BY)의 인덱스 사용

  WHERE, ORDER BY절이 '같이' 사용된 쿼리는 다음 3가지 중 한가지 로만 인덱스를 이용한다.

  1) WHERE, ORDER BY 동시에 같은 인덱스를 이용

    WHERE, ORDERBY의 칼럼이 모두 하나의 인덱스에 연속해서 포함될 때, 이 방식 - 다른 2가지보다 훨씬 빠르다.

  2) WHERE 절만 인덱스를 이용

    ORDER BY 인덱스 사용이 불가능할때, WHERE절에 일치하는 조건의 건수가 많지 많을때 효율적

  3) ORDER BY절만 인덱스를 이용

    ORDER BY의 인덱스를 이용하면서 한 건식 WHERE 조건에 일치하는지 처리하는 형태 


 6) GROUP BY, ORDER BY절의 인덱스 사용

   동시 사용된 쿼리에서 인덱스를 사용해서 처리하려면, 두 곳의 명시된 칼럼의 '순서,내용'이 모두 같아야 한다. 만약 둘 중 하나라도 인덱스를 사용하지 못하면 둘다 인덱스를 사용하지 못한다.


Comments