Programing

DB 튜닝 실전(3)

handam 2016. 10. 28. 17:33

개발자를 위한 튜닝 실전(3편)



성공과 실패의 경험을 나누자, 용기와 희망을 나누자

개발업무를 시작으로 IT계에 입문했던 필자가 10년 가까이 DB엔지니어로서 활동하면서 얻은 경험과 지식을 나누고자 한다. DB를 자주 접하는 SW 개발자뿐 아니라, DB 전문가를 꿈꾸는 대학생에서DB 분야에 입문한지 1~2년 된 기입문자가 쉽게 이해할 수 있도록 비유를 통해 쉽게 접근해볼 계획이다. 물론 전문가들이라도 다시 한번 개념을 정립하는 의미에서 필요한 내용이 될 수 있다.

전체적으로 DB의 기본 원리와 개념을 이해하고 테이블, 인덱스, 쿼리, 튜닝, 플랜 등 개발자들이 알아야 하는 DB 전분야에 대해 쉽게 이해하도록 설명하겠다. DB 기술서적이나 번역서보다는 조금 더 부드럽게 접근할 계획이다. 그렇다고 흔히 서점에서 만날 수 있는 개발자 위주의 SQL 소개서도 아니다. 이 연재는 시리즈로 나갈 것이다. 연재를 끝까지 읽는 독자라면 준전문가 수준의 DB 원리를 아는 것을 목표로 한다.



좋은 쿼리와 나쁜 쿼리 그리고 ‘공정쿼리’

튜닝실전 1편에서는 대용량 데이터를 처리하는 배치 쿼리에 있어서 인덱스를 사용하지 말아야 하는 경우에 대하여 중요하게 설명하였다. 튜닝실전 2편에서는 소규모 데이터를 처리하는 온라인 쿼리에 있어서 인덱스를 정확히 사용해야 하는 경우에 대하여 주로 설명하였다. 이번 연재에서는 좋은 쿼리 작성법에 대하여 설명할 것이다. 

좋은 쿼리와 나쁜 쿼리는 어떤 차이점이 있을까? 필자가 생각하는 좋은 쿼리란 누구나 쉽게 이해하게 작성된 쿼리를 말한다. 반면에 나쁜 쿼리란 작성자 본인만 이해할 수 있는 쿼리를 말한다. 좋은 쿼리를 필자는 공정쿼리라 부른다. 예전 연재에서 언급한 적이 있지만, 다시 한번 짚고 넘어 갈 필요가 있다. 

공정쿼리는 작성하기 쉬워야 하고 이해하기 좋아야 한다. 다른 사람이 작성한 쿼리를 여러분이 쉽게 이해를 못한다면 이것은 공정쿼리가 아니다. 또한 여러분이 작성한 쿼리를 다른 사람이 쉽게 이해 못한다면 이 또한 공정쿼리가 아니다. 공정쿼리는 서로가 쉽게 이해할 수 있도록 약속된 규칙에 의하여 작성된 쿼리를 말한다. 공정 쿼리의 큰 개념은 아래 [그림 1]과 같다. 



[그림 1] 공정쿼리에 대한 이해

공정쿼리는 무엇을 조회할지에 대한 쿼리 결과도 중요하지만, 어떻게 조회할지에 대한 쿼리 과정도 중요하게 생각하는 쿼리다. 한마디로 공정쿼리는 무엇을(What) 어떻게(How) 조회할지에 대한 내용이 모두 포함되어야 하는 것이다. 공정쿼리로 작성한 쿼리에서는 쿼리의 결과뿐만 아니라 생성해야 할 인덱스 위치 정보와 접근되어야 할 순차적 정보(Plan) 모두를 알 수 있다. 

일부 개발자는 어떻게(How) 조회할지에 대한 쿼리 과정은 등한시하고 무엇을(What) 조회할지에 대한 쿼리 결과에만 신경을 쓰는 경향이 있다. 그렇게 작성된 쿼리는 올바른 결과는 얻을지는 모르나 튜닝에 대한 좋은 성능은 기대할 수 없다. 



[그림 2] 잘못된 쇼핑: 무엇을(What) 구매할 것인가?

위 [그림 2]에서 나막사 주부는 무엇을(What) 사야하는지는 알고 있었으나, 어떻게(How) 사야하는지에 대한 고민은 없어 보인다. 이동 경로가 불필요하게 중첩되어 있다. 시간이 중요하지 않는 주중의 한가한 오후에는 멋진 쇼핑이 될 수 있으나 남편과 같이 간 주말 쇼핑이라면 남편으로부터 불편한 잔소리를 들을 것이다. 



[그림 3] 올바른 쇼핑: 무엇을(What) + 어떻게(How) 구매할 것인가?

위의 [그림 3]에서 나계획 주부는 무엇을(What) 사야하는지 알고 있었고, 어떻게(How) 사야하는지에 대해서도 알고 있었다. 이동 경로도 최적화되어 있다. 우리는 나막사 주부의 쇼핑과 나계획 주부의 쇼핑을 보면서 중요한 차이점을 발견할 수 있다. 그것은 바로 매장방문 순서에 대한 고민이다. 두 주부는 무엇을(What) 사야 하는지에 대한 구매 목록은 동일하지만, 어떻게(How) 사야 하는지에 대한 매장방문 순서에 대한 생각은 서로 다르다. 

나계획 주부의 쇼핑처럼 우리는 쿼리 작성에 있어서 무엇을(What) 조회할지에 대한 쿼리 결과뿐만 아니라 어떻게(How) 조회할지에 대한 쿼리 과정도 포함되어야 할 것이다. 이렇게 작성된 쿼리를 공정쿼리라 부른다. 공정쿼리는 우리에게 중요한 정보를 제공한다.



공정쿼리 기본 규칙

공정쿼리 기본 규칙은 쉽고 단순하다. 이해하기 위한 어떠한 노력도 필요 없을 정도로 아주 쉽다. 하지만 그렇게 작성되된 공정쿼리는 우리에게 엄청난 혜택을 준다. 아래 4가지는 공정쿼리 작성에 대한 기본 규칙이다.

1. SELECT 절에 대한 규칙: 접근하고자 하는 테이블의 순서대로 조회 컬럼을 나열한다.
2. FROM 절에 대한 규칙: 접근하고자 하는 순서대로 테이블을 나열한다.
3. 조인절에 대한 규칙: 접근하고자 하는 테이블 순서대로 조인절을 나열한다.
4. 조건절에 대한 규칙: 접근하고자 하는 테이블의 순서대로 조건절 컬럼을 나열한다.

위의 4가지 규칙을 요약하면 한 가지 규칙만 남는다. 접근하고자 하는 테이블 순서대로 쿼리를 작성하면 되는 것이다. 



[그림 4] 인덱스 생성도

위 [그림 4]는 작성해야 할 쿼리를 접근 방향에 따라 인덱스 생성도로 표현한 예시다. 인덱스 생성도를 근거로 하여 공정쿼리 기본 규칙에 따라 쿼리를 작성해 보면 다음과 같다.



SELECT A.컬럼들, B.컬럼들, C.컬럼들 → 공정쿼리 기본 규칙 1 FROM 고객 A, 주문 B, 상품 C → 공정쿼리 기본 규칙 2 WHERE A.고객번호 = B.고객번호 → 공정쿼리 기본 규칙 3 AND B.상품번호 = C.상품번호 → 공정쿼리 기본 규칙 3 AND A.고객명 = ? → 공정쿼리 기본 규칙 4 AND B.주문일자 = ? → 공정쿼리 기본 규칙 4 AND C.상품분류 = ? → 공정쿼리 기본 규칙 4



그렇다면 이렇게 작성된 공정 쿼리에서 우리가 얻는 정보(혜택)가 무엇인지 알아 보자.



SELECT A.컬럼들, B.컬럼들, C.컬럼들 FROM 고객 A, 주문 B, 상품 C ………. 테이블 접근 순서를 알 수 있다. (A → B → C) WHERE A.고객번호 = B.고객번호 ………. 조인절의 우측편 컬럼에 인덱스 생성 AND B.상품번호 = C.상품번호 ………. 조인절의 우측편 컬럼에 인덱스 생번째 접근 테이블의 조건절에 인덱스 생성 AND B.주문일자 = ? AND C.상품분류 = ?



결론적으로 우리는 공정쿼리로 작성된 쿼리에서 다음과 같은 정보(혜택)를 얻을 수 있다. 

1. 테이블의 접근 순서를 알 수 있다(플랜 정보). 
2. 조인절의 우측편 컬럼에 인덱스가 생성되어야 함을 알 수 있다(인덱스 정보). 
3. 첫번째 조건절 컬럼에 인덱스가 생성되어야 함을 알 수 있다(인덱스 정보).

공정쿼리 기본 규칙에 따라 작성한 쿼리에서 얻는 정보(혜택)는 모든 쿼리에 적용되는 것은 아니지만 대부분의 온라인 쿼리에 해당하므로 아주 중요한 의미를 가진다. 지금까지는 다른 개발자가 작성한 쿼리에 대한 이해에 많은 시간이 필요 했지만, 공정쿼리 기본 규칙에 근거하여 작성된 쿼리라면 어느 누구라도 쿼리 작성자의 의도를 쉽게 알 수 있으며 쿼리에 대한 빠른 이해가 가능하다. 

우리는 공정쿼리의 FROM 절을 통해 테이블 접근 순서를 알 수 있으며, 조인절 및 조건절을 통하여 인덱스 생성 위치를 알 수 있다. 공정쿼리에서 우리는 무엇을(What) 조회하는지 알 수 있고 어떻게(How) 플랜을 하는지, 어떻게(How) 인덱스를 만들어야 하는지 알 수 있다. 서로 다른 개발자들이 작성한 공정 쿼리에서 우리는 동일한 정보를 공유 할 수 있다. 공정쿼리는 모든 개발자가 동일한 방법과 기준으로 쿼리를 작성함으로써 무엇을(What) 어떻게(How) 할 것인지에 대한 내용을 서로 공유할 수 있게 해준다.

공정쿼리로 작성한 쿼리는 기본적인 튜닝은 완료된 것이라 보면 틀림이 없다. 단지 우리는 2가지 측면에서 확인할 필요는 있다. 첫째는 인덱스가 있어야 할 위치에 실제로 인덱스가 존재하는지 확인하는 것이다. 만약 인덱스가 존재하지 않는다면 인덱스를 생성해야 할 것이다. 둘째는 우리가 생각하는 테이블 접근 순서와 오라클 옵티마이저의 테이블 접근 순서가 일치하는지 확인하는 것이다. 만약 일치하지 않는다면 힌트절을 추가하여 올바른 테이블 접근 순서로 유도해야 할 것이다.

공정쿼리에 대해 필자가 사내에서 교육할 때 가장 많이 받는 질문이 있다. 테이블 접근 순서는 대체 어떻게 알 수 있는가? 테이블 접근 순서를 정할 때 어떠한 규칙이 있는가? 였다. 그때마다 필자는 아래의 심부름을 예로 들어 되묻곤 했다.



[그림 5] 심부름: 쌀1포대, 두부1모

쌀1포대와 두부1모를 사야 한다면 여러분들은 어떤 가게부터 먼저 방문해야 하는가? 되물으면 99%는 두부가게부터 먼저 가야 한다고 답하였다. 바로 그것이다. 여러분들은 이미 정답을 알고 있다고 답하곤 했다. 사람들은 노동력을 가장 최소화하는 방법으로 일을 한다. 마찬가지로 오라클 옵티마이저도 부하가 가장 적게 드는 방법으로 일을 한다. 사람이나 기계나 생존 방식은 동일하다. 

개발자들은 쿼리 작성과 튜닝을 별개로 구분하여 생각하는 경우가 많은데, 실제로는 그렇지 않다. 쿼리 작성과 튜닝은 단계가 구분되는 것이 아니다. 잘 만든 쿼리는 그 자체만으로 튜닝이 이미 이루어진 것이다. 공정쿼리 자체가 튜닝이 완료된 쿼리라고 말하고 싶다. 

이번 연재에서는 공정쿼리 즉 좋은 쿼리를 만드는 방법에 대해서 설명하였고 이것이 곧 튜닝의 완성이라고 말하였다. 다음 연재도 계속해서 튜닝과 관련하여 2회에 걸쳐서 구체적인 쿼리 구문 구문에 대한 튜닝 방안에 대해서 설명할 계획이다. (다음 호에 계속)



출처 : 한국데이터진흥원

제공 : 데이터 전문가 지식포털 DBguide.net

반응형