티스토리 툴바


Static SQL2009/02/01 05:27
Static SQL에 대한 연재를 하자면 왜 Static SQL을 사용하여야 하는가에 대한 설명이 있어야하지 않겠는가?
어쩔 수 없이 글을 길게 쓰게 됬지만 긴 글을 읽기 싫은 분들은 결론만 읽으셔도 되겠다.

Static SQL과 Dynamic SQL
DBMS는(정확히 말해서는 Optimizer는) 다음과 같은 SQL을 다 다른 SQL로 처리하며 이를 Dynamic SQL이라고 한다. 
nSelect * From Table1 Where Column1 = 1
nSelect * From Table1 Where Column1 = 2
nSelect * From Table1 Where Column1 = 3
(일부 DBMS에서는 이것을 자동으로 변수처리해주기도 하는데 복잡한 SQL에서는 기대할만한 기능이 아니다.)

반면, Static SQL은 위와 같은 SQL을 다음과 같이 작성한다.
Select * From Table1 Where Column1 = :v1
:v1과 같은 방식을 Parameter Binding이라고 하며 변하는 부분을 변수처리한 것이라고 생각하면 되겠다.
Parameter Binding == Static SQL은 아니지만 오늘 이야기할 내용은 그렇게 이해해도 충분하리라 생각한다.


SQL의 수행과정
SQL은 어떤 단계를 거쳐 수행되는 것일까?
물론 SQL문은 원하는 집합을 규정하는 언어일 뿐, 처리 방법을 기술하는 언어는 아니다. 하지만 실제로는 수행되는 절차가 있는데 이에 대해서 한번 알아보자.

Oracle기준이며 DML문과 DDL문은 수행방법이 약간 다른데 Select문과 같은 DML문에 대해서만 언급하도록 하겠다.
1. 파싱(구문/의미검사)
    1) 구문검사 : SQL 문법에 맞는가? 예를 들어 Select를 Selct라고 오타가 난 경우 여기서 Error를 발생한다.
    2) 의미검사 : SQL이 실행가능한가? 컬럼명이나 테이블명이 명확하고 애매함이 없는가?
    3) 공유풀검사 : 이미 실행계획이 세워져 수행된 Query인지 공유풀(Shared Pool)을 검사하고 세워진 실행계획이 있다면 
                         이를 재사용하여 실행전단계까지 건너뛴다.(소프트파스)

2. 실행계획 수립
실행계획이란 SQL을 수행할 순서를 말한다. Table1과 Table2가 Join을 하고 있다면 Nested Loop Join방식으로 처리할 것인지 Sort Merge Join으로 처리할지 Hash Join일지를 결정한다.
또한, Nested Loop Join이라면 Table1을 먼저 Driving(읽을)할 것인지 어떤 Index를 사용할 것인지... 등등을 결정하게 된다.
실행계획은 Optimizer가 세우게 되는데 그 Optimizer가 RBO(Rule Based Optimizer)인지 CBO(Cost Based Optimizer)인지에 따라 실행계획을 세우는 방법은 다르지만 어쨋든 실행계획은 이 단계에서 수립된다.

잘 이해가 안된다면 Optimizer가 실행계획이란 것을 세우고, 그 계획에 따라 SQL이 처리된다는 것만 이해하고 넘어가자. 여기서 설명하고자 하는 요점은 바로 그 것이다.

3.  Parameter Binding 및 실행
Parameter 처리된 실제 값을 적용하고 SQL을 실행한다.


실행계획 수립의 비용
이 실행계획 수립은 비용이 많이 드는 연산이다. 이 단계를 건너뛸 수 있다면 우리는 상당한 시간을 절약할 수 있을 것이다.
또한 하나의 실행계획을 세우기 위해서는 공유풀에 접근하여 현재 사용가능한 Index가 어떤 것이 있는지 Column의 분포도가 어떠한지를 살펴보아야 한다. 하지만 이러한 구조을 살펴보기 위해서는 이 구조에 대한 다른 접근을 막아야 한다. Index를 타는 것이 타당한지 살펴보고 있는데 다른 사용자가 Index를 지운다고 생각해보자. 당연히 문제가 발생하지 않겠는가.
따라서 이런 구조에 대한 접근은 직렬화되며 따라서 실행계획을 수립하기 위한 SQL이 많다면 자신의 차례가 올때까지 기다려야 한다.


실행계획 확인의 비용
어느날 DBA가 어떤 Table에 하나의 Index를 더 만들겠다고 선언했다. Optimizer는 새로운 Index가 생겼으므로 기존의 실행계획을 다시 검토해볼 수 있다. 따라서, 우리는 그 Index가 그 Table을 접근하는 SQL의 실행계획에 영향을 주지 않는지 검토해보아야 할 것이다. 하지만, Dynamic SQL을 사용한 경우에는 확인 자체도 그리 만만하지 않다.
예를 들어 Where절을 동적으로 결합하기 위한 if/else 문이 2개가 있다고 하면 그 경우의 수는 4가지이며 그 4가지 경로에 대한 실행계획의 변경을 재검토해보아야 할 것이다.(3개라면 경우의 수는 8개이다.)
하지만 Static SQL은 하나의 SQL로 모든 것을 처리하므로 하나의 SQL에 대한 실행계획만 검토해보면 된다.


Parameter Binding과 SQL Injection
Parameter Binding 방식은 SQL Injection을 방지하는 한가지 방법이다. SQL Injection이란 Query에 SQL을 주입하여 원하지 않는 행동(Admin 권한 획득 혹은 Table Drop 등)을 할 수 있는 악의적인 보안 Issue 중 하나이다.
SQL Injection만으로도 엄청난 주제이니 관련 사항은 인터넷을 찾아보기 바란다.


왜 Static SQL인가
공유풀을 적절히 활용하고, 보안문제도 손쉽게 해결할 수 있으며 Debugging 혹은 실행계획 검토도 쉽게 만들어줄 수 있는 방식이다. 이 방법을 몰랐다면 모르지만 알면서도 사용하지 않는다면 꿈에 Optimizer가 나타나서 괴롭힐지도 모른다.-_-
Dynamic SQL은 Toad와 같은 DB 개발 Tool에서는 사용해도 무방한 방식이지만 프로그램에 의해 자주 사용되는 SQL이 Dynamic SQL이어서는 안될 것이다.

물론 단점도 있다.
처음 예로 든 SQL은 누가 봐도 이해할 만하지만 알다시피 현실세계의 문제들은 그리 간단하지 않다. SQL이 복잡해지면 질수록 Static한 SQL은 더더욱 복잡해진다. 따라서 일부 사람들이 가독성의 문제를 제기하기도 한다. (필자의 경우에는 if/then/else를 사용한 SQL이 더 가독성이 없다고 생각한다.) 가독성에 대한 문제제기를 받았다면 이 포스트를 참고하라.
또, CBO는 Parameter Binding된 변수에 대해 통계정보를 활용하지 못한다. 이에 대해서는 이후에 다시 설명하게 될 것이다.

하나 하나의 주제만 해도 수십페이지는 될 내용을 한 번에  요약하였으니, 잘 이해가 안 갈만도 하다. 이해가 안가는 부분이나 용어는 인터넷에 많은 자료들이 있으니 한번 찾아보기 바란다.
무책임해서 미안하다.-_-

다음 포스트부터는 이제 본격적으로 Static SQL을 뒤집어보자.

블로그코리아에 블UP하기
Posted by 막장개발자

TRACKBACK http://rtti.tistory.com/trackback/4 관련글 쓰기

댓글을 달아 주세요