전문가칼럼

DBMS, DB 구축 절차, 빅데이터 기술 칼럼, 사례연구 및 세미나 자료를 소개합니다.

만능 쿼리와 한 방 쿼리

전문가칼럼
DBMS별 분류
Etc
작성자
dataonair
작성일
2014-12-03 00:00
조회
15967




◎ 연재기사 ◎


물탱크 구조로 알아본 오라클의 블록 옵션 ‘PCTFREE와 PCTUSED’


이산가족 찾기 생방송을 통해 배우는 DB 원리


개발자에게 맞는 DB 공부방법 찾기: 물리적 분류와 논리적 분류 그리고 인덱스


데이터베이스 인덱스의 오해와 진실


쉬운 것이 올바른 것이다. ‘인덱스 끝장리뷰’ (상)


쉬운 것이 올바른 것이다. ‘인덱스 끝장리뷰’ (하)


누구도 알려주지 않았던 ‘오라클 인덱스 생성도’의 비밀


누구도 알려주지 않았던 ‘오라클 쿼리 작성의 비법’


퀴리 최적화 및 튜닝을 위한 오라클 공정쿼리 작성법


만능 쿼리와 한 방 쿼리


오라클 옵티마이저 ‘CBO와 RBO’ 이해하기


재미있는 DB 이야기 ‘60갑자와 쿼리’


그림으로 배우는 ‘오라클 조인의 방식’ 이야기


반드시 알아야 하는 오라클 힌트절 7가지


오라클 플랜을 보는 법


개발자들의 영원한 숙제 ‘NULL 이야기’


알면 유용한 오라클 기능 ‘GATHER_PLAN_STATISTICS’


알면 유용한 오라클 기능들


오라클 DICTIONARY를 활용한 DB툴 프로그램 ‘FreeSQL’


이제는 말할 수 있다: 주식 자동매매 프로그램(상)


이제는 말할 수 있다: 주식 자동매매 프로그램(하)


개발자들이 자주 접하는 오라클 에러 메세지


재미있는 DB 이야기 ‘사라진 날짜를 찾아라’


오라클 랜덤 함수와 사용자 정의 함수


그림으로 배우는 ‘공정쿼리와 인덱스 생성도’


이병국의 개발자를 위한 DB 이야기: 디폴트 세팅의 함정과 오라클 파라미터


재미있는 DB 이야기 ‘놀라운 마방진의 세계’


오라클 운반 최소 단위 BLOCK


이병국의 개발자를 위한 DB 이야기: 이세돌과 알파고의 세기의 대결


이병국의 개발자를 위한 DB 이야기(30회) : DB 엔지니어의 가볍게 읽는 세상 이야기


이병국의 개발자를 위한 DB 이야기: 튜닝(31회) : 개발자를 위한 DB 튜닝 실전(1편)


이병국의 개발자를 위한 DB 이야기: 튜닝(32회) : 개발자를 위한 튜닝 실전(2편)


이병국의 개발자를 위한 DB 이야기: 튜닝(33회) : 개발자를 위한 튜닝 실전(3편)


이병국의 개발자를 위한 DB 이야기: 튜닝(34회) : 개발자를 위한 DB 튜닝 실전(4편)


이병국의 개발자를 위한 DB 이야기: 튜닝(35회) : 개발자를 위한 튜닝 실전(5편)


이병국의 개발자를 위한 DB 이야기: 페이징 처리에 대한 이해 (36회)


보기 좋은 떡이 먹기도 좋다 - 좋은 쿼리 좋은 성능


테이블의 수직분할과 수평분할에 대한 이해


DB 성능 제고를 위한 채번의 이해와 방식별 장단점 비교


이병국의 개발자를 위한 DB 이야기: 마지막회 : ‘개발자를 위한 DB 이야기’ 연재를 마치며



이병국의 개발자를 위한 DB 이야기: 쿼리 (10회)

만능 쿼리와 한 방 쿼리



이병국 andongcn@dreamwiz.com 프리랜서 DB 엔지니어로서 동아제약 전산실에서 SW 개발 업무를 시작으로 프리랜서 개발자로 독립해 활동하던 중 우연한 기회에 DB와 인연을 맺게 됐다. 현재 삼성생명 전산 운영팀에서 쿼리 성능을 개선하는 DB 튜닝과 IOA 업무를 맡고 있다. 개발자 출신의 DB 엔지니어로 활동하면서 개발자에게 DB 관련 지식이 꼭 필요함을 절감했다. ‘정보의 불균형이 시장 왜곡을 가져온다’는 ‘레몬시장이론’은 중고차 거래에서 흔히 나타나기 쉽다. 좋은 차와 나쁜 차를 아는 중개인과 모르는 구매자 사이에는 정보의 비대칭 때문에 구매자가 손해를 볼 수 있다. 구매자도 차에 대해 기본적인 지식을 알고 있어야, 정보의 균형이 맞으므로 서로 손해를 보지 않고 합리적인 가격에 차를 거래할 수 있다. 마찬가지로 개발자들도 DB에 대해 기본적인 지식을 습득하여 정보의 균형을 맞추면, DB 엔지니어와 협업이 더 쉬워지고 한 단계 더 발전한 자신의 모습을 발견할 것이다.



성공과 실패의 경험을 나누자, 용기와 희망을 나누자
개발업무를 시작으로 IT계에 입문했던 필자가 10년 가까이 DB 엔지니어로서 활동하면서
얻은 경험과 지식을 나누고자 한다. DB를 자주 접하는 SW 개발자뿐 아니라,
DB 전문가를 꿈꾸는 대학생에서 DB 분야에 입문한 지 1~2년 된 기 입문자가
쉽게 이해할 수 있도록 비유를 통해 쉽게 접근해볼 계획이다. 물론 전문가들이라도
다시 한번 개념을 정립하는 의미에서 필요한 내용이 될 수 있다.
전체적으로 DB의 기본 원리와 개념을 이해하고 테이블, 인덱스, 쿼리, 튜닝, 플랜 등
개발자들이 알아야 하는 DB 전분야에 대해 쉽게 이해하도록 설명하겠다.
DB 기술서적이나 번역서보다는 조금 더 부드럽게 접근할 계획이다.
그렇다고 흔히 서점에서 만날 수 있는 개발자 위주의 SQL 소개서도 아니다.
이 연재는 시리즈로 나갈 것이다. 연재를 끝까지 읽는 독자라면, 준전문가 수준의 DB 원리를 아는 것을 목표로 한다.

이번 연재에서는 만능 쿼리와 한 방 쿼리에 대해서 소개한다. 지향해야 할 쿼리 제작 방법과 지양해야 할 쿼리 제작 방법에 대해 설명 하고자 한다.



‘나쁜 사람이 세상을 발전시킨다‘

위의 말에 동의하지 않는 사람들도 많겠지만 하나의 설로 이해하자. 인류 역사에서 나쁜() 사람은 수없이 많았다. 그 나쁜 사람 때문에 인류 역사는 달라지기도 하였다. 그것이 좋은 역사든 나쁜 역사든 별개의 문제다. 로마의 네로 황제에 의해 로마의 2/3가 불탔고, 시민들은 엄청난 피해를 입었다. 하지만 큰 화재 후에 좁고 복잡한 골목길과 수로는 넓게 확장되었고, 도시가 계획적으로 재건축되었다. 큰 화재 이후 도시 전체가 이전보다 더 아름답고 웅장하게 바뀌었다. 로마의 후손들은 선조들의 피땀으로 이뤄진 도시 건축물이 세계적인 관광 유산이 되어 그 혜택을 톡톡히 보고 있다.

또한 세계 7대 불가사의한 건축물 중에서 현존하는 피라미드, 만리장성, 마추픽추, 타지마할, 콜로세움 등은 세계적으로 유명한 관광자원이 되어 해당 국가의 이미지와 재정에 도움을 주고 있다. 하지만 과거 이러한 건축물을 짓기 위해 많은 사람의 희생이 있었을 것이라는 데에는 의심의 여지가 없다. 그리고 그 희생자들 뒤에는 희생을 강요했을 장본인이 반드시 있었을 것이다.

최근의 예를 든다면, 2차 세계대전에서 패망한 독일의 앞선 무기 기술을 미국과 소련이 경쟁적으로 가져가서 자국의 첨단 무기 기술로 발전시켰다. 2차 세계대전을 겪으면서 인류는 레이더, 스텔스, 로켓, 인공위성, 무선기술 등 수많은 과학 기술을 얻게 되었다. 적을 파괴하고자 연구되었던 기술들이 인류의 과학 기술을 진일보시켰다. 그러한 기술의 발전은 현재 전 인류에게 생활의 편리함과 이익을 주고 있다.

구석기 시대에서 신석기, 청동기, 철기를 거치면서 문명의 발전이 굉장히 더디게 진행되다가 근·현대에 이르러 기술의 발전 속도가 가파른 상승 곡선을 그리고 있다. 인류 전체 역사의 99% 기간 동안 1% 정도의 문명 발전을 서서히 이루다가 최근 1% 기간에 99% 문명 발전을 이뤘다고 한다. 가히 폭발적이라 할 수 있다. 나쁜 사람이 기하 급수적으로 늘어난 것은 아닐까 씁쓸한 생각을 지울 수 없다.

이번 연재의 주제는 ‘만능 쿼리’와 ‘한 방 쿼리’에 대한 내용이다. 무엇이 좋고 무엇이 나쁜지 또한 무엇이 서로 다른지 비교하고 이해하는 시간을 가져 보자. 쿼리는 좋은 쿼리도 있고 나쁜 쿼리도 있을 수 있다. 나쁜 쿼리라고 해서 그냥 무시할 것이 아니라, 그 안에서 뜻하지 않게 좋은 아이디어를 얻을 수도 있다. 비록 현재의 DB 기술로는 어쩔 수 없이 나쁜 쿼리로 인식되지만, 향후 DB 기술의 발전에 따라 그 나쁜 쿼리가 좋은 쿼리로 새로 주목 받을지 누가 알겠는가!



만능 쿼리에 대한 이해

우리가 일반적으로 알고 있고 또한 가장 많이 사용하는 쿼리는 정적 쿼리다. 정적 쿼리는 조건들이 고정돼 있으며 플랜도 고정돼 있으므로 성능 문제 발생 시 조치와 대응이 쉽다. 이에 비해 동적 쿼리는 조건 자체가 가변적이기 때문에 적절한 튜닝으로 대응 하기가 곤란하다.

동적 쿼리는 애플리케이션 소스상에서 사용할 조건들을 가변적으로 구성하는 쿼리를 말한다. 이러한 동적 쿼리는 그 위험성을 간과한 채 애플리케이션에서 자주 사용되고 있는 것이 현실이다. 물론 소스코드가 간단하다는 이점도 있지만, 악성 쿼리로 바뀔 가능성도 배제할 수 없다. 동적 쿼리는 이번 연재 내용 중 하나인 만능 쿼리와 전체적으로 동일한 의미를 가진다. 물론 약간의 다른 면도 있다. 아래 그림은 동적 쿼리와 만능 쿼리에 대한 간단한 예제다.

column_img_1563.jpg

동적 쿼리는 하나의 쿼리가 아니다. 위의 동적 쿼리는 7가지 조건절이 가변적으로 변하므로 128가지의 쿼리로 나눌 수 있다. 오라클 옵티마이저가 128가지의 모든 쿼리에 대해 플랜을 제공하지만, 모든 플랜의 성능을 보장하지는 못한다. 즉 실행 계획을 완벽하게 통제하기가 어렵다는 의미다.

이에 더해 만능 쿼리는 동적 쿼리보다 더 심각하다. 위의 예시인 만능 쿼리는 조건절이 가변적이지는 않다. 그래서 오라클 옵티마이저에게는 하나의 쿼리로 인식되고, 하나의 플랜만 우리에게 제공할 것이다. 하지만 조건값에 따라서 실제로는 128가지의 쿼리로 구분될 수 있음을 우리들은 알고 있다. 128가지의 쿼리가 오직 하나의 플랜만으로 실행된다면 얼마나 심각한 악성 쿼리인지 충분히 알 수 있다.

그렇다면, 왜 개발자들은 동적 쿼리 혹은 만능 쿼리로 작성하는 것일까

첫째, 개발 일정이 촉박하여 최소한의 개발 시간을 보장 받지 못하기 때문이다.
둘째, 애플리케이션 소스 코드가 간단해서 그 유혹에서 벗어나기 쉽지 않기 때문이다.
셋째, 고객이 원하는 모든 요구사항을 한 번에 해결하고자 하는 개발자의 강박감이 있기 때문이다.

만능 쿼리를 가만히 들여다 보면, 필자도 솔직히 반할 때가 있다. 비록 잠깐의 유혹이지만 벗어나기 쉽지 않은 쿼리다. 이렇게 쉬운 쿼리로 작성하면 얼마나 편할까

다시 현실로 돌아오면 내 앞엔 해결할 수 없는 쿼리가 놓여 있다. 현재의 오라클 알고리즘과 현재의 지원 가능한 시스템 자원으로는 이러한 만능 쿼리의 문제점을 해결해 주지는 못한다. 향후 가까운 미래에는 가능할지도 모른다. 지금 개발을 시작하는 초년생 개발자에게는 만능 쿼리가 꿈의 쿼리이고 완벽한 쿼리처럼 보일지도 모른다. 그런 날이 오기를 바랄 것이다. 하지만 필자는 그런 날이 영원히 오지 않았으면 좋겠다. 그런 날이 온다는 것은 내 존재 가치가 엷어지기 때문이다. 여러분의 존재 가치 또한 엷어지지 않을까^^ 사람의 손이 필요치 않는 그런 세상이 올까 두렵다.

동적 쿼리에서는 실행 계획을 통제하기 위해 UNION ALL을 이용해 쿼리를 분리한다는 내용을 책에서 본 적이 있다. 그 방법이 효과적인 해결 방법인지는 솔직히 필자도 잘 모르겠다. 반면 만능 쿼리는 해결 방법이 없다. 사용하지 않는 것뿐이다. 만약 꼭 사용해야 한다면, 소규모 작은 테이블이면서 업무 담당자가 다양한 조건 검색을 원할 때뿐이다. 그 외에는 절대 사용해서는 안된다.

만능 쿼리는 사용해서는 안되는 쿼리다. 비록 수많은 조건절을 BETWEEN이나 LIKE 문을 이용해 하나의 쿼리로 통합해 한 번에 해결하려는 유혹이 있을 수 있다. 하지만 그것은 올바른 방법이 아니다. 핵심 조건절의 수만큼 쿼리 자체를 분리해야 한다. 핵심 조건절 이외의 조건절은 부가적인 조건절이므로 BETWEEN이나 LIKE 문을 사용해도 무방하다. 여러분들은 만능 쿼리의 유혹에서 벗어나야 한다.

요즘 은퇴하는 사람들에게 귀촌이 대세가 되고 있다고 한다. 귀촌하면서 집 한 채를 지으면 없던 종교를 갖게 되고, 그렇지 않으면 거의 도인의 경지에 이르게 될 정도로 마음 고생이 심하다는 소리가 있다. 건축업자와의 밀고 당기기, 인허가와 관련하여 관청과의 싸움, 건축사무소와의 여러 절차적인 실랑이 등을 해야 하기 때문이란다. 그런 의미에서 필자가 요즘 튜닝에 있어서 도인이 되었다. 만능 쿼리 앞에서 도인이 되었다. 여러분! 만능 쿼리… 사용하지 맙시다. ㅠㅠ



한 방 쿼리에 대한 이해

프로그래머는 절차적이고 구조적인 사고를 가져야 한다. 유능한 프로그래머는 한 라인, 한 라인 단계적으로 처리하는 절차적 언어의 전문가다. 반면 데이터베이스 개발자는 집합적 사고를 가져야 한다. 쿼리를 작성해 한 방에 원하는 결과를 추출하는 집합적 사고력이 필요하다.

여러분은 프로그래머에 가까운가 데이터베이스 개발자에 가까운가
유능한 프로그래머인 당신! 혹시 쿼리를 절차적인 구조로 작성하고 있지 않는가
유능한 데이터베이스 개발자인 당신! 혹시 프로그램을 집합적 사고로 작성하고 있지 않는가

유능하든 유능하지 않던 그것은 중요하지 않다. 프로그램은 절차적인 구조로 작성하고, 데이터베이스 개발은 집합적인 사고로 작성하는 유연성이 필요하다. 많은 개발자가 프로그램 개발과 데이터베이스 개발을 병행하면서 한쪽으로 치우치는 경향이 있다. 이에 대한 균형이 필요하다. 아래 그림은 한 방 쿼리에 대한 간단한 예제이다.

column_img_1564.jpg

위의 쿼리는 검색 기간에 해당하는 월별-연별 통계를 한방으로 조회·정렬하는 쿼리다. 비록 몇 줄 되지 않는 간단한 쿼리지만, 만약 숙달되지 않는 프로그래머가 절차적인 사고로 구현하려 한다면 수백 라인 이상의 소스 코드와 수많은 쿼리를 수행해 해결해야 할 만큼 쉽지 않는 쿼리다.

예전에 절차적인 언어에 익숙해 있던 코블 세대 선배들은 데이터베이스를 개발할 때 조인을 사용하지 못하게 하기도 했다. 당시 ‘메인 쿼리와 서브 쿼리를 분리해 결과를 조회하는 방법이 성능상의 이점이 있다;는 잘못된 내용을 전파하기도 했다.

만약 여러분이 필요로 하는 내용에 대한 한 방 쿼리를 구현하고 싶은데 좋은 방법이 잘 떠오르지 않는다면 ‘데이터베이스 사랑넷(http://database.sarang.net)’에서 도움을 구하기 바란다. 사랑넷은 필자가 가장 많이 이용하는 사이트로서 개발자에게는 매우 유용한 DB 사이트다. 재야의 숨은 고수로부터 도움을 받을 수 있을 것이다. 특히 ‘마농’이라는 분은 재야의 숨은 고수임에 분명하다. 얼굴도 이름도 모르지만 개인적으로 존경한다.

집합적인 사고를 필요로 하는 한 방 쿼리는 개발자에게 매우 유용한 쿼리 제작 방법이고, 사례별로 틈틈이 익히고 숙지해야 하는 노하우다. 그렇다고 모든 쿼리가 한 방 쿼리로 작성돼야 하는 것은 아니다. 때론 너무 한 방 쿼리에 매달리다 보면 절차적인 쿼리보다 오히려 못할 때가 있을 것이다. 너무 넘치면 모자람만 못하다는 것을 명심하자.

오늘 연재를 통해 우리는 한 방 쿼리와 만능 쿼리에 대해 알아 보았다. 어떤 것을 지향해야 하고, 어떤 것을 지양해야 하는지 살펴 보았다. 다음 연재에서는 오라클의 RBO 방식과 CBO 방식에 대해서 알아 보겠다.



용기를 갖자

오라클 DB뿐 아니라 대부분의 DB 구성 알고리즘은 어느 날 ‘하늘에서 뚝 떨어져 새로 만들어진 것’이 아니라 실생활에서 이용되는 혹은 이미 상식 수준에서 인지되는 그런 보편적인 원리를 바탕으로 만들어졌으므로 쉽게 접근하고 이해할 수 있다. 서두에서 말했듯이 ‘레몬시장이론’을 상기하며 DB를 지레짐작으로 어려워하지 말고 용기를 내고 하나씩 터득해 나가기를 바란다.

이 글은 DB 전문가 수준의 이해를 요구하지는 않는다. 단지 DB에 대해서 더 친숙하고 더 쉽게 이해하고 접근하길 바랄 뿐이다. 이 글을 읽으면서 궁금하거나 의문 나는 점이 있으면, 댓글을 달아주실 것을 적극 바란다. 아무리 어렵고 힘든 일이더라고 ‘관계’와 ‘소통’으로 풀어나갈 수 있음을 다시 한 번 믿으며...



[지난 문제의 정답과 풀이]

원리를 이해하고 논리로 풀어가는, 쉬어가는 DB 문제

지난 연재에 출제한 ‘원리를 이해하고 논리로 풀어가는, 쉬어가는 DB 문제’에 대한 정답과 해설은 아래와 같다. 문제를 풀면서 DB 원리를 하나씩 배우고 이해할 수 있다.

column_img_1565.jpg



[이번 호 문제]

원리를 이해하고 논리로 풀어가는, 쉬어가는 DB 문제

각 연재의 말미에 간단하면서도 재미있고 생각해 보는 문제를 출제하려 한다. 모든 문제는 DB의 원리를 이해할 수 있는 문제로 출제할 예정이다. 문제를 풀면서 DB 원리를 하나씩 배우고 이해할 수 있다. 정답과 그에 대한 설명은 다음 연재에서 한다.



column_img_1566.jpg