SQL 문의 특징과 이를 잘 다루는 법

데이터베이스를 다루는 애플리케이션이라면 예외 없이 사용하는 것이지만, 그 사용법이 틀리면 고생하는 것은 사실이다. SQL 문의 사용법에 대한 요점과 장점 및 단점을 알자보자.

# 테이블 조작하기

SQL은 실로 심오한 언어이다. "SELECT 문이란 무엇인가?"와 같은 초보적인 이야기는 많은 독자들에게 있어 그다지 필요가 없으리라 생각한다. 그래서 이 장에서는 어느 정도 현장에서 사용할 수 있는 실용적인 이야기를 중점으로 설명하고자 한다. RDBMS로는 무엇을 사용해도 좋지만, 여기에서는 무료 데이터베이스 중 가장 널리 사용되고 있는 MySQL로 동작 시켜 보겠다. 

직원 부서 정보를 취급하기 위한 테이블 구성도

테이블 작성하기

데이터베이즈 제품 간의 호환성 확보가 힘들다.

특정 RDBMS에서는 동작하는 것이 다른 RDBMS에서는 동작하지 않거나 한다. 세세한 부분에서 RDBMS 같의 차이가 있기 때문이다. 특히 데이터형의 차이가 크다. MySQL의 문자열형에서는 VARCHAR형, 긴 것에는 TEXT 형식을 사용하는데, Oracle에서는 VARCHAR2형, 긴 것에는 LONG형 등을 사용한다. 또한 동일 RDBMS임에도 의미가 변하는 경우가 있다. MySQL의 이전 버전에서는 VARCHAR의 숫자가 바이트 제한을 의미했다. 그러나 이후 버전에서는 문자 수의 제한을 의미하는 등 동일 RDBMS에서도 그 의미가 변하였다. -> 실제로 과도한 표준화에 연연하지 않는 편이 좋다. 왜냐하면 데이터형의 선택이 성능에 직결되기 때문이다.

한번 만든 테이블은 쉽게 바꿀 수 없다.

어플리케이션으로부터 일체 정지 없이 테이블의 칼럼을 추가하거나 삭제가 쉽지 않다. 업데이트가 모두 차단되거나 체품에 따라서는 참조조차 차단되어 버리는 것도 있다. 

INSERT 문 / SELECT 문 / UPDATE 문 / DELETE 문을 사용하여 데이터 조작

분산 데이터 환경과 조인 궁합

대규모 애플리케이션에서는 특정 테이블로의 트래픽이 매우 커서 한 개의 서버에서 처리를 충분히 끝낼 수 없기 때문에 테이블 단위로 여러 서버에 분산하는 겨우가 있다. 이러한 분할을 특히 샤딩이라고 한다. -> 샤딩을 하고 있으면 조인을 사용하기 어렵다. 왜냐하면 결합 대상 테이블 혹은 레코드가 반드시 같은 서버에 있다고 할 수 없기 때문이다. -> 대규모가 될 것으로 예상되는 어플리케이션은 샤딩의 필요성을 처음부터 염두에 두고 거대하게 될 것 같은 테이블과 조인을 하지 않도록 애플리케이션을 작성하는 방법이 자주 사용되고 있다.

조인은 느린가?
sql문이 복잡하면 복잡할수록 개발자에 있어 정확하고 빠른 쿼리를 작성하는 것은 고충이다. 그러나 모든 것을
단일 테이블에서의 참조만으로 끝내도록 하면 SQL 문의 실행 회수가 증가하게 되므로 주의가 필요하다.
조인이면 한 번만으로 끝날 것이 SELECT 문을 100번 실행하는 처지가 되는 경우도 드물지 않다. 물론
네트워크 부하 및 서버 부하도 증가하기 때문에 효율이 떨어진다.

=> 결론

SQL문을 잘쓰자. 사용법에 대해서 알아보았다. Join은 반드시 나쁜것은 아니다 적절히 사용해야 한다. 

SQL 문의 실행 효율 의식하기

데이터베이스를 우선 동작할 수 있다라는 것과 애플리케이션으로서의 기능을 재대로 빨리 사용한다는 다른 이야기다.

적절한 인덱스가 사용되고 있는지 확인

고속의 SQL문을 작성하는 데 있어서 중요한 것은 여러가지가 있지만, 그 중에서도 가장 중요하다고 말할 수 있는 것이 적절한 인덱스를 사용하도록 하는 것이다. 예를 들어 사원 번호에 인덱스가 되는 기본 키가, 그리고 사원 로마자에도 인덱스가 정의 되어 있기 때문에 빠른 결과를 반환할 수 있다. -> 한편 이것들 이외의 열만을 WHERE 조건으로 지정한 검색은 인덱스를 사용할 수 없다. 인덱스를 전혀 사용할 수 없는 경우는 테이블 전체의 레코드를 검색해야만 결과 일치 여부를 판정할 수 있다. 테이블이 거대한 경우 이 작업은 매우 무거워진다. 무거운 처리가 되면 실행 되는 동안에 다른 작업에도 영향을 주게 되기 때문에 서비스 다운을 초래하는 일이 많아진다. 

EXPLAIN

데이터베이스 제품에서는 이러한 SQL문의 실행 방식이 적절한지 여부를 실제로 실행하지 않고 판정만 해주는 기능을 가지고 있다. 그것이 EXPLAIN이다. 주목하고 싶은 것은 표시 순서와 table, type, key, ref, rows이다. 아주 대략적으로 말하자면, 대부분의 경우 여기에 나와 있는 rows의 값이 실제로 데이터베이스 레코드에 액세스되는 횟수가 된다. (추정치로 어디까지나 기준 값이다.) 이번 경우는 등장하는 모든 테이블에서 rows가 1이므로 각 테이블 모두 1 레코드밖에 액세스하지 않는 것을 알 수 있다. 이것이 가장 액세스 효율이 좋은 패턴으로, 조인을 이러한 형태로 할 수 있으면 매우 고속이 된다. 인덱스를 제대로 사용하지 않는 경우 전체 테이블 검색을 할 수 밖에없게 되어 rows 값이 커지고 시간이 걸리게 된다. 실행하기 전에 EXPLAIN을 처리해 봄으로써 그러한 나쁜 쿼리를 사전에 찾아낼 수 있게 되는 것이다.

쿼리분석도구

EXPLAIN은 분명히 응답 속도가 느린 SELECT 문 등 체감적으로 분명히 문제가 있는 것들에 대해서 그 실행 효율을 분석하는 데 도움이 된다. 한편, 다양한 쿼리를 실행하는 애플리케이션을 운용해 나가다 보면 도대체 어느 쿼리가 느린가? 라는 점에서 고민을 하게 된다. EXPLAIN을 실행하기 전에 먼저 어떤 쿼리가 수상한지 찾을 필요가 있다. 

관리계 명령

데이터베이스에 대해 수행할 작업은 테이블을 만들거나 내용을 조작하는 것만이 아니다. 시스템을 오랫동안 운용하고 있으면 데이터베이스의 안정성과 성능이 이상하게 되는 경우도 적지 않은 법이다. 이럴 때에 테이블의 내용이 아니라 데이터베이스의 내부 구조에까지 깊게 발을 디뎌 해석하고 싶은 경우도 많다.

  • 초당 몇 차례의 SELECT/INSERT/UPDATE/DELETE를 실행하고 있는가?
  • 초당 몇 개의 레코드를 읽고 있는가?
  • 초당 몇 차례의 무거운 쿼리가 실행되고 있는가?

상당수의 데이터베이스 제품에서는 이러한 조작 또한 sql문으로 사용할 수 있도록 되어있다.

=> 결론

성능을 향상시키는데 있어서 인덱스는 중요한 역할을 한다. EXPLAIN과 쿼리 분석 도구를 활용하여 어떠한 쿼리 혹은 테이블을 조회할 때 성능이 느려지는지 파악해보자.

SQL의 장점과 단점

프로그래밍 언어에서 데이터 구조를 조작하는 경우에 비하여 SQL문을 사용하여 데이터베이스에 액세스하는 작성법은 다양한 장점과 단점이 있다. 여기에서는 조작성과 기능명의 측면에서 설명하고자 했다.

SQL은 기술 습득이 용이하다

SQL의 문의 큰 장점 중 하나는 사용법이 간단하다는 점이다. SQL문은 직관적이고 영문 그대로 의미가 통하므로 알기 쉽다. 최근 NoSQL이라는 SQL 인터페이스가 없는 ( 대신 고속의 ) 데이터베이스가 주목을 받고 있다. 이러한 제품은 SQL 문으로 조작할 수없기 때문에 주로 자신이 직접 프로그래밍 언어를 구사하여 데이터를 검색하거나 조작한다.

  나쁜 SQL문을 작성하면 성능이 안좋은 문제도 있긴 하지만 그것은 프로그램을 짜는 경우도 동일하다. 대규모 프로젝트 등에서는 SQL 문을 모두 전용 설정 파일에서 일괄 관리해 두어 튜닝 시 그 부분을 철저히 검토한다는 방침을 취하고 있는 경우도 있다. NoSQL과 기존의 관계형 데이터베이스의 차이점과 차별점에 대해서는 제 11장에서 고찰하도록 하겠다. 

하지만 SQL도 심오하다.

SQL은 습득이 용이한다고는 했지만 그것은 어디까지나 `일단 사용해 보는 수준에 도달하는 데까지`의 이야기이다. 대량의 데이터를 취급하는 데이터베이스에서는 종종 성능이 나오지 않는다. 10시간이 지나도 쿼리가 끝나지 않는다 등의 문제가 발생하는 경우도 있다. 왜 이런 문제가 일어나는지 이해하려면 데이터베이스 아키텍처와 인덱스 구조, 디스크와 메모리의 속도 차이 등 다양한 관점에서의 이해가 필요하다. 

기능면

SQL 문은 편리한 언어지만 모든 처리를 간단하게 기술할 수 있다는 뜻은 아니다. 데이터를 반환하는 것뿐만 아니라 업무 로직을 사이에 넣고 싶으면 SQL 구문으로 로직을 기술하는 것이 곤란한다. -> 데이터베이스를 제공하고 있느 저장 프로시저를 이용하면 다소 복잡한 로직을 구현할 수 있다. 이러한 기능을 적극적으로 이용하면 SQL만으로는 할 수 없는 것들도 실현할 수 있다.

  저장 프로시저는 데이터베이스 서버에서 동작한다. 따라서 수십 번 실행해야 하는 SQL 문 대신 이들을 정리한 저장 프로시저를 한번만 호출하는 사용법을 이용하면 네트워크 액세스 빈도를 크게 줄일 수 있다. 이것은 성능을 크게 높이는 효과가 있으며, 특히 네트워크가 느린 10여 년 전에는 애용되기도 하였다. 그러나 최근에는 저장 프로시저를 사용하는 일이 적고 일반적으로메일 전송과 같은 로직은 Perl과 같은 애플리케이션 층에서 실현한다. -> 로직은 프로그래밍 언어, 데이터 조작은 SQL에 분담시키는 큰 이유는 프로그래밍 언어 쪽이 SQL 및 저장 프로시저보다 개발환경이 압도적으로 충실하다는 점에 있으며, 데이터가 없는 웹 서버 쪽이 데이터가 있는 데이터베이스 서버보다 쉽게 증가하고 있기 때문에 기동력이 높다라는 점을 들을 수 있겠다. 개발 환경이 풍부하다라고 하는 것은 생상성 측면에서 매우 큰 요소이다.

-> 대규모 웹 서비스 등에서는 특정하게 한정된 로직이 매우 높은 빈도로 불리는 경향이 있다. 그런 특수한 처리만을 고속의 저장 프로시저로 최적화하는 것은 최근의 경향이다.

SQL문의 특징에 대해 알아보았다. 프로그래밍 언어를 쓰는 것에 비하면 쉽게 레코드를 조작할 수 있으므로 
일반 사용자에게는 친숙하다고 할수 있다. 조인은 잘 사용하면 성능을 높일 수 있다. 한편, 기능 면에서는
부족한 부분도 있는데, 특히 여러 서버와 연계한 처리를 조인을 실현하기 어렵다는 점이 과제로서 존재한다.
  또한, 트래픽이 매우 높은 환경에서는 sql문을 실행한다 라는 프로세스 자체가 큰 처리비용이 될 수도 있다.
최근 트랜드로 원격 서버에 걸친 액세스를 조인으로 쓸 수 있도록 한다 라는 방식이나, SQL 문이 아니라 
프로그래밍 언어를 이용하여 보다 빠른 결과를 취하는 것에 대한 접근이 주목을 받고 있다. 

=> 결론

한번에 확 와닿은 챕터는 아닌 것 같다. 처음 진입에 있어서 SQL문의 사용법이 직관적이라는 점에서 쉽게 배울 수 있지만 깊은 이해는 어렵다. 데이터베이스만을 사용하면 모든 것을 해결할 수 는 없다.

BELATED ARTICLES

more