SQLite를 운영하며 새롭게 배운 몇 가지
요약
소규모 프로덕션 환경에서도 SQLite 사용이 가능하지만, Django ORM을 통해 데이터베이스 운영 복잡성을 체감했습니다. 특히 쿼리 플래너 통계(ANALYZE)가 검색 성능에 큰 영향을 미치며, 대량의 쓰기 작업은 시간 초과 및 시스템 충돌 위험을 높여 작은 배치로 분할 처리하는 것이 중요함을 깨달았습니다.
핵심 포인트
- SQLite도 운영 지식이 필요한 복잡한 DB이며 WAL 모드 활성화가 권장됨.
- ANALYZE 실행만으로 FTS5 검색 성능이 5초에서 0.05초로 극적으로 개선될 수 있음.
- 대량 DELETE 작업은 시스템 제한 시간 초과를 유발하므로 작은 배치로 분할해야 함.
- OOM 종료 및 잠금 문제에 대비하여 Litestream 등 증분 백업 방식을 고려하는 것이 좋음.
-
소규모 웹사이트의 프로덕션 환경에도 SQLite를 쓸 수 있지만, Django ORM이 맡는 작업이 늘면서 데이터베이스의
운영 복잡성을 체감함 - 4,000행 테이블의 FTS5 검색이 5초 걸렸으나
실행 후 약 0.05초로 줄어, 쿼리 플래너 통계가 성능에 큰 영향을 줄 수 있음을 확인함ANALYZE -
대량
DELETE
가 5초를 넘으면 다른 쓰기 작업도 시간 초과되고 워커와 VM까지 종료될 수 있어, 정리 작업을작은 배치로 나눠 처리함 - 백업에는
VACUUM INTO
와 restic을 사용했지만 OOM 종료를 겪었으며, 더 효율적인증분 백업을 위해 Litestream도 시험 중임 - 테이블을 여러 SQLite 파일로 분리할 수 있으며, Mess with DNS는 2022년부터 4년간 SQLite로 운영돼 프로젝트에 적합한 선택이었다고 평가함
Django 사이트에서 SQLite 운영하기
- 소규모 프로덕션 사이트에서도 SQLite를 사용할 수 있다는 여러 글을 참고해 Django 사이트의 데이터베이스로 채택함
- SQLite 역시 운영 지식이 필요한
복잡한 데이터베이스이며, 이번 프로젝트에서는 Django ORM을 통해 이전보다 더 많은 작업을 맡기고 있음 - 여러 권장 사항에 따라 처음부터
WAL 모드를 활성화해 운영함 - 이번 사이트는 SQLite를 사용한 네 번째 웹사이트임
ANALYZE
가 바꾼 검색 성능
- 4,000행 테이블에서 SQLite FTS5를 이용한 전문 검색 쿼리에
5초가 걸림ANALYZE
를 실행하자 같은 쿼리가 약0.05초로 단축돼 더 조사할 필요가 없을 정도가 됨- 정확히 어떤 쿼리 계획 문제가 있었는지는 확인하지 못했으며, 의도치 않은 이차 시간 복잡도와 비슷한 상황이었을 것으로 추측함
ANALYZE
는 테이블 행 수 등을 포함한통계 정보를 생성해 쿼리 플래너가 더 나은 선택을 하도록 도움- 아직 쿼리 계획을 읽는 방법은 익히지 못한 상태임
데이터 정리와 단일 쓰기 제약
-
django-tasks-db의 완료된 작업처럼 불필요한 행을 대량으로 삭제할 때 연쇄적인 문제가 생김
-
많은 행을 처리하는 정리 명령이
5초 이상실행됨 - 그동안 다른 워커의 데이터베이스 쓰기가 설정된 5초 제한을 넘겨 시간 초과됨 -
쓰기에 실패한 워커가 충돌하고 VM도 종료됨
-
많은 행을 처리하는 정리 명령이
DELETE
가 느린 정확한 이유는 확인하지 못했으며, 트랜잭션 안에서 많은 Python 코드가 실행되기 때문일 가능성도 고려하고 있음- 현재는 각 데이터베이스 쿼리가 5초를 넘지 않도록 정리 작업을
작은 배치로 분할함 - 이 경험을 통해 여러 쓰기 작업을 동시에 처리할 수 있는 Postgres 같은 데이터베이스가 필요한 이유를 체감함
- 향후에는 이런 작업 중 사이트를 내려
예정된 유지보수를 수행하는 방안도 고려하지만, 아직 작업 흐름은 마련하지 못함
ORM 쿼리와 현재 데이터 규모
- 지금까지 Django ORM으로 원하는 쿼리를 만들면서
성능을 별도로 점검하지 않았지만,ANALYZE
문제 외에는 대부분 정상적으로 작동함 - 데이터베이스는 약
10,000행으로 작으며 앞으로도 계속 작은 규모를 유지할 것으로 예상함
SQLite 백업 방식
- SQLite 백업에는 restic과 Litestream 두 가지 방식을 사용해 봄
- 백업 작업은 보통
데드맨 스위치로 감시하지만, 실제 복원 테스트는 아직 하지 않은 것으로 보임 -
restic을 이용한 백업
VACUUM INTO
로 데이터베이스 사본을 만들고 gzip으로 압축한 뒤 S3에 업로드함- restic으로 백업 생성, 스냅샷 확인, 오래된 백업 삭제 및 정리를 수행함
- 백업이 간혹
OOM으로 종료되면서 잠금이 남아restic unlock
도 실행함
sqlite3 /data/calendar.db "VACUUM INTO '/tmp/calendar.sqlite'" gzip /tmp/calendar.sqlite restic -r s3://s3.amazonaws.com/some_bucket/ unlock restic -r s3://s3.amazonaws.com/some_bucket/ backup /tmp/calendar.sqlite.gz restic -r s3://s3.amazonaws.com/some_bucket/ snapshots restic -r s3://s3.amazonaws.com/some_bucket/ forget -l 1 -H 6 -d 2 -w 2 -m 2 -y 2 restic -r s3://s3.amazonaws.com/some_bucket/ prune
Litestream을 이용한 증분 백업
- restic 백업의 OOM 종료를 피하고
증분 백업의 효율을 시험하기 위해 Litestream을 사용하기 시작함 - 설정 파일을 작성한 뒤 다음 명령으로 복제를 실행함
litestream replicate -config litestream.yml
- 데이터베이스 이력을 일정 기간 유지하려고
retention: 400h
를 지정했지만, 의도대로 작동하는지는 아직 확인하지 못함 - AWS에 백업하고 있으나 콘솔에서 자격 증명을 생성하기가 번거로워, 향후 다른
S3 호환 서비스로 옮기는 방안도 고려함
- restic 백업의 OOM 종료를 피하고
여러 SQLite 데이터베이스 파일 사용
- 현재 프로젝트는 데이터베이스 하나만 사용하지만, Mess with DNS에서는 함께 둘 필요가 없는 테이블을
3개 데이터베이스 파일로 분리함 - 이러한 분리가 운영에 도움이 됐다고 판단함 - Mess with DNS는 2022년부터 4년 동안 SQLite로 운영됐으며, 해당 프로젝트에서는 Postgres에서 SQLite로 옮긴 것이 좋은 선택이었음
운영하며 뒤늦게 발견한 기본 기능
- 웹 프로젝트에서 SQLite를 처음 사용한 시점은
2022년이지만ANALYZE
의 존재는 이번에 처음 알게 됨 - 사용하는 기술의 기본 기능도 실제 운영 과정에서 수년에 걸쳐 계속 배우게 됨
AI 자동 생성 콘텐츠
본 콘텐츠는 GeekNews의 원문을 AI가 자동으로 요약·번역·분석한 것입니다. 원 저작권은 원저작자에게 있으며, 정확한 내용은 반드시 원문을 확인해 주세요.
원문 바로가기