기본 콘텐츠로 건너뛰기

온라인 SQL 튜닝 전략

튜닝은 기술이면서, 동시에 행정이고, 외교이다. 시스템의 성능 문제를 분석하고 개선하기 위한 전문적인 기술은 필수이고, 내부 이해관계자의 다양한 요구 사항과 의견을 조율해야 하고, 때로는 외부 이해관계자와 첨예한 사안을 놓고 협상해야 할 수도 있다.

튜닝 이론으로는 얼마든지 성능 개선 가능하더라도, 실무에서는 기술적 주장 만으로 개선 방안이 적용되도록 밀어붙이는게 쉽지 않은게 현실이다. 다양한 주체의 다양한 이해관계를 풀어가기 위해서는 시스템 상태 뿐만 아니라, 이해관계자(특히 문제 원인에 귀책이 있거나, 개선방안을 적용하고 책임져야할 인프라팀이나 개발팀)의 상태도 함께 파악되어야 하고, 개선 방안을 작성하고 피력할때, 기술적인 내용 외에 이들을 잘 설득할 수 있는 함의(含意)를 담는 것은 노련한 SQL 튜너가 갖추어야할 기본적인 덕목이다.

다음은 튜닝 방법론의 일부라고도 할 수 있는 튜닝 전략 몇 가지를 소개한다. 

신속하고 정확한 튜닝을 위해, SQL 트레이스 결과 같은 구체적인 성능 자료를 우선 확보한다.

  • 세그먼트/오퍼레이션 수준의 결과 로우수(Rows), 논리 읽기 블록 수(Buffers), 물리 읽기 블록  수(Reads)는 필수적인 성능 분석 기초 자료이다

경험적으로 보면, (온라인 처리 SQL) 트레이스 결과에서 주요하게 많은 시간이 소요된 부분은거의 한 두 곳에 불과하며, 그 부분을 집중적으로 분석하고 개선한다

  • 사용자 체감 성능 또는 시스템 전체 자원 사용률에 별 영향을 주지 않는 소소한 개선은 설득력이 없고,  경제적이지도 못하다

문제의 근본적인 원인을 파악하여, 그것이 우선 해결되도록 한다

  • 최적 실행계획을 만들기 위해 무작정 힌트만 사용할게 아니라, 옵티마이저가 왜 성능에 불리한  실행계획을 수립했는지? 보다 근본적인 원인을 파악한다
  • 불필요하게 복잡한 쿼리문이 원인이라면, 쿼리문을 단순 명료하게 재작성하고,
  • 최신 통계정보가 없어서 그렇다면, 통계정보를 재생성하고,
  • 부적합한 DBMS 환경 설정값 때문이라면, 그 설정 값을 보완하고,
  • 적합한 인덱스가 없어서 그렇다면, 인덱스를 신규 생성 또는 변경하고,
  • 비정상적인 데이터 처리를 위한 예외 로직 때문이라면, 데이터 정제 노력을 우선 시도한다

다만 적용이 어려울 뿐, 성능 개선이 불가능할 수는 없다

  • 문제의 원인을 정확히 파악했다면, 성능을 개선할 방법도 반드시 존재할 것이다
  • 예를 들어, 데이터 구조 변경이나 정렬재구성을 운영 환경에서 당장 적용할 수 없더라도, 그것이 성능을  개선할 수 있는 유일한 방안이라면, 그 방안을 제시할 수 있어야 한다

최선이 어려우면 차선, 차선도 어려우면 차차선의 방안을 제시한다
  • 예를 들어, 데이터 구조 변경을 통해 확실한 개선이 가능하나, 구조 변경을 할 수 없는 상황이고, 인덱스 신규 생성으로 상당 부분 개선 가능하나 그것마저 적용 불가한 상황이면, SQL 수정으로라도 개선할 수  있는 방안을 제시할 수 있어야 한다

SQL 개발자가 기본적인 SQL 튜닝을 수행하도록, 성능 목표를 구체화한다
  • 구체적인 SQL/AP 성능 목표가 없으면, SQL 개발자의 노력이 오류 제거에만 집중되어, 통합테스트 시 성능 이슈로 큰 어려움을 겪을 수 있다
  • 그냥 튜닝하는 사람은 닥친 성능 문제만 해결하고, 튜닝 고수는 여러 개를 묶어서 한번에 해결하고, 튜닝 초고수는 미래의 성능 이슈를 예견하고 미리 예방하는 조치를 취한다

튜닝은 ‘오류 수정’이 아닌 ‘성능 개선’ 개념으로 인식한다
  • 튜닝은, 잘못을 질책하고, 오류를 수정하는 활동이라기 보다 이해관계자가 성능 개선을 위해 함께  노력하는 활동이다

댓글

댓글 쓰기

이 블로그의 인기 게시물

사례 : 실행계획 분리 - UNION ALL

복잡한 선택적 조건절을 사용하는 경우, 옵티마이저가 최적 실행계획을 수립하기 어려운데, 쿼리 수정 또는 USE_CONCAT 힌트 사용을 통해 OR EXPANSION을 유도하거나, UNION ALL 구문으로 입력 케이스별로 실행계획을 강제적으로 분리시키는 방법을 사용하여 성능을 최적화 한다. 개선 전 - 트레이스 결과 (문제 상황) 외환기본_IX08 인덱스 액세스에 대부분의 시간이 소요됨 IX08 인덱스가 거래일자와 과목코드 순으로 구성되어 있어서, 거래일자 범위 조건은 인덱스 access 조건이 되었지만,  과목코드 조건을 인덱스 filter 조건이 됨 (참고로, 과목코드 값이 ‘EX’인 것은 전체 로우의 약 5%임) 개선 전 - SQL문 (문제 원인) 고객번호 및 관리점번호 입력값이 필수가 아니어서, 해당 값 입력 여부에 따라 최적 실행계획이 달라질 수  있는데, 앞의 실행계획을 보면, 고객번호(:B3) 입력 여부 따라 실행계획이 분리되었음 (CONCATENATION/FILTER 오퍼레이션  등장) INDEX 힌트를 사용하여 항상 IX08 인덱스가 사용되도록 했는데, 이 INDEX 힌트를 제거하더라도 최적 실행계획이 수립되지  않았음 개선 방안 (개선 방안) 고객번호와 관리점번호 입력 여부에 따른 3가지  경우 각각을 구분하여 처리할 수 있도록 UNION ALL 사용 이때, 배타적인 3개 집합은 반드시 상호 배제되고 전체를  포괄해야 함 (MECE, Mutually Exclusive, Collectively Exhaustive) 개선 후 (개선 결과) 3가지 경우 각각에 최적인 실행계획이 수립됨(각각 IX01, IX04, IX08 인덱스를 사용) (개선 결과) 본 사례는 고객번호가 입력된 경우로서 IX01 인덱스가 사용되었고, 개선 전에 비해 액세스량/소요시간이  현저히 감소함

데이터 액세스 이슈와 SQL 튜닝

SQL 처리 시간이 오래 걸리는 직접적인 이유는 (대부분)  그 SQL문이 데이터 블록을 많이 액세스하기 때문이고 , SQL 튜닝  방안 대부분은 데이터 블록 액세스 최소화 노력이다. SQL 튜닝 경험이 풍부하면, SQL 트레이스 리포트만 있어도 데이터 블록 액세스 상황이 어떠한지? 어느 단계에서 가장 많은 시간이 많이 소요되었는지? 를 신속하게 파악할 수 있고, 이후 구체적인 문제 원인을 분석하고, 개선 방안을 찾는 것을 일사천리로 진행할 수 있다. 다음은 비교적 SQL 튜닝 경험이 많지 않은 초심자도 SQL 튜닝 실무에 쉽게 접근할 수 있도록 SQL 트레이스 분석, 문제 원인 분석, 개선 방안 수립 과정 전체 과정을 마인드 맵 형태로 도식하였고, 도식 내용에 대한 설명도 첨언하였다. (문제 상황) SQL 트레이스 결과 만으로 쉽게 구분 가능하도록 3가지 유형만 정의하였는데, 먼저 넓은 범위 액세스 여부를 판별하고, 그 다음 조인 순서 부적합 여부를 판별하고, 그외의 경우인 경우 마지막 테이블/인덱스 과다 액세스로 구분한다.   (문제 원인) SQL 트레이스 결과, SQL문 인덱스 정보, 데이터 구조와 값 등을 분석하여 종합적인 판단으로 주요하게 영향을 미친 문제 원인을 1개 이상 열거한다. (개선 방안) 문제 원인을 개선할 수 있고, 개선 효과도 충분히 큰 것을 우선 고려하고, 적용 가능 여부도 함께 고려하여 1개 이상의 개선 방안을 제시한다. 사실, SQL 트레이스 결과(또는 이에 버금가는 정보)를 보지 않고, (여기서 정의된) 데이터 액세스 이슈인지, 아니면 다른 이슈 인지를 판단하는 것은 쉽지 않을 수 있다. 예를 들어, 락 경합, 버퍼 경합과 같은 이슈는 데이터 액세스 이슈와는 그 성격이 다른 것이고, 그런 이슈는 대기 이벤트 정보가 있어야 문제 상황을 파악할 수 있다. 이렇듯 위 도식에 모든 SQL 성능 이슈, 모든 데이터 이슈 관련한 문제 상황, 문제 원인,...

사례 : 실행계획 고정

옵티마이저는 Query Transformation 기능 중 하나인 OR EXPANSION(실행계획 분리)을 통해 선택적인  조건절을 최적화할 수 있는데, 그런 기능이 적용된 실행계획이 오히려 성능에 불리한 경우, NO_EXPAND,  INDEX 힌트 등을 통해 OR EXPANSION 기능이 작동하지 않도록 한다. 개선 전 (문제 상황) 고객번호 조건으로도 액세스해야 할 데이터 건수가 충분히 줄어들지 않았고, 전문발송내역 테이블과  조인하면서 결과 건수가 급감함 (문제 원인) :고객번호 값이 입력되면 외환기본 테이블이 먼저 액세스되고, :고객번호가 입력되지 않으면 전문발송내역  테이블이 먼저 액세스되도록 실행계획이 분리되었는데(오라클 옵티마이저의 OR EXPANSION 기능), :고객번호가  입력되더라도 전문발송내역이 먼저 액세스 되는 것이 성능에 유리함을 확인함 개선 후 (개선 방안) :고객번호 값 입력되더라도 전문발송내역 테이블이 먼저 액세스되도록(OR EXPANSION 되지 않도록)  NO_EXPAND 힌트를 추가함 (LEADING 힌트로도 가능) (개선 결과) CONCATENATION 오퍼레이션이 사라지고, :고객번호 값 입력 여부 상관없이 전문발송내역 테이블을 먼저 액세스하는 실행계획이 수립되었으며, 개선 전보다 액세스 량이 크게 감소함