안녕하세요 투자하는 개발자 투개자입니다.
오늘은 SQL쿼리튜닝에 대해 이야기해보려합니다.
현재 1년차 개발자로 일하고 있는 저는 SQL 쿼리를 어떻게 하면 소위 더 잘 짤수 있을까를 많이 고민하고 있습니다.
쿼리를 완성하고 나면 오버타임으로 좌절감에 빠지기도 하고, 어떻게 튜닝해야할지 몰라 난감하며 밤새 노력하시는 개발자님들을 위해(저와같은...ㅠㅠ) 조금이나마 도움이 되고자 글을 작성합니다. 두서없이 작성해도 이해해주시고 시작해보겠습니다.
SQL튜닝하는 방법은 다양하고, 알아야할 부분도 많습니다. 그러나 오늘 글에서는 인덱스와 조인을 통해 쿼리 성능을 높이는 방법에 대해 글을 써보려 합니다.
우선 쿼리를 튜닝하기 위해선 실행계획을 알아야합니다.
각 DB마다 실행계획을 확인할 수 있는 방법은 다르지만 MS_SQL기준으로는 쿼리를 작성 후 Ctrl + L을 누르시면 실행계획이 나옵니다.
SELECT * FROM [스키마명].[테이블명] | cs |
Ctrl + L
이런식으로 내 쿼리가 어떤 식으로 조회가 되는지 보실 수 있습니다.
기본적으로 여기까지 준비가 되셨다면 실행계획을 보는 방법에 대해 알려드리겠습니다.
테이블 스캔(해당 실행계획 아이콘)에 마우스를 올려두시면 노랑색 박스로 된 상자를 보실 수 있습니다.
이떄 우리가 확인해야할 부분은 물리적연산, 논리적연산, 비용 마지막으로 정렬됨 확인하시면 됩니다.
물론 다른 값들도 중요합니다. 하지만 초보자인 저는 위의 4가지를 보고 판단을 합니다.
1. 물리적연산 및 논리적연산은 index스캔인지, table스캔인지 알려주는 내용입니다.
index란 쉽게말해 테이블의 주소를 미리 저장해두는 개념으로 이해하시면 됩니다.
예를들어) 책에 목차와 차례들이 나오는데 글 맨 마지막에는 항상 숫자로 페이지를 적어둡니다. 이 페이지가 인덱스의 개념으로 이해하시면 될것 같습니다!
table스캔은 테이블 전체를 읽어서 연산했다고 생각하시면 됩니다.
2. I/O비용은 내부적인 작업에 의해서 서버의 하드디스크에 물리적으로 읽기 작업이 일어난 비용을 말합니다.
데이터가 반환되는 시간으로 생각하시면 됩니다. 고로 숫치가 작으면 작을 수록 성능이 좋은 쿼리라고 생각하시면 됩니다.
3.비용은 쿼리를 수행하는데 소요되는 비용이라고 생각하시면 됩니다.
4. 정렬됨은 정렬이 된것인가 안된것인가를 나타냄니다. 즉 정렬이 된다면 좀 더 오랜 시간이 걸리겠죠? (True, False값으로 나누어지는데 밑에서 이야기할 clustered index가 적용되면 True값으로 나오고 아니면 False값이 나옵니다. 해당 내용은 밑에서 다시 이야기 해보겠습니다.)
여기까지 실행계획을 어떻게 보고, 어떤 부분을 봐야할지 알아봤습니다.
그럼 본론으로 들어겠습니다.
쿼리 성능을 향상시키는데 가장 쉽고, 빠르게 바꿀 수 있는 방법은 인덱스(index)와 조인(join)입니다. 물론 다양한 방법들이 있습니다.
예를들면 커서를 안쓰기, 임시테이블 활용하기, update문 대신 case문 사용하기 등 다양한 방법으로 쿼리를 튜닝할 수 있습니다.
다만 해당 방법들은 작성된 쿼리마다 다르고, 한계가 있어 인덱스와 조인을 통해 쿼리를 튜닝하는 것이 기초를 잡을 수 있고, 충분히 좋은 성능이 나오는 쿼리를 작성할 수 있기 때문입니다.
먼저 인덱스이야기부터 해보겠습니다.
인덱스를 알려면 차례와 색인의 개념을 알아야합니다. 차례는 순서대로 찾고자하는 내용을 적는 것으로 이해하시고, 색인은 책의 구성내용이 번호로 적인 곳으로 이해하시면 될것 같습니다.
1. Clustered index(클러스터된 인덱스)
클러스터된 인덱스는 데이터의 순서대로 하드디스크 상 저장됩니다. 즉 순서대로라는 개념이 있기 때문에 차례에 해당합니다. 테이블 당 하나만 설정가능하고, 풀스캔보다 빠르며 유니크인덱스입니다. 다면 데이터를 입력할때는 느린단점이 있고, 범위로 처리해야합니다. 순서가 입력되기 때문에 데이터가 입력되면 처음부터 끝까지 데이터를 읽고 그다음 인덱스를 추가하기 때문입니다.
CREATE CLUSTERED INDEX [인덱스이름] ON [테이블](컬럼명) | cs |
2. 클러스터 되지 않은 인덱스
클러스터된 인덱스와는 다르게 순서에 따라 저장되지 않습니다. 하여 데이터 반환시에는 클러스터된 인덱스보단 느리지만 순서가 없기 때문에 데이터 입력할때는 훨씬 빠른 속도로 처리됩니다. 테이블 당 249개까지 설정가능하고, 적은범위의 데이터에서 특정 데이터를 반환하는 쿼리에 많이 사용됩니다.
구분 |
클러스터된 인덱스 |
클러스터 되지 않은 인덱스 |
INDEX 수 |
1 |
249 |
INDEX 지정에 따른 크기 |
TABLE크기의 1~5% |
TABLE크기의 10~20% |
조회성능 |
빠름 |
보다 느림 |
DATA 수정 |
보다 느림 |
빠름 |
사용 |
영역지정 |
하나의 값 반환 |
CREATE INDEX [인덱스이름] ON [테이블이름](컬럼명) | cs |
3. 단일 컬럼 인덱스
하나의 컬럼만으로 인덱스를 설정하는 것입니다.
4. 복합 컬럼 인덱스
여러개의 컬럼으로 인덱스를 설정합니다. 복합컬럼인덱스는 T-SQL을 사용할 때 성능이 향상됩니다.
이렇게 4가지 인덱스만 잘 알고계셔도 쿼리의 성능을 향상시킬 수 있습니다.
팁으로 클러스터된 인덱스는 가능하면 유니크 인덱스 설정을 권장드립니다.
이렇게 크게 4가지 인덱스를 통해 각 테이블에 설정 후 실행계획을 보시면 물리적연산, 논리적연산에 설정한 인덱스scan이 나오며
인덱스를 추가하는 것만으로 조회속도가 빨라진다는 것을 확인해 보실 수 있습니다
여기까지 INDEX를 알아 보았습니다. 다음글에선 조인을 알아보고 조인으로 쿼리를 튜닝하는 방법에 대해 이야기해보겠습니다.
감사합니다.
'DB > MSSQL (SQLSERVER)' 카테고리의 다른 글
[MSSQL]테이블 별 ROW 사이즈 추출 - 테이블 별 할당 데이터 사이즈출력 (0) | 2020.07.16 |
---|---|
[MSSQL] SQL 쿼리 튜닝 -> 조인(JOIN)로 답을 찾자!(NESTED LOOP JOIN (중첩반복),SORT MERGE JOIN (정렬병합),HASH JOIN (해시매치)) (0) | 2020.07.15 |
[MSSQL] 쿼리 CPU사용량 조회 -> 튜닝 시작 전 CPU확인 방법 (0) | 2020.07.14 |
[MSSQL] WITH 사용해서 연속숫자 조회/뽑기 (0) | 2020.07.13 |
[MSSQL] 스키마 별 전체 행수(ROW)수 구하기 - COUNT (0) | 2020.07.13 |