'성능'에 해당되는 글 2건

  1. 2009/08/20 글뻥 SQL 사용시 주의할 점
  2. 2007/03/09 글뻥 MSSQL 과부하 걸릴때 조치
지금까지 십여년 가까이 전산쟁이 생활하면서 개발자들이 많이 저지르는 SQL miss-사용법에 대해 한번 정리 해보고자 한다. 한마디로 성능 저하의 원인이 되는 것들이다.
특히 이런 녀석들은 데이터량이 작을때는 문제가 안되다가 일정 용량 넘어가면 그때부터 문제가 되는 녀석들이다.

따라서, 실행계획을 계속 모니터링 하면서 일정 시간 이상의 SQL문은 튜닝해주자.

1. Index를 생성하지 않은 컬럼에 Where 조건 주는 경우
조건 : T1이라는 Table은 C1과 C2 컬럼이 있다.
SQL : select C1 from T1 where C2 = '1'
이경우 CPU 부하가 무지막지하게 올라간다. C2에 Index가 걸려 있는지 확인하여 안걸려 있다면 걸어주도록 하자.

2. Database Table간에 중복되는 값이 들어가 있는 경우
조건 : T1에 C1과 C2가 있고 T2에는 C3와 C4, C5가 있는데 C1과 C3는 PK/FK 관계이다. C2와 C5는 사실상 같은 내용의 컬럼이다.
이경우는 성능보다는 데이터 무결성에 문제가 되기도 한다. 또한 T1과 T2를 정규화 시키지 않음으로 해서 결과적으로 update 1번이면 되는 것을 2번하게 만드는 것때문에 불합리한 사용법중 하나이다.

3. Order by 명령
조건 : T1에 C1과 C2가 있다.
SQL : select C1 from T1 order by C2
흔히 사용하는 Query문이다. 문제가 되는 이유는 조건 없이 Full Sorting 하고 있다는 점이다.
이런 경우는 반드시 where 조건을 줘서 뽑아온 부분만 Order by 를 하도록 하자.
(간단한 사례 100,000건의 데이터 남녀 구분의 데이터 중에 정작 쓰는건 남자라고하면 Where 조건을 주게되면 50,000건만 Sorting하게 된다.)

4. Join 명령
조건 : T1에 C1과 C2가 있고 T2에 C3와 C4가 있다.
SQL : select T1.C1, T1, C2, T2, C4 from T1 join T2 on T1.C1=T2.C3 where T1.C1 = '1'
주로 사용하는 방식의 Join명령이다. 하지만 이것도 데이터의 수가 많으면 문제가 된다.
T1의 C1을 기준으로 T2의 C3와 매칭시켜 뽑아 오는 Query문인데 이런 경우는 이렇게 처음 부터 만들면 나중에 데이터가 많아지더라도 크게 문제가 되지 않는다.
select VT1.C1, VT2.C2, T2.C4 from (select C1, C2 from T1 where C1='1') VT1 join T2 on VT1=T2
Full scan 이 일어날 만한 명령을 사전에 차단해버리는 방법이다.

5. Hint 를 주지 않는 경우
조건 : T1에는 C1, C2, C3가 있고 C1과 C2에 각각 Index1과 Index2가 걸려 있다.
SQL : select C1, C2 from T1 where C2 = '1'
이런 경우는 특정 인덱스를 타라고 선언해주는 쪽이 나중에 성능 문제가 발생하지 않을 소지가 높다.
다시말해 이렇게 바꾸도록 하자
MSSQL : select C1, C2 from T1 with (INDEX (index2)) where C2='1'
Oracle : select /*+INDEX(index2) */ C1, C2 from T1 where C2='1'

보통 CPU에 과부하 걸린다고 해서 나가서 보면 이런 문제들이다.
처음 개발할때 부터 조금만 신경 쓰면 나중에 문제가 발생하지 않을 일을 하고 있다는것이 매우 아쉽다고나 할까?

그리고나서는 꼭하는 말들이 이러하다.
MS-SQL이라서... MySQL이라서...
ORACLE이 사실 하드웨어 스팩상 가장 빵빵하기때문에 이러한 실수를 조금 가려주기도 한다.
그러나 이런 문제들은 지아무리 오라클이 와도 조금 지나면 재발되는 문제이다.

나중에 땀 삐질 삐질 흘리지 말고 지금부터라도 잘 잡도록 하자
2009/08/20 11:41 2009/08/20 11:41
SQL만 공부들 하시느라 그런지 MSSQL이나 오라클 등이 나자빠질정도로 과부하가 걸려도 아무렇지도 않다는 듯이 무관심한 사람들이 꽤 있다. 그러지말자. 그덕에 나같은 사람들 출장다녀야 하니 짜증 짬뽕이다.

가장 많이 접하는 경우를 예로 들면 테이블에 인덱스 안걸고 쿼리문에는 where조건 미친 프로그래머들이다.
나도 개발하지만 미친 프로그래머들땜시 RX8620의 CPU가 풀나는 아주 웃기지도 않는 사건이 있다.
그럴때는 차분히 다음과 같이 하자.

1. 먼저 MSSQL의 "프로필러"를 실행하라.
사용자 삽입 이미지

2. 정보를 수집하라
- 다른곳은 그대로 두고 "추적속성"에 "이벤트"탭만 설정한다.
사용자 삽입 이미지

3. 수집된 정보를 분석하라.
- "CPU"와 "Duration" 2개 필드가 높은넘부터 Sort하여 정렬한다. 예제에서는 그런넘이 없어 아쉽지만 참고만하자.
사용자 삽입 이미지

4. 가능성 있는 용의자를 확인했으면 테스트하자
- begin tran ~ rollback 사이에 용의자(쿼리)를 집어넣고 "CTRL+L"을 눌러 실행계획을 보자
- 실행계획에 가는 실선이 아닌 굵은 선으로 된부분을 따라가다보면 다음과 같이 나온다.
- 예제에서는 풀스캔하고 있다... ㅡㅡ;;
사용자 삽입 이미지

5. 이제 제대로 바꿔놓자
- 인덱스를 추가해놓자
사용자 삽입 이미지

6. 결과
- 적용 5분후 결과이다.
사용자 삽입 이미지
- 최종 10분후의 CPU사용율이다.
사용자 삽입 이미지

* 본사례는 H대학교 시스템에서 발생했던 부하에 대해 조치한 것을 리포트형식을 빌어 기록해둔것이다.
* 처음 추적을 시작할때 필터를 걸면 원하는 것을 얻어 낼 수도 있지만 DB에 넣어 원하는 바를 얻고싶다면 SQL에서 생성한 파일을 직접 import할 수도 있다.
SELECT * INTO tbltr
FROM ::fn_trace_gettable('D:\tmp\파일명.trc', default) 
2007/03/09 11:11 2007/03/09 11:11