Successfully reported this slideshow.

개발자들이 흔히 실수하는 SQL 7가지

145

Share

1 of 26
1 of 26

개발자들이 흔히 실수하는 SQL 7가지

145

Share

Download to read offline

자바카페 2014.06.10 내부 세미나 발표자료
블로그로 정리한 내용
http://blog.cjred.net/tag/se20140628

자바카페 2014.06.10 내부 세미나 발표자료
블로그로 정리한 내용
http://blog.cjred.net/tag/se20140628

More Related Content

Viewers also liked

Related Books

Free with a 14 day trial from Scribd

See all

개발자들이 흔히 실수하는 SQL 7가지

  1. 1. 개발자가 흔히 실수하는 SQL 7가지 2014 자바카페 SQL 동영상 스터디 이정근 cjred77@gmail.com 1
  2. 2. 2014 자바카페 SQL 동영상 스터디 이정근 1. SQL 파싱 순서 2. 인덱스 스캔, 풀스캔 3. 무조건 인덱스 많이 4. 조인을 사용하면 성능이 떨어진다? 5. count(*) > 0 6. 내림차순 인덱스 와 힌트절 7. LIKE BETWEEN, <>, IN 2
  3. 3. 2014 자바카페 SQL 동영상 스터디 이정근 SQL 파싱 순서 SELECT * FROM BIG_EMP WHERE MGR=‘7698’ AND DEPTNO=’60’; 직원테이블(EMP) 의 총 사원수(레코드 개수) 28955명 메니져(MGR) 가 7698인 사원수 10,319명 부서(DEPTNO) 가 60 인 사원수 1263명 3 MGR 7698 etc DEPTNO 60 etc
  4. 4. 2014 자바카페 SQL 동영상 스터디 이정근 SQL 파싱 순서 COST 기반 옵티마이져 인 경우 옵티마이져가 알아서 순서를 정함. (대부분의 경우 COST 기반 옵티마이져를 사용) RULE 기반 옵티마이져인 경우 이거나 RULE 을 사용하도록 힌트를 사용 하는 경우 1. 가장 나중에 생성한 인덱스가 있는 컬럼부터 파싱 2. 같은 경우 AND 는 WHERE 절에 가장 가까운 조건부터 뒤에서 부터 , OR 는 WHERE 절의 가장 오른쪽부터 파싱 DEPTNO=‘60' AND MGR=‘7698'; 앞 --> 뒤 DEPTNO=‘60' OR MGR=‘7698'; ; 앞 <-- 뒤 4
  5. 5. 2014 자바카페 SQL 동영상 스터디 이정근 SQL 파싱 순서 5 MGR=‘7698' AND DEPTNO=‘60'; 앞 --> 뒤 DEPTNO=‘60' AND MGR=‘7698'; 앞 --> 뒤
  6. 6. 2014 자바카페 SQL 동영상 스터디 이정근 SQL 파싱 순서 6 DEPTNO=‘60' OR MGR=‘7698'; 앞 <-- 뒤
  7. 7. 2014 자바카페 SQL 동영상 스터디 이정근 SQL 파싱 순서 A : 일반적(COST 기반 옵티마이져) 으 로 WHERE 절 컬럼순서에 상관없음 7
  8. 8. 2014 자바카페 SQL 동영상 스터디 이정근 인덱스 스캔, 풀 스캔 SELECT SAL FROM BIG_EMP WHERE MGR=‘7698’ AND JOB=‘SALESMAN’; 8
  9. 9. 2014 자바카페 SQL 동영상 스터디 이정근 인덱스 스캔, 풀 스캔 Single Block I/O (랜덤 액세스) • 인덱스를 사용하여 검색(인덱스 스캔)을 하게 되면 한번 의 I/O 요청에 한 블록씩 데이터를 읽는다. Multi Block I/O • 전체 데이블 검색(풀 스캔)은 데이터를 읽을 때 한번의 I/O 요청으로 여러 블록을 한꺼번에 읽는다. 9
  10. 10. 2014 자바카페 SQL 동영상 스터디 이정근 인덱스 스캔, 풀 스캔 Single Block I/O 1. 인덱스 테이블에서 조건절 검색 MGR=‘7698' 2. ROWID 로 테이블 검색 (1만 ROW , 1만회 I/O) 3. 조건절 검색 ( JOB='SALESMAN') Multi Block I/O 1. 3만 / 150 = 2백회 IO 2. 조건절 검색 ( JOB=‘SALESMAN') 10 10만 I/O 2천 I/O
  11. 11. 2014 자바카페 SQL 동영상 스터디 이정근 인덱스 스캔, 풀 스캔 풀 스캔을 유도하는 방법 • 인덱스가 걸린 컬럼을 가공 SELECT SAL FROM BIG_EMP WHERE MGR || ‘’ ='7698‘ AND JOB='SALESMAN'; • 힌트를 사용 SELECT /*+ FULL(EMP) */ SAL FROM BIG_EMP WHERE MGR='7698' AND JOB='SALESMAN'; 11
  12. 12. 2014 자바카페 SQL 동영상 스터디 이정근 인덱스 스캔, 풀 스캔 12
  13. 13. 2014 자바카페 SQL 동영상 스터디 이정근 인덱스 스캔, 풀 스캔 A : 인덱스컬럼의 조건이 대부분의 경 우에 포함되는 경우 풀 스캔이 더 성능 이 좋을 수 있음 13
  14. 14. 2014 자바카페 SQL 동영상 스터디 이정근 무조건 인덱스 많이 SELECT SAL FROM BIG_EMP WHERE MGR=‘7698’ AND JOB=‘SALESMAN’; • 인덱스를 만들거나 수정시 DB 성능 지연 발생 • 분포도가 좋지 않은 컬럼에 인덱스를 생성하더라도 성능에 영향이 적음. – 대부분의 LOCATION 컬럼값이 'SEOUL' 인 경우 오히려 Full Scan 이 유리 • INSERT, UPDATE, DELETE 시에 성능 저하 14
  15. 15. 2014 자바카페 SQL 동영상 스터디 이정근 무조건 인덱스 많이 A : 인덱스를 꼭 필요한 경우에만 추가 해야 한다. 15
  16. 16. 2014 자바카페 SQL 동영상 스터디 이정근 조인을 사용하면 성능이 떨어진다? A : 정규화를 하면 저장공간 및 I/O 부하가 줄어듬 16 사원번호 (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. 17. 2014 자바카페 SQL 동영상 스터디 이정근 조인을 사용하면 성능이 떨어진다? A : 정규화를 하면 저장공간 및 I/O 부하가 줄어듬 17
  18. 18. 2014 자바카페 SQL 동영상 스터디 이정근 count(*) > 0 SELECT (*) 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){ … } 18
  19. 19. 2014 자바카페 SQL 동영상 스터디 이정근 count(*) > 0 SELECT COUNT(*) FROM BIG_EMP WHERE MGR=‘7698’ AND JOB=‘SALESMAN ‘ AND ROWNUM <= 1; If(rs.getString("CNT") > 0){ … } MS-SQL 인 경우 Top N 사용 19
  20. 20. 2014 자바카페 SQL 동영상 스터디 이정근 count(*) > 0 EXISTS 서브쿼리 • 조건절을 만족하면 첫번째 레코드를 만나는 순간 True를 반환하고 서브쿼리를 종료 SELECT COUNT(*) FROM DUAL WHERE EXISTS( SELECT ‘x’ FROM BIG_EMP WHERE MGR=‘7698’ AND JOB=‘SALESMAN' ); If(rs.getString("CNT") > 0){ … } 20
  21. 21. 2014 자바카페 SQL 동영상 스터디 이정근 count(*) > 0 21
  22. 22. 2014 자바카페 SQL 동영상 스터디 이정근 count(*) > 0 A : EXISTS 나 ROWNUM 을 사용하여 불필요한 작업을 제거 22
  23. 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 ; 23
  24. 24. 2014 자바카페 SQL 동영상 스터디 이정근 내림차순 인덱스 와 힌트절 A : 내림차순 인덱스와 힌트절을 사용 하여 검색 속도를 개선 24
  25. 25. 2014 자바카페 SQL 동영상 스터디 이정근 LIKE, BETWEEN, <>, IN SELECT 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 을 사용시에 갯수를 적게 사용할것. 너무 많으면 시스템에 부하가 발생된다. 25
  26. 26. 감사합니다. 여호와를 두려워하는 것이 지혜의 첫걸 음이요 거룩하신 분을 아는 것이 깨달음이다. _잠언 9장 10절 Blog - http://blog.cjred.net Homepage – http://cjred.net 26

Editor's Notes

  • 오늘은 시간관계상 5개만 소개하도록 하겠습니다.
    각 타이틀을 다 읽어줄것

  • 풀스캔을 강제하는 방법은 /*+ full(emp) */
  • 테이블에 무조건 인덱스를 만드는 것은 비효율적이다.

    인덱스를 만들거나 수정시 DB 성능 지연 발생
    실제 구동하며 서비스하고 있는 DB에 아무리 작은 테이블이라도 인덱스를 생성하는 명령을 실행하면
    0.001 초라도 DB서버는 버벅이게 된다.
    이것은 no logging 등 별의별 옵션을 사용하도라도 기존 서비스에 영향도가 0% 라고 전혀 말 할 수 없다.
    인덱스를 추가하는 것을 100% 반대하는 것은 아니지만 운영중에 인덱스를 추가하거나 수정하는 것은
    가급적 피해야한다.

    분포도가 좋지 않은 컬럼에 인덱스를 생성하더라도 성능에 영향이 적음.
    분포도가 좋지 않다는것은 해당 컬럼의 값이 특정 값에 편중되어 있는 비율이 커서 차라리 Full Scan 을 통하여
    조회를 하는 것이 유리하다는 것이다.(인덱스 손익분기점)
    인덱스컬럼을 추가하던지(복합인덱스),
    다른 컬럼을 사용하여 조회하도록 쿼리 튜닝하던지,
    Full Scan을 사용하는 방법을 고려해야 한다.

    INSERT, UPDATE, DELETE 시에 성능 저하
    인덱스를 추가하게되면 당장 SELECT 시에 성능향상을 기대할 수 있겠지만,
    INSERT, UPDATE, DELETE 시에 오히려 성능이 저하된다.
    일일히 해당 인덱스에서도 INSERT, UPDATE, DELETE 가 수행되기 때문이다.


    저장공간의 낭비
    과다한 인덱스 생성으로 실제 테이블공간과 비슷하거나 더 많은 저장소 공간을 차지하는 배보다 배꼽이 더 큰 경우도 발생되고 있다.
  • 테이블에 무조건 인덱스를 만드는 것은 비효율적이다.

    인덱스를 만들거나 수정시 DB 성능 지연 발생
    실제 구동하며 서비스하고 있는 DB에 아무리 작은 테이블이라도 인덱스를 생성하는 명령을 실행하면
    0.001 초라도 DB서버는 버벅이게 된다.
    이것은 no logging 등 별의별 옵션을 사용하도라도 기존 서비스에 영향도가 0% 라고 전혀 말 할 수 없다.
    인덱스를 추가하는 것을 100% 반대하는 것은 아니지만 운영중에 인덱스를 추가하거나 수정하는 것은
    가급적 피해야한다.

    분포도가 좋지 않은 컬럼에 인덱스를 생성하더라도 성능에 영향이 적음.
    분포도가 좋지 않다는것은 해당 컬럼의 값이 특정 값에 편중되어 있는 비율이 커서 차라리 Full Scan 을 통하여
    조회를 하는 것이 유리하다는 것이다.(인덱스 손익분기점)
    인덱스컬럼을 추가하던지(복합인덱스),
    다른 컬럼을 사용하여 조회하도록 쿼리 튜닝하던지,
    Full Scan을 사용하는 방법을 고려해야 한다.

    INSERT, UPDATE, DELETE 시에 성능 저하
    인덱스를 추가하게되면 당장 SELECT 시에 성능향상을 기대할 수 있겠지만,
    INSERT, UPDATE, DELETE 시에 오히려 성능이 저하된다.
    일일히 해당 인덱스에서도 INSERT, UPDATE, DELETE 가 수행되기 때문이다.


    저장공간의 낭비
    과다한 인덱스 생성으로 실제 테이블공간과 비슷하거나 더 많은 저장소 공간을 차지하는 배보다 배꼽이 더 큰 경우도 발생되고 있다.
  • 
즉
    저장공간에서는 3배가 줄어들게 되고
    풀 스캔시 4배의 I/O 가 감소되게 된다.

    실제 필드에서는 수천만 수억, 수십억의 레코드가 있는 테이블도 있으므로 성능의 차이는 더 커진다.
  • 
즉
    저장공간에서는 3배가 줄어들게 되고
    풀 스캔시 4배의 I/O 가 감소되게 된다.

    실제 필드에서는 수천만 수억, 수십억의 레코드가 있는 테이블도 있으므로 성능의 차이는 더 커진다.
  • 자세한 설명은 생략한다..
  • ×