개발자들이 흔히 실수하는 sql 7가지
DESCRIPTION
자바카페 2014.06.10 내부 세미나 발표자료 블로그로 정리한 내용 http://blog.cjred.net/tag/se20140628TRANSCRIPT
2
2014 자바카페 SQL 동영상 스터디 이정근
1. SQL 파싱 순서
2. 인덱스 스캔 , 풀스캔
3. 무조건 인덱스 많이
4. 조인을 사용하면 성능이 떨어진다 ?
5. count(*) > 0
6. 내림차순 인덱스 와 힌트절
7. LIKE BETWEEN, <>, IN
3
2014 자바카페 SQL 동영상 스터디 이정근
SQL 파싱 순서SELECT * FROM BIG_EMP WHERE MGR=‘7698’ AND DEPTNO=’60’;
직원테이블 (EMP) 의 총 사원수 ( 레코드 개수 ) 28955 명메니져 (MGR) 가 7698 인 사원수 10,319 명부서 (DEPTNO) 가 60 인 사원수 1263 명
MGR
7698etc
DEPTNO
60etc
4
2014 자바카페 SQL 동영상 스터디 이정근
SQL 파싱 순서COST 기반 옵티마이져 인 경우 옵티마이져가 알아서 순서를 정함 .( 대부분의 경우 COST 기반 옵티마이져를 사용 )
RULE 기반 옵티마이져인 경우 이거나 RULE 을 사용하도록 힌트를 사용 하는 경우1. 가장 나중에 생성한 인덱스가 있는 컬럼부터 파싱2. 같은 경우 AND 는 WHERE 절에 가장 가까운 조건부터 뒤에서 부터 ,
OR 는 WHERE 절의 가장 오른쪽부터 파싱
DEPTNO=‘60' AND MGR=‘7698'; 앞 --> 뒤 DEPTNO=‘60' OR MGR=‘7698'; ; 앞 <-- 뒤
5
2014 자바카페 SQL 동영상 스터디 이정근
SQL 파싱 순서
MGR=‘7698' AND DEPTNO=‘60'; 앞 --> 뒤DEPTNO=‘60' AND MGR=‘7698'; 앞 --> 뒤
6
2014 자바카페 SQL 동영상 스터디 이정근
SQL 파싱 순서DEPTNO=‘60' OR MGR=‘7698'; 앞 <-- 뒤
7
2014 자바카페 SQL 동영상 스터디 이정근
SQL 파싱 순서
A : 일반적 (COST 기반 옵티마이져 ) 으로 WHERE 절 컬럼순서에 상관없음
8
2014 자바카페 SQL 동영상 스터디 이정근
인덱스 스캔 , 풀 스캔SELECT SAL FROM BIG_EMP WHERE MGR=‘7698’ AND JOB=‘SALESMAN’;
9
2014 자바카페 SQL 동영상 스터디 이정근
인덱스 스캔 , 풀 스캔Single Block I/O ( 랜덤 액세스 )• 인덱스를 사용하여 검색 ( 인덱스 스캔 ) 을 하게 되면 한번의
I/O 요청에 한 블록씩 데이터를 읽는다 .
Multi Block I/O• 전체 데이블 검색 ( 풀 스캔 ) 은 데이터를 읽을 때 한번의 I/O
요청으로 여러 블록을 한꺼번에 읽는다 .
10
2014 자바카페 SQL 동영상 스터디 이정근
인덱스 스캔 , 풀 스캔Single Block I/O1. 인덱스 테이블에서 조건절 검색 MGR=‘7698' 2. ROWID 로 테이블 검색 (1 만 ROW , 1 만회 I/O)3. 조건절 검색 ( JOB='SALESMAN')
Multi Block I/O4. 3 만 / 150 = 2 백회 IO5. 조건절 검색 ( JOB=‘SALESMAN')
10 만 I/O
2 천 I/O
11
2014 자바카페 SQL 동영상 스터디 이정근
인덱스 스캔 , 풀 스캔풀 스캔을 유도하는 방법
• 인덱스가 걸린 컬럼을 가공SELECT SAL FROM BIG_EMPWHERE MGR || ‘’ ='7698‘ AND JOB='SALESMAN';
• 힌트를 사용SELECT /*+ FULL(EMP) */ SAL FROM BIG_EMPWHERE MGR='7698' AND JOB='SALESMAN';
12
2014 자바카페 SQL 동영상 스터디 이정근
인덱스 스캔 , 풀 스캔
13
2014 자바카페 SQL 동영상 스터디 이정근
인덱스 스캔 , 풀 스캔
A : 인덱스컬럼의 조건이 대부분의 경우에 포함되는 경우 풀 스캔이 더 성능이 좋을 수 있음
14
2014 자바카페 SQL 동영상 스터디 이정근
무조건 인덱스 많이SELECT SAL FROM BIG_EMP WHERE MGR=‘7698’ AND JOB=‘SALESMAN’; • 인덱스를 만들거나 수정시 DB 성능 지연 발생• 분포도가 좋지 않은 컬럼에 인덱스를 생성하더라도 성능에 영향이 적음 .
– 대부분의 LOCATION 컬럼값이 'SEOUL' 인 경우 오히려 Full Scan 이 유리
• INSERT, UPDATE, DELETE 시에 성능 저하
15
2014 자바카페 SQL 동영상 스터디 이정근
무조건 인덱스 많이
A : 인덱스를 꼭 필요한 경우에만 추가해야 한다 .
16
2014 자바카페 SQL 동영상 스터디 이정근
조인을 사용하면 성능이 떨어진다 ?
A : 정규화를 하면 저장공간 및 I/O 부하가 줄어듬
사원번호 (8)
이름 (10)생년월일 (8)입사일 (8)직급 (8)연봉 (4)부서명 (12)부서사업장주소 (100)부서장이름 (10)
40 만 레코드 X 168 Byte = 67,200,000 Byte= 64Mbyte
사원번호 (8)
이름 (10)생년월일 (8)입사일 (8)직급 (8)연봉 (4)부서코드 (8)
부서코드 (8)
부서명 (12)부서사업장주소 (100)부서장이름 (10)
40 만 레코드 X 46 Byte= 18,400,000 Byte= 17.5Mbyte
100 레코드 X 130Byte= 12Kbyte
EMP 테이블 사원 테이블
부서 테이블
17
2014 자바카페 SQL 동영상 스터디 이정근
조인을 사용하면 성능이 떨어진다 ?
A : 정규화를 하면 저장공간 및 I/O 부하가 줄어듬
18
2014 자바카페 SQL 동영상 스터디 이정근
count(*) > 0SELECT (*) AS CNT FROM BIG_EMP WHERE MGR=‘7698’ AND JOB=‘SALESMAN’;; If(rs.getString("CNT") > 0){ …}
Or
SELECT * FROM BIG_EMP WHERE MGR=‘7698’ AND JOB=‘SALESMAN’; If(rs.size() > 0){ …}
19
2014 자바카페 SQL 동영상 스터디 이정근
count(*) > 0SELECT COUNT(*) FROM BIG_EMPWHERE MGR=‘7698’ AND JOB=‘SALESMAN ‘ AND ROWNUM <= 1; If(rs.getString("CNT") > 0){ …}
MS-SQL 인 경우 Top N 사용
20
2014 자바카페 SQL 동영상 스터디 이정근
count(*) > 0
EXISTS 서브쿼리• 조건절을 만족하면 첫번째 레코드를 만나는 순간 True 를 반환하고
서브쿼리를 종료 SELECT COUNT(*) FROM DUALWHERE EXISTS( SELECT ‘x’ FROM BIG_EMP WHERE MGR=‘7698’ AND JOB=‘SALESMAN');
If(rs.getString("CNT") > 0){ …}
21
2014 자바카페 SQL 동영상 스터디 이정근
count(*) > 0
22
2014 자바카페 SQL 동영상 스터디 이정근
count(*) > 0
A : EXISTS 나 ROWNUM 을 사용하여 불필요한 작업을 제거
23
2014 자바카페 SQL 동영상 스터디 이정근
내림차순 인덱스 와 힌트절조회하고자 하는 데이터의 특성상 가장 최근의 데이터부터 역순으로 인덱스를 조회하는 것이 유리할 경우가 있음 예 )• 신입사원의 입사정보조회• 게시판의 최신 글 내용 조회• 로그성 데이터의 정보조회
내림차순인덱스 생성하는 방법CREATE INDEX I_EMP_EMPNO ON BIG_EMP (EMPNO DESC)
조회시 힌트를 사용하는 방법SELECT /*+ INDEX_DESC (BIG_EMP I_EMP_EMPNO) */EMPNO FROM BIG_EMP ROWNUM<10 ;
24
2014 자바카페 SQL 동영상 스터디 이정근
내림차순 인덱스 와 힌트절
A : 내림차순 인덱스와 힌트절을 사용하여 검색 속도를 개선
25
2014 자바카페 SQL 동영상 스터디 이정근
LIKE, BETWEEN, <>, INSELECT PAYMENT FROM EMP WHERE DEPARTMENT = 'SALES' AND HIRE_DT > '201301' AND HIRE_DT < '201312'; EMP 의 ROW 갯수 40만 A : HIRE_DT > '201301' AND HIRE_DT < '201312' B : HIRE_DT LIKE '2013%' C : BETWEEN '201301' AND '201312' D : HIRE_DT IN ('201301', '201302', '201303', '201304', '201305', '201306', '201307', '201308', '201309', '201310', '201311', '201312')
소요시간 : D < B < C < A
A : 가급적이면 범위 검색 할 때 IN 을 사용하자! 주의 . IN 을 사용시에 갯수를 적게 사용할것 . 너무 많으면 시스템에 부하가 발생된다 .
26
감사합니다 .
여호와를 두려워하는 것이 지혜의 첫걸음이요 거룩하신 분을 아는 것이 깨달음이다 .
_ 잠언 9 장 10 절Blog - http://blog.cjred.net
Homepage – http://cjred.net