7.4.3 WHERE 절의 비교 조건 사용 시 주의사항

NULL 비교

  • 다른 DBMS와는 조금 다르게 MySQL에서는 NULL 값이 포함된 레코드도 인덱스로 관리된다. 이는 인덱스에서는 NULL을 하나의 값으로 인정해서 관리한다는 것을 의미한다.
  • SQL 표준에서 NULL의 정의는 비교할 수 없는 값이다. 그래서 두 값이 모두 NULL을 가진다고 하더라도, 이 두 값이 같은지 비교 하는 것이 불가능하다.
  • 쿼리에서 NULL인지 비교하려면 IS NULL 연산자를 사용해야 한다.
  • ISNULL() 함수도 된다.
SELECT * FROM titles WHERE to_date IS NULL;
SELECT * FROM titles WHERE ISNULL(to_date);
SELECT * FROM titles WHERE ISNULL(to_date)=1;
SELECT * FROM titles WHERE ISNULL(to_date)=true;
  • 가급적 IS NULL 연산자를 사용하길 권장한다.

  • 3, 4번째는 인덱스를 사용 못한다.

문자열이나 숫자 비교

  • 문자열 칼럼이나 숫자 칼럼을 비교할 때는 반드시 그 타입에 맞춰서 상수를 사용할 것을 권장한다. 즉 비교 대상 칼럼이 문자열 칼럼이라면 문자열 리터럴을 사용하고, 숫자 타입이라면 숫자 리터럴을 이용한다.
SELECT * FROM employees WHERE emp_no=10001;
SELECT * FROM employees WHERE first_name='Smith';
SELECT * FROM employees WHERE emp_no='10001';
SELECT * FROM employees WHERE first_name=10001;
  • 첫 번째와 두 번째 쿼리는 칼럼의 타입과 비교하는 상수값이 동일한 타입으로 사용됐기 때문에 인덱스를 적절히 이용할 수 있다.
  • 세 번째의 쿼리는 emp_no 칼럼이 숫자 타입이기 때문에 문자열 상수값을 숫자로 타입 변환해서 비교를 수행하므로 특별히 성능 저하는 발생하지 않는다.
  • 네 번째 쿼리는 first_name이 문자열 칼럼이지만 비교되는 상수값이 숫자 타입이므로 옵티마이저는 우선순위를 가지는 숫자 타입으로 비교를 수행하려고 실행 계획을 수립한다. 그래서 first_name 칼럼의 문자열을 숫자로 변환해서 비교를 수행한다. 하지만 first_name 칼럼의 타입 변환이 필요하기 때문에 ix_firstname 인덱스를 사용하지 못한다.