[실전 DB 05] 복합 인덱스, 컬럼 순서의 기술

인덱스를 쓰다 보면 조건이 한 컬럼이 아니라 여러 컬럼에 걸리는 경우가 많다. 특정 게시판의 글을 시각순으로 본다면 게시판과 시각 두 컬럼이 함께 쓰인다. 이럴 때 필요한 게 여러 컬럼을 묶는 복합 인덱스다. 그런데 이 복합 인덱스는 컬럼 순서가 결정적이다. 이번 편은 복합 인덱스와 그 순서의 기술을 다룬다.


복합 인덱스는 실전에서 가장 많이 쓰는 인덱스인데, 순서를 잘못 잡으면 안 쓰인다. 이 순서의 원리를 이해하는 게 핵심이다.

1. 복합 인덱스란 무엇인가

복합 인덱스는 두 개 이상의 컬럼을 묶어 만든 인덱스다. 조건이 여러 컬럼에 걸리는 쿼리를 위한 것이다. 예를 들어 가상의 글 테이블에서 게시판과 작성 시각으로 조회한다면, CREATE INDEX idx_articles_board_created ON articles(board_id, created_at) 같은 복합 인덱스를 만든다.


이렇게 두 컬럼을 묶으면, 게시판으로 거르고 시각으로 정렬하는 쿼리가 이 인덱스 하나로 처리된다. 게시판별로 나뉘고 그 안에서 시각순으로 정렬된 표가 미리 만들어져 있으니, 특정 게시판의 시각순 목록을 바로 찾아간다. 두 조건을 한 인덱스로 만족시키는 것이다.


복합 인덱스가 단일 인덱스 여러 개보다 나은 경우가 많다. 게시판 인덱스 따로, 시각 인덱스 따로 만드는 것보다, 둘을 묶은 복합 인덱스 하나가 게시판과 시각을 함께 쓰는 쿼리에 더 효율적이다. 데이터베이스가 인덱스 하나로 두 조건을 다 처리할 수 있기 때문이다.


복합 인덱스는 실전에서 가장 많이 쓰는 인덱스다. 실제 쿼리는 조건이 여러 컬럼에 걸리는 경우가 대부분이라, 단일 컬럼 인덱스만으로는 부족하다. 게시판으로 거르고 시각으로 정렬하는 흔한 목록 쿼리도 두 컬럼이 함께 쓰인다. 그래서 복합 인덱스를 잘 다루는 게 실무 최적화의 핵심 기술이 된다.


한 가지 더, 복합 인덱스는 단일 인덱스 여러 개보다 효율적인 경우가 많다. 게시판 인덱스 따로 시각 인덱스 따로 만드는 것보다, 둘을 묶은 복합 인덱스 하나가 두 컬럼을 함께 쓰는 쿼리에 낫다. 데이터베이스가 인덱스 하나로 두 조건을 다 처리하기 때문이다. 게다가 인덱스 개수가 줄어 쓰기 비용도 아낀다.

2. 컬럼 순서가 결정적이다

복합 인덱스의 핵심은 컬럼 순서다. 게시판과 시각을 묶을 때, 게시판을 앞에 두느냐 시각을 앞에 두느냐가 완전히 다른 인덱스를 만든다. 순서에 따라 어떤 쿼리에 쓰이고 어떤 쿼리에 안 쓰이는지가 갈린다.


원리는 이렇다. 복합 인덱스는 앞 컬럼으로 먼저 정렬하고, 그 안에서 뒤 컬럼으로 정렬한다. 게시판, 시각 순서면 게시판별로 나뉘고 각 게시판 안에서 시각순으로 정렬된다. 그래서 게시판으로 거르는 쿼리는 이 인덱스를 쓸 수 있다. 앞 컬럼이 조건에 맞기 때문이다.


반대로 앞 컬럼이 조건에 없으면 인덱스를 제대로 못 쓴다. 게시판, 시각 순서 인덱스인데 게시판 조건 없이 시각으로만 거르려 하면, 인덱스가 게시판별로 먼저 나뉘어 있어서 시각만으로는 바로 찾기 어렵다. 그래서 복합 인덱스의 앞 컬럼은 항상 조건에 쓰이는 컬럼이어야 한다.


컬럼 순서가 결정적이라는 게 복합 인덱스의 가장 중요한 포인트다. 같은 두 컬럼이라도 순서에 따라 완전히 다른 인덱스가 된다. 앞 컬럼이 조건에 안 맞으면 인덱스를 제대로 못 쓴다. 그래서 어떤 쿼리들이 이 인덱스를 쓸지 그려보고, 그 쿼리들의 조건에 맞게 컬럼 순서를 정하는 게 설계의 핵심이다.

3. 순서를 정하는 원칙

컬럼 순서를 정하는 원칙이 있다. 먼저 등호로 정확히 거르는 컬럼을 앞에, 범위나 정렬에 쓰는 컬럼을 뒤에 둔다. 게시판은 특정 값으로 정확히 거르니 앞에, 시각은 정렬에 쓰니 뒤에 두는 식이다. 이러면 앞 컬럼으로 딱 좁히고 뒤 컬럼으로 정렬이 된다.


또 하나, 여러 쿼리에 두루 쓰이는 컬럼을 앞에 두는 게 유리하다. 게시판 조건은 거의 모든 목록 쿼리에 들어가지만 다른 조건은 가끔만 들어간다면, 게시판을 앞에 둬야 그 인덱스가 많은 쿼리에 쓰인다. 앞 컬럼일수록 활용도가 높으니, 가장 자주 쓰이는 컬럼을 앞에 배치한다.


이 순서 결정이 복합 인덱스 설계의 기술이다. 내가 실제로 인덱스를 만들 때도, 어떤 쿼리들이 이 인덱스를 쓸지 그려보고 컬럼 순서를 정했다. 순서를 잘못 잡으면 인덱스를 만들어도 안 쓰이거나 일부 쿼리에만 쓰인다. 순서 하나가 인덱스의 효용을 좌우한다.


순서를 정하는 원칙이 명확하다. 등호로 정확히 거르는 컬럼을 앞에, 범위나 정렬 컬럼을 뒤에 둔다. 그리고 여러 쿼리에 두루 쓰이는 컬럼을 앞에 둔다. 이 원칙을 따르면 하나의 복합 인덱스가 여러 쿼리를 커버한다. 앞 컬럼일수록 활용도가 높으니, 가장 자주 조건에 쓰이는 컬럼을 맨 앞에 배치하는 게 유리하다.


또 하나, 순서를 정할 때 앞 컬럼의 활용도를 본다. 게시판 조건은 거의 모든 목록 쿼리에 들어가지만 다른 조건은 가끔만 들어간다면, 게시판을 앞에 둬야 그 인덱스가 많은 쿼리에 쓰인다. 앞 컬럼일수록 두루 쓰이니, 가장 공통적인 컬럼을 맨 앞에 두는 게 인덱스의 활용 범위를 넓힌다.

4. 여러 쿼리를 한 인덱스로

잘 설계한 복합 인덱스는 여러 쿼리를 함께 처리한다. 게시판, 시각 순서 인덱스는 게시판별 시각순 목록에도 쓰이고, 특정 게시판의 특정 시각 범위 조회에도 쓰인다. 앞 컬럼이 맞으면 뒤 컬럼을 부분적으로만 써도 인덱스가 도움이 되기 때문이다.


그래서 인덱스를 무작정 늘리기보다, 하나의 잘 설계한 복합 인덱스로 여러 쿼리를 커버하는 게 좋다. 인덱스가 많으면 앞서 다룬 쓰기 비용이 늘어난다. 반면 잘 설계한 복합 인덱스 하나가 여러 쿼리를 처리하면, 적은 인덱스로 넓은 커버리지를 얻는다. 인덱스 개수를 줄이면서 효과는 유지하는 것이다.


내 사이트에서도 목록 관련 쿼리들이 대체로 게시판과 시각을 함께 쓰기에, 그 복합 인덱스 하나가 여러 목록 쿼리를 커버했다. 각 쿼리마다 인덱스를 따로 만들 필요 없이, 공통 패턴을 담은 복합 인덱스로 여러 개를 함께 최적화한 것이다. 이 효율이 복합 인덱스의 강점이다.


여러 쿼리를 한 인덱스로 커버하는 게 복합 인덱스의 강점이다. 잘 설계하면 인덱스 하나가 여러 목록 쿼리를 처리한다. 인덱스를 무작정 늘리면 쓰기 비용이 커지는데, 공통 패턴을 담은 복합 인덱스 하나로 여러 쿼리를 최적화하면 적은 인덱스로 넓은 커버리지를 얻는다. 효율과 효과를 함께 챙기는 것이다.


또 하나, 복합 인덱스의 뒤 컬럼은 범위 조건에도 유용하다. 게시판으로 정확히 거른 다음 시각 범위로 좁히는 쿼리라면, 게시판 시각 복합 인덱스가 앞 컬럼으로 좁히고 뒤 컬럼으로 범위를 처리한다. 그래서 등호 컬럼을 앞, 범위 컬럼을 뒤에 두는 원칙이 이런 범위 조회에서도 그대로 효과를 낸다.

5. 순서를 실행 계획으로 검증한다

복합 인덱스도 만든 뒤 실행 계획으로 검증한다. 순서를 이렇게 하면 이 쿼리들이 인덱스를 탈 것이라는 예상이, 실제로 맞는지 확인하는 것이다. 각 대상 쿼리의 실행 계획을 보고, 그 복합 인덱스가 검색에 나오는지 확인한다.


만약 예상한 쿼리 중 일부가 인덱스를 안 타면, 컬럼 순서가 그 쿼리에 안 맞는 것이다. 그럴 땐 순서를 조정하거나, 그 쿼리를 위한 별도 인덱스를 고려한다. 모든 쿼리를 한 인덱스로 커버할 수 없을 때는, 가장 중요한 쿼리들을 커버하는 순서를 택하고 나머지는 별도로 처리한다. 이 판단도 실행 계획을 봐야 할 수 있다.


정리하면 복합 인덱스는 여러 컬럼을 묶어 여러 조건을 한 번에 처리하되, 앞 컬럼은 자주 등호로 거르는 컬럼, 뒤 컬럼은 정렬이나 범위 컬럼으로 두는 순서가 핵심이고, 실행 계획으로 검증한다. 다음 편에서는 인덱스를 더 정교하게 만드는 기법, 부분 인덱스와 커버링 인덱스를 다룬다.


순서를 실행 계획으로 검증하는 게 마무리다. 이 순서면 이 쿼리들이 인덱스를 탈 것이라는 예상이 맞는지, 각 대상 쿼리의 실행 계획으로 확인한다. 예상한 쿼리가 인덱스를 안 타면 순서가 안 맞는 것이니 조정한다. 모든 쿼리를 한 인덱스로 못 커버할 땐 가장 중요한 쿼리를 우선하는 순서를 택한다.


복합 인덱스 설계는 어떤 쿼리들이 이 인덱스를 쓸지 그려보는 데서 시작한다. 목록 쿼리들의 조건과 정렬을 모아 공통 패턴을 찾고, 그 패턴에 맞는 컬럼 순서를 정한다. 그러면 하나의 인덱스가 여러 쿼리를 커버한다. 순서를 잘못 잡으면 일부 쿼리에만 쓰이니, 이 그려보는 단계가 설계의 성패를 가른다.