EXPLAIN

한상우·2024년 6월 30일

SQL

목록 보기
1/8

584. Find Customer Referee

select name from Customer
where referee_id != 2 or referee_id is null
  • where문의 조건문 순서를 바꿀 경우 최적화에 도움이 되는지 궁금했다.

SQL 쿼리가 실행되는 순서

  1. FROM: Customer 테이블을 스캔합니다.

    • Customer 테이블의 모든 레코드를 읽어옵니다.
  2. WHERE: 조건을 평가합니다.

    • referee_id != 2 OR referee_id IS NULL 조건을 각 레코드에 적용합니다.
    • referee_id가 2가 아닌 레코드와 referee_id가 NULL인 레코드를 필터링합니다.
  3. SELECT: 선택된 레코드에서 name 컬럼을 추출합니다.

    • 필터링된 레코드의 name 컬럼 값을 반환합니다.

-> 이때, 실제 물리적 실행 순서는 MySQL 옵티마이저에 의해 최적화된다

EXPLAIN 명령

  • EXPLAIN 명령의 결과를 해석하면 쿼리가 데이터베이스에서 어떻게 실행될지를 알 수 있다

    • 아래 명령의 결과를 확인해보자.

      EXPLAIN SELECT name FROM Customer WHERE referee_id != 2 OR referee_id IS NULL;
      | id | select_type | table    | partitions | type | possible_keys | key  | key_len | ref  | rows | filtered | Extra       |
      | -- | ----------- | -------- | ---------- | ---- | ------------- | ---- | ------- | ---- | ---- | -------- | ----------- |
      | 1  | SIMPLE      | Customer | null       | ALL  | null          | null | null    | null | 6    | 86.11    | Using where |
      
  • id: 쿼리 내 각 SELECT 문에 대한 고유 식별자입니다. 복잡한 쿼리(예: 서브쿼리, 조인)에서는 여러 행을 가질 수 있으며, 간단한 쿼리에서는 일반적으로 1입니다.

  • select_type: SELECT 문의 유형을 나타냅니다. SIMPLE은 서브쿼리나 UNION이 없는 단순 SELECT 문을 의미합니다.

  • table: 해당 행이 참조하는 테이블의 이름입니다. 이 경우 Customer 테이블을 참조합니다.

  • partitions: 쿼리가 액세스하는 파티션을 나타냅니다. null은 파티션이 사용되지 않음을 의미합니다.

  • type: 조인 유형을 나타냅니다. 이는 테이블에 접근하는 방식의 지표입니다. ALL은 테이블 전체를 스캔하는 풀 테이블 스캔을 의미합니다. 이는 가장 비용이 많이 드는 접근 방식입니다.

  • possible_keys: 쿼리에서 사용할 수 있는 인덱스 목록입니다. null은 이 쿼리에 대해 사용할 수 있는 인덱스가 없음을 의미합니다.

  • key: 실제로 사용된 인덱스입니다. null은 인덱스가 사용되지 않았음을 의미합니다.

  • key_len: 사용된 인덱스의 길이입니다. null은 인덱스가 사용되지 않았으므로 길이가 없음을 의미합니다.

  • ref: 인덱스와 비교할 컬럼 또는 상수입니다. null은 참조가 없음을 의미합니다.

  • rows: MySQL이 이 쿼리를 실행하기 위해 스캔해야 한다고 예측하는 행의 수입니다. 6은 Customer 테이블의 6개의 행을 스캔할 것임을 의미합니다.

  • filtered: 조건에 의해 필터링된 행의 비율을 백분율로 나타냅니다. 86.11은 MySQL이 86.11%의 행이 조건을 만족할 것으로 예측한다는 의미입니다.

  • Extra: 추가 정보입니다. Using where는 WHERE 절이 사용되었음을 나타냅니다.

결론

  • 인덱스가 없기 때문에 MYSQL은 모든 행을 스캔할 수밖에 없다.

  • EXPLAIN 결과를 보면, rows 필드가 6으로 표시되어 있습니다. 이는 MySQL이 Customer 테이블의 모든 행을 스캔할 것으로 예상한다는 의미입니다. 이 경우 Customer 테이블의 행 수가 적고, 풀 테이블 스캔이 큰 성능 문제를 일으키지 않기 때문에 WHERE 조건의 순서가 성능에 큰 영향을 미치지 않을 가능성이 큽니다.

  • 추가적으로, 더 큰 데이터셋이나 더 복잡한 조건을 다룰 때 성능을 최적화하려면 다음과 같은 조치를 고려할 수 있습니다:

    • 인덱스 추가: 쿼리 성능을 향상시키기 위해 적절한 인덱스를 추가합니다.

    • 조건문 순서 최적화: 더 선택적인 조건을 먼저 평가하도록 조건문 순서를 최적화합니다.

      • 조건문 순서 최적화는 인덱스가 없더라도 데이터 분포와 조건에 따라 효과적일 수 있다. 또한, 위의 예시처럼 OR을 사용하여 조건문을 연결하는 경우 보다는 AND를 사용하여 조건문을 연결 할 경우 더욱 효과적이다.
profile
개인 공부용 블로그입니다

0개의 댓글