분류
개발 · 2쪽
DB·백엔드에서 실제로 터지는 문제와 USB·CD 굽기 교과서를 모았다. 느린 쿼리, 락과 트랜잭션, 장애와 확장, 배포와 관측은 태그로 나눠 찾는다.
96편 · 글 80 · 강 16 · 마지막 글 2026.09.28
교과서굽기 16강
개발 글
96편 중 13–24
한 파일이 CD도 되고 USB도 되는 이유 — 하이브리드 ISO
여기서 이상한 점이 하나 생긴다. .iso 는 CD용 이미지다. CD의 칸은 2048바이트고, 부팅은 El Torito 방식이다. 그런데 USB의 칸은 512바이트고, 부팅은 MBR이나 ESP로 한다. 규칙이 전혀 다른데 우분투 ISO는 CD에 구워…
dd 한 줄을 뜯어본다
dd 는 유닉스에 50년 가까이 있던 도구다. 하는 일은 딱 하나다. 한쪽에서 바이트를 읽어 다른 쪽에 그대로 쓴다. 파일시스템을 전혀 신경 쓰지 않으니 굽기에 딱 맞다. 그리고 같은 이유로 가장 위험한 도구이기도 하다.
느린 쿼리 1등을 고쳤는데 왜 그대로일까
느린 쿼리 1등을 3초에서 0.5초로 줄였는데 서비스 체감은 그대로였다. 하루 500만 번 도는 50ms 쿼리가 총 69시간. 진짜 짐은 그쪽이었다.
쿼리는 그대로인데 조인이 100배 느려졌다
쿼리도 인덱스도 그대로인데 리포트 쿼리가 어느 날부터 100배 느려졌다. EXPLAIN 을 보니 조인 순서가 뒤집혀 있었다. 뒤집힌 이유는 조인이 아니라 행 수 추정에 있었다.
Index Scan 이라고 찍혔는데 왜 3초나 걸릴까
EXPLAIN 에 인덱스 스캔이 찍혔는데도 쿼리가 3초씩 걸린다. 인덱스를 타는 건 시작일 뿐이다. 시간이 어디로 새는지는 계획 아래 숫자 몇 개가 말해 준다.
다시 만들었더니 인덱스가 절반이 됐다, 인덱스 팽창
테이블은 그대로인데 인덱스만 몇 달에 걸쳐 조금씩 커진다. 다시 만들어 보면 크기가 절반으로 줄기도 한다. 그동안 늘린 서버 비용이 사실은 빈 공간 값이었다.
COUNT(*) 는 결국 다 세는 일이다
목록 스무 개는 10ms 에 나오는데 전체 개수를 세는 데는 3초가 걸린다. 인덱스를 더해도 크게 안 준다. 이 비용은 구조에서 나온다. 고칠 곳은 쿼리보다 화면 쪽일 때가 많다.
NOT IN 결과가 0건, 범인은 NULL 하나
NOT IN 으로 걸렀는데 에러도 없이 결과가 0건이다. 데이터는 분명히 있는데. NULL 하나가 결과를 통째로 비우고, DB 를 옮기면 정렬 순서까지 바뀐다.
OR 하나 붙였더니 인덱스를 안 탄다
검색 조건에 OR 하나를 더했을 뿐인데 쿼리가 갑자기 느려진다. AND 로 바꾸면 멀쩡하다. 어떤 OR 은 괜찮고 어떤 OR 만 탈이 나는지는 같은 컬럼이냐 다른 컬럼이냐로 갈린다.
왜 하필 여섯 번째 실행부터 쿼리가 느려질까
같은 쿼리가 다섯 번까지는 빠르다가 여섯 번째부터 느려지고, 서버를 재시작하면 다시 빨라진다. 우연 같은 이 숫자는 PostgreSQL 옵티마이저가 정해 둔 규칙이다.
조건에 맞는 글이 없다. 브루니가 숨었나 보다.