![[실전 DB 08] 인덱스도 공짜가 아니다, 쓰기 비용과 중복 정리](https://img.thenullpage.com/posts/5645/5645_1_04c161.webp)
지금까지 인덱스의 좋은 점을 주로 다뤘는데, 이번엔 어두운 면을 볼 차례다. 인덱스는 공짜가 아니다. 저장 공간을 쓰고, 데이터를 쓸 때마다 갱신 부담을 준다. 그래서 인덱스를 무작정 늘리면 오히려 손해다. 이번 편은 인덱스의 비용과, 중복 인덱스를 정리하는 법을 다룬다.
인덱스를 잘 쓰는 것만큼 인덱스를 절제하는 것도 최적화다. 좋은 도구도 남용하면 짐이 된다.
1. 인덱스의 쓰기 비용
인덱스의 가장 큰 비용은 쓰기 부담이다. 데이터를 추가하거나 수정하면, 그 데이터가 담긴 인덱스도 함께 갱신해야 한다. 인덱스가 하나면 한 번 갱신하면 되지만, 인덱스가 다섯 개면 데이터 하나 쓸 때마다 다섯 개를 다 갱신해야 한다. 인덱스가 많을수록 쓰기가 느려진다.
읽기가 많은 사이트에서는 인덱스의 읽기 이득이 이 쓰기 비용을 훌쩍 넘어서 이득이 크다. 그런데 쓰기가 많은 경우엔 이 비용을 무시할 수 없다. 데이터를 자주 쓰는데 인덱스가 많으면, 쓰기가 느려지고 쓰기 관련 자원도 더 쓴다. 그래서 읽기와 쓰기의 비율을 보고 인덱스를 정해야 한다.
대부분의 커뮤니티는 읽기가 쓰기보다 훨씬 많다. 글 하나가 쓰이면 수백, 수천 번 읽힌다. 그래서 인덱스의 읽기 이득이 쓰기 비용보다 대체로 크다. 하지만 그렇다고 인덱스를 무한정 늘려도 되는 건 아니다. 안 쓰이는 인덱스는 이득 없이 쓰기 비용만 늘리기 때문이다.
인덱스의 어두운 면을 아는 게 균형 잡힌 최적화의 조건이다. 인덱스가 좋다고 아무 데나 다 걸면 쓰기가 느려지고 공간이 낭비된다. 좋은 도구도 남용하면 짐이 된다. 그래서 인덱스를 잘 쓰는 것만큼 절제하는 것도 최적화다. 필요한 곳에만 걸고 안 쓰이는 건 걷어내는 균형이 필요하다.
한 가지 더, 인덱스의 균형은 사이트 성격에 따라 다르다. 읽기가 압도적인 커뮤니티는 인덱스를 넉넉히 써도 이득이 크지만, 쓰기가 많은 서비스는 인덱스를 절제해야 한다. 그래서 정답이 하나가 아니라, 내 사이트의 읽기와 쓰기 비율을 보고 정하는 것이다. 이 비율을 알면 인덱스를 몇 개까지 둘지 감이 잡힌다.
2. 안 쓰이는 인덱스는 순손해
가장 나쁜 게 만들어놓고 안 쓰이는 인덱스다. 앞 편에서 인덱스가 안 쓰일 수 있다고 했는데, 안 쓰이는 인덱스는 읽기 이득이 없으면서 쓰기 비용과 저장 공간만 차지한다. 순손해다. 그래서 인덱스를 만들면 실제로 쓰이는지 확인하고, 안 쓰이면 지우거나 고쳐야 한다.
안 쓰이는 인덱스는 시간이 지나며 쌓이기 쉽다. 예전에 어떤 쿼리를 위해 만들었는데 그 쿼리가 바뀌거나 사라지면, 인덱스만 남는다. 또는 여러 인덱스를 시도해보다 안 쓰이는 걸 안 지우고 두면 쌓인다. 이 잔재 인덱스들이 조용히 쓰기 비용을 늘린다.
그래서 주기적으로 인덱스를 점검하는 게 좋다. 각 인덱스가 실제 쿼리에 쓰이는지 확인하고, 안 쓰이는 건 정리한다. 인덱스를 만드는 것만 관리하지 말고 지우는 것도 관리하는 것이다. 안 쓰이는 인덱스 정리는 쓰기 비용을 줄이는 확실한 방법이다.
쓰기 비용이 인덱스의 가장 큰 대가다. 데이터를 쓸 때마다 그 데이터가 담긴 인덱스를 다 갱신해야 하니, 인덱스가 많을수록 쓰기가 느려진다. 읽기가 많은 사이트는 인덱스의 읽기 이득이 이 비용을 넘지만, 안 쓰이는 인덱스는 이득 없이 비용만 늘린다. 그래서 읽기와 쓰기 비율을 보고 인덱스를 정한다.
3. 중복 인덱스 찾기
특히 조심할 게 중복 인덱스다. 앞서 복합 인덱스를 다뤘는데, 복합 인덱스가 있으면 그 앞 컬럼만 담은 단독 인덱스는 대체로 중복이다. 게시판, 시각 복합 인덱스가 있으면, 게시판 단독 인덱스는 복합 인덱스로 대신할 수 있어 불필요하다.
이유는 복합 인덱스가 앞 컬럼부터 정렬돼 있어서, 앞 컬럼만 쓰는 쿼리도 그 복합 인덱스로 처리되기 때문이다. 게시판, 시각 인덱스는 게시판만으로 거르는 쿼리에도 쓰인다. 그러니 게시판 단독 인덱스는 있으나 마나다. 이런 중복 인덱스는 쓰기 비용만 늘리니 정리 대상이다.
내 사이트에서도 인덱스를 점검하다 이런 중복을 발견했다. 복합 인덱스와 그 앞 컬럼 단독 인덱스가 함께 있었던 것이다. 단독 인덱스를 지워도 복합 인덱스가 그 역할을 하니 읽기 성능은 그대로면서 쓰기 비용만 줄었다. 중복을 찾아 정리하는 게 순수한 이득이었다.
안 쓰이는 인덱스는 순손해다. 읽기 이득이 없으면서 쓰기 비용과 공간만 차지한다. 예전 쿼리를 위해 만들었는데 그 쿼리가 사라졌거나, 여러 인덱스를 시도하다 안 지운 것들이 쌓인다. 그래서 주기적으로 인덱스를 점검해, 실제 쓰이는지 확인하고 안 쓰이는 건 정리한다. 만드는 것만큼 지우는 것도 관리다.
또 하나, 안 쓰이는 인덱스를 찾으려면 실제 쿼리 목록과 대조한다. 각 인덱스가 어떤 쿼리에 쓰이는지 확인하고, 어느 쿼리에도 안 쓰이는 인덱스를 찾는다. 예전에 만들었는데 그 쿼리가 사라진 인덱스가 이렇게 드러난다. 이 대조 작업이 잔재 인덱스를 걷어내 쓰기 비용을 줄인다.
4. 중복 정리는 신중하게
다만 중복 인덱스 정리는 신중해야 한다. 중복처럼 보여도 실제로는 특정 쿼리에 쓰이고 있을 수 있기 때문이다. 그래서 지우기 전에 그 인덱스가 정말 안 쓰이는지, 다른 인덱스로 대체 가능한지 확인해야 한다. 실행 계획으로 그 인덱스를 쓰는 쿼리가 다른 인덱스로도 처리되는지 봐야 한다.
인덱스를 지우는 건 되돌리기 쉽지만, 잘못 지우면 그 쿼리가 갑자기 느려진다. 그래서 지우기 전에 충분히 확인하고, 지운 뒤에도 관련 쿼리들이 여전히 인덱스를 잘 타는지 점검한다. 앞서 여러 시리즈에서 강조한 배포 후 확인이 인덱스 정리에도 적용된다. 지웠으면 영향을 확인한다.
중복이 확실한 경우에도 한 번에 여러 개를 지우기보다 하나씩 지우고 확인하는 게 안전하다. 여러 개를 동시에 지우면 문제가 생겼을 때 어느 것 때문인지 분간하기 어렵다. 하나 지우고 확인하고, 문제없으면 다음 걸 지운다. 신중하게 하나씩 하는 게 정리의 원칙이다.
중복 인덱스가 특히 조심할 대상이다. 복합 인덱스가 있으면 그 앞 컬럼만 담은 단독 인덱스는 대체로 중복이다. 복합 인덱스가 앞 컬럼부터 정렬돼 있어 앞 컬럼만 쓰는 쿼리도 처리하기 때문이다. 이런 단독 인덱스는 있으나 마나이니, 지우면 읽기 성능은 그대로면서 쓰기 비용만 준다. 순수한 이득이다.
또 하나, 인덱스를 지운 뒤에는 관련 쿼리들이 여전히 잘 도는지 확인한다. 중복이라 판단해 지웠는데 실제로 어떤 쿼리가 그걸 쓰고 있었다면, 그 쿼리가 갑자기 느려진다. 그래서 지운 뒤 관련 쿼리들의 실행 계획을 다시 봐서, 다른 인덱스로 잘 처리되는지 확인한다. 지웠으면 영향을 확인하는 것이다.
5. 인덱스는 자산이자 부채다
인덱스를 자산이자 부채로 보는 균형 잡힌 시각이 필요하다. 읽기를 빠르게 하는 자산이면서, 쓰기를 느리게 하고 공간을 쓰는 부채이기도 하다. 그래서 자산 가치가 부채보다 큰 인덱스만 유지하는 게 최적이다. 자주 쓰이는 인덱스는 자산이고, 안 쓰이는 인덱스는 부채다.
이 균형을 잡으려면 인덱스를 정기적으로 점검해야 한다. 어떤 인덱스가 쓰이고 어떤 게 안 쓰이는지, 중복은 없는지 살핀다. 쓰이는 건 유지하고 안 쓰이는 건 정리한다. 이 점검이 인덱스를 자산으로만 남기고 부채는 걷어낸다. 인덱스 관리는 만드는 것과 정리하는 것 양쪽을 포함한다.
정리하면 인덱스는 읽기를 빠르게 하지만 쓰기 비용과 공간을 쓰니, 안 쓰이는 인덱스와 중복 인덱스는 정리하되 신중하게 하나씩 확인하며 지운다. 여기까지가 인덱스 파트다. 다음 편부터는 인덱스로 안 풀리는 구조적 문제, 페이지네이션의 함정과 개수 세기의 비용을 다룬다.
중복 정리는 신중하게 하나씩 한다. 중복처럼 보여도 특정 쿼리에 쓰일 수 있으니, 지우기 전에 다른 인덱스로 대체 가능한지 실행 계획으로 확인한다. 그리고 한 번에 여러 개를 지우기보다 하나 지우고 확인하고 다음 걸 지운다. 문제가 생겼을 때 어느 것 때문인지 분간하려면 하나씩 하는 게 안전하다.
인덱스를 자산이자 부채로 보는 시각이 이 편의 결론이다. 읽기를 빠르게 하는 자산이면서 쓰기를 느리게 하는 부채이기도 하다. 자산 가치가 부채보다 큰 인덱스만 유지하는 게 최적이다. 그래서 인덱스 관리는 만드는 것과 정리하는 것 양쪽을 포함한다. 쓰이는 건 유지하고 안 쓰이는 건 걷어내는 균형이 최적화다.
또 하나, 인덱스 정리는 사이트가 커지기 전에 습관으로 만들어두면 좋다. 데이터가 적을 때는 인덱스가 많아도 부담이 안 느껴지지만, 데이터와 트래픽이 커지면 쓰기 비용이 뚜렷해진다. 그래서 작을 때부터 인덱스를 깔끔하게 관리하는 습관이, 커진 뒤의 큰 정리 부담을 미리 던다.