584. Find Customer Referee
select name from Customer
where referee_id != 2 or referee_id is null
SQL 쿼리가 실행되는 순서
FROM: Customer 테이블을 스캔합니다.
WHERE: 조건을 평가합니다.
SELECT: 선택된 레코드에서 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 조건의 순서가 성능에 큰 영향을 미치지 않을 가능성이 큽니다.
추가적으로, 더 큰 데이터셋이나 더 복잡한 조건을 다룰 때 성능을 최적화하려면 다음과 같은 조치를 고려할 수 있습니다:
인덱스 추가: 쿼리 성능을 향상시키기 위해 적절한 인덱스를 추가합니다.
조건문 순서 최적화: 더 선택적인 조건을 먼저 평가하도록 조건문 순서를 최적화합니다.