b

7.4.SELECT ( 7.4.3 WHERE ~ 7.4.5 LIMIT ) 본문

RealMysql

7.4.SELECT ( 7.4.3 WHERE ~ 7.4.5 LIMIT )

dev.bistro 2012. 12. 11. 21:44


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


 1) NULL 비교

   - MySQL에서는 NULL값도 인덱스로 관리된다. SQL정의에 의해 NULL은 "비교할 수 없는 값" 그래서 NULL은 ISNULL을 사용하라.

     SELECT CASE WHEN NULL  IS NULL THEN 1 ELSE 0 END;

     SELECT * FROM titles WHERE to_date IS NULL (type:ref)


     ISNULL( )함수를 사용해도 되지만, 주의하라. 인덱스를 이용할 수 없을지도 모른다.

     이용X : SELECT * FROM titles WHERE ISNULL(to_date) = 1;

     이용O : SELECT * FROM titles WHERE ISNULL(to_date);


2) 문자열, 숫자 비교

  - 반드시 그 타입에 맞춰 상수를 사용하라.

    SELECT * FROM emp where emp_no = '10001'

    => 숫자타입, 문자열을 비교하지만, 옵티마이저가 문자열의 숫자를 숫자타입으로 변경하기때문에 큰 성능저하는 없다.

    SELECT * FROM emp where first_name = 10001;

    => 옵티마이저는 우선순위로 first_name을 숫자형으로 변경하려고 한다.그래서 first_name이 가지는 원래 인덱스를 사용하지 못한다.


3) 날자 비교

  DATE :날자 저장

  DATETIME, TIMESTAMP : 날자,시간 저장

  TIME : 시간 저장



7.4.4 DISTINCT

 * 집함 함수와 같이 사용될때, 인덱스를 사용하지 못하면 항상 임시 테이블이 필요하다 하지만 Extra에 Using temp 표시가 나오지 않으므로 주의.

 

 1) SELECT DISTINCT

   유니크한 레코드를 찾을때, GROUP BY와 거의 유사한 방식. 단 이방법은 정렬이 보장되지 않는다.

   SELECT DISTINCT emp_no FROM sal = SELECT emp_no FROM sal GROUP BY emp_np 

   DISTINCT는 레코드 유니크이지, 칼럼 유니크는 아니다!


   DISTINCT는 함수가 아니므로 뒤의 괄호는 무시한다

   SELECT DISTINCT(first_name) , last_name === SELECT DISTINCT first_name , last_name 

   ==>절대로 일부 칼럼에만 유니크하게 조회 하는 방법은 없다. 아래는 예외


2) 집함 함수와 DISTINCT

  집합 함수 내에서 사용된 DISTINCT는 그 함수의 인자의 조합 가운데서 유일한 값만 가져온다.

  SELECT COUNT(DISTINCT s.salary) FROM emp e, sal s WHERE e.emp_no = s.emp_no

  e,s테이블의 조인 결과에서 salary 칼럼만 저장하기 위한 임시 테이블을 생성하지만 실행계획에서 using temp는 나오지 않는다.



 SELECT DISTINCT first_name, last_name

 SELECT COUNT(DISTINCT first_name) , COUNT(DISTINCT last_name)

 SELECT COUNT(DISTINCT first_name, last_name) 은 전부 다 다르다.



7.4.5 LIMIT n

 (MySQL)전용 키워드, 오라클의 ROWNUM과 비슷하다. 항상 쿼리의 제일 마지막에 실행된다.

 ** LIMIT가 필요한 건수만 준비되면 쿼리를 종료한다 

 SELECT  * FROM emp WHERE emp_no BETWEEN 10001 AND 10010 ORDER BY first_name LIMIT 0, 5

 ==> 정렬하다가 5건만 되면 더 이상 정렬 안하고 쿼리를 종료한다.


 SELECT * FROM emp LIMIT 0, 10 => 원래는 풀 스캔인데 LIMIT 때문에 위에서 10개의 레코드를 읽는 순간 읽기 작업이 멈춘다.

 ORDER BY, GROUP BY, DISTINCT가 적절히 인덱스를 이용하면, LIMIT은 꼭 필요한 만큼만을 정하므로 성능 향상이 있다.


  * LIMIT제약 : 인자로 표현식이나 별도의 서브 쿼리를 사용 할 수 없다. ( ex: SELECT * FROM emp LIMIT (100-10) )

  * LIMIT 0 : MySQL옵티마이저는 쿼리를 실행하지 않고 최적화만 실행하고 즉시 응답한다. 이건, 커넥션 풀에서 커넥션의 유효성을 체크하는데 유용하게 사용한다


Comments