Post List

2015년 1월 8일 목요일

대용량 데이터베이스 솔루션 2권 #03 SQL 활용방법

SQL이란 ?

- SQL은 명령어(Statement)가 아니라 프로그램(Application)이다.
- Database에게 일을 시킬 수 있는 유일한 수단이다.
- 절차형 사고를 집합적 사로로 전환해야 한다.
- 동일한 결과를 내는 처리경로는 많으나 효율의 차이는 크다.
- 응용력에 따른 개인차가 크며, 사용상의 미묘한 차이가 엄청난 효율성의 차이를 가져온다.
- 1000줄의 절차형 프로그램을 SQL 10줄로 처리가능한 경우가 많다.
- 1000초의 수행속도를 보이는 SQL을 약간의 변경으로 1초 이내로 향상하는 것이 가능하다.
- 내부 처리절차를 모르는 사람은 100만년이 지나도 여전히 알 수가 없다. PC로 게임 백날 한다고 해서 게임 프로그램이 가능하나?
- 원리 이해를 바탕으로 정석을 익히고 응용력을 길러라 !

1. SQL에서 IF 처리

 if ... else ... 때문에 어쩔수없이 Logic을 쓴다고 ? SQL에서도 다 된다.



CASE 보다 DECODE가 훨씬 짧고 편리하다.
하지마 모든 DBMS가 DECODE를 지원해주지는 않는다. 생각보다 많다. MS-SQL 과 기타 Open Source 계열의 DBMS 들도...
하지만 CASE 는 Equal (=) 연산 말고 다른 모든 비교가 다 가능하지만, CASE는 Equal 연산밖에 안된다.
하지만 여러가지 함수를 활용하면 부등호 연산을 대신해서 사용이 가능하다.
대표적으로 SIGN() 함수는 음수, 0 , 양수 값이 입력되면 각각 -1, 0 ,1 을 반환한다.

2. 문자열의 부등호 비교



LEAST() : 작거나 같으면 입력값을 반환
GREATEST() : 크거나 같으면 입력값을 반환
같은거 말고 아에 작거나 같은 것만 비교는 어떻게 하냐고 ?
문자열 뒤에 Space ' '를 하나 붙여서 비교를 한다던지,
아니면 LEAST() 로 비교 대신 GREATEST()로 비교한 후 참, 거짓값의 위치를 바꾼다던지
이렇게 생각을 하는 능력이 바로 응용력 ! 이걸 길러야 한다.
이 능력은 절차형 프로그래밍에서도 상당히 중요한 능력이다.

3. SUM(DECODE) : 내용이 많아서 별도 단원으로 분리

4. COUNT(DECODE)


  • 1, 2, 4, 5 는 COL1이 'A'인 경우만 COUNT
  • 3 의 결과는 COUNT(*) 와 동일
  • 1은 2보다 더 느림 (0보다는 NULL이 차라리 더 나음)
  • 2는 4, 5 보다 더 느림
  • 4, 5는 성능이 동일함


한가지 의문점이 생길수도 있다. 왜 굳이 DECODE 까지 써가면서 COUNT 안에서 비교를 하냐 ? 그냥 WHERE에서 CHECK하는게 더 빠르자나. 물론 그렇다. 하지만 위와 같이 쓸일이 안생길까 ? 분명 생긴다. SQL문 작성시 같은 DATA를 절대로 2번 이상 읽지 않게 만들어야 한다. 그렇게 짜기 위해서는 위의 방법이 필요할 때가 분명히 생긴다.

- SUM은 COUNT보다 30 ~ 50% 정도 더 느리다.
- COUNT는 NOT NULL 인 경우만 처리한다. (모든 GROUP 함수들이 다 그렇다.)
- COUNT로 해결이 된다면 SUM을 굳이 사용하지 마라.

5. GROUP BY 문에서 MIN, MAX의 활용
SELECT 사번, 입사일, SUM(급여)
  FROM 근태
 WHERE 부서코드 = '1110'
   AND 일자 BETWEEN '20130101' AND '20131231'
 GROUP BY 사번, 입사일
위의 SQL문을 한번 살펴보자. 그냥 흔한 문장이다. 각 사원별 입사일과 2013년 받은 총 급여를 출력하는 것이다.
근데 가만히 보면 GROUP BY에 사번과 입사일이 같이 있다. GROUP BY를 좀 써본 사람이라면 왜 저런지 알것이다. 왜냐면 GROUP BY를 사용한 문장에서 SELECT 에는 GROUP BY에 적은 Column 과 GROUP 함수 , 상수만 올 수 있기 때문이다.
당연히 상식적으로 한 개의 사번에 2개의 입사일이 있을리가 없지만 그래도 분명 위의 SQL문은 원하지 않는 집합 생성의 우려가 존재한다. 한 사원이 하나 이상의  ROW로 나뉠 수가 있다.
그럼 입사일도 출력하고 싶은데 어떻게 해야 할까 ? 과거의 나는 그냥 입사일을 제외한 나머지를 INLINE VIEW로 만들어서 JOIN 했다. 그런데 그렇게 하면 분명 같은 TABLE에서 2번 DATA를 읽었다. 대용량 데이터베이스를 배우면서 그러면 안된다.
이럴때 활용가능것이 바로 MIN, MAX 의 활용이다. 대부분 그냥 MIN을 많이 쓴다. 어차피 정상적인 경우 입사일은 1개 뿐이니 MIN 을 하든 MAX를 하든 그냥 출력하든 값은 값이 나올 것이다. 하지만 MIN, MAX는 GROUP 함수이므로 GROUP BY 절에 적지 않고도 출력이 가능하다. 이것을 활용하여 아래와 같이 수정이 가능하다.
SELECT 사번, MIN(입사일), SUM(급여)
  FROM 근태
 WHERE 부서코드 = '1110'
   AND 일자 BETWEEN '20130101' AND '20131231'
 GROUP BY 사번
작가
이화식
출판
엔코아컨설팅
발매
1999.11.20
평점

블로거의 오늘의 책에 참여한 포스트 입니다

댓글 없음:

댓글 쓰기