PostgreSQL이냐 MySQL이냐…JSON보다 읽기·쓰기 혼합에서 갈린다

|작성자: QUASA 편집팀|6 분 소요| 3
PostgreSQL이냐 MySQL이냐…JSON보다 읽기·쓰기 혼합에서 갈린다

새 애플리케이션에서 조회와 갱신이 같은 데이터에 자주 겹친다면 PostgreSQL을 우선 후보로 둘 만하다. 한 동일 VM의 sysbench 측정에서 PostgreSQL은 MySQL보다 혼합 읽기·쓰기 처리량이 크게 높았지만, 읽기 전용 처리량은 훨씬 가까웠다. 이미 MySQL을 안정적으로 운영하는 서비스라면 이 측정치만으로 이전을 결정하기보다 현재 쿼리의 병목과 전환 비용을 먼저 따져야 한다.

두 제품 모두 JSON을 저장하고 검색할 수 있다. 선택을 가르는 질문은 JSON 지원 여부 자체가 아니라 자주 검색할 경로가 정해져 있는지, 쓰기와 읽기가 한 트랜잭션 흐름에서 얼마나 충돌하는지, 팀이 어느 쪽의 백업과 장애 대응을 지속할 수 있는지다. 새 서비스에는 예상 작업량과 운영 역량을 함께 적용하고, 기존 서비스에는 실제로 느린 요청을 기준으로 이전의 이익을 계산하는 편이 정확하다.

같은 장비에서도 혼합 부하와 읽기 전용의 차이는 달랐다

ComputingForGeeks의 2026년 3월 sysbench 측정은 PostgreSQL 17.9와 MySQL 8.4.8을 각각 같은 4코어·8GB VM에서 실행해, 혼합 OLTP에서 2,886 대 436 TPS와 평균 지연 5.54 대 36.6ms, 읽기 전용에서 5,628 대 5,400 TPS, 포인트 조회에서 72,664 대 49,889 QPS를 기록했다. 측정은 제품을 한 번에 하나씩 구동하고 같은 크기의 데이터를 사용했으며, 동시 스레드 16개로 각 작업을 60초 동안 실행했다.

가장 눈에 띄는 것은 순위 자체보다 작업 종류에 따라 격차가 달라진다는 점이다. 혼합 OLTP에서는 조회와 함께 삽입, 수정, 삭제가 일어나므로 인덱스 갱신, 로그 기록, 동시 접근의 비용이 함께 반영된다. 읽기 전용에서는 그런 쓰기 비용이 측정되지 않는다. 실제 서비스가 상품 조회 뒤 재고를 갱신하거나 계정 상태를 변경한다면 혼합 부하가 더 가까운 참고점이 된다.

다만 이 결과는 해당 버전, 메모리 설정, 데이터 크기, 동시성, 짧은 실행 시간에 묶여 있다. 공개된 수치가 MySQL의 모든 설정에서 동일한 격차를 낳는다는 뜻은 아니며, 차이의 원인을 특정 잠금 방식이나 로그 구조 하나로 확정할 수도 없다. 서비스에서는 연결 수, 스토리지, 데이터 분포, 반복 갱신되는 행의 비율이 달라질 수 있다. 따라서 처리량 차이는 후보를 좁히는 근거로 읽고 실제 응답 시간의 예측치로 옮겨 적지 않는 편이 좋다.

조회 중심 서비스라면 어떤 수치를 봐야 하나

읽기 전용 처리량이 가까웠다는 사실은 조회가 대부분인 시스템의 판단을 바꾼다. 보고서 화면이나 목록 요청이 중심이고 쓰기가 분리돼 있다면 혼합 OLTP에서 나타난 큰 차이만으로 이전 비용을 정당화하기 어렵다. 이때는 느린 쿼리가 조인과 정렬에 시간을 쓰는지, 선택도가 낮은 조건으로 많은 행을 읽는지, 인덱스로 소수의 행만 가져오는지 나눠 보는 것이 유용하다.

포인트 조회는 또 다른 작업이다. 기본키나 고유 인덱스로 한 행을 찾는 요청의 처리량은 복잡한 필터, 집계, 정렬이 있는 조회의 속도를 대신하지 않는다. 위 측정에서 PostgreSQL의 포인트 조회 수치가 더 높았어도, 그것을 모든 읽기 요청의 우위로 확대할 수는 없다. 캐시가 대부분의 단순 조회를 흡수하는 서비스라면 데이터베이스의 포인트 조회 처리량이 사용자 지연에 기여하는 비중도 달라진다.

측정 단위도 구별해야 한다. TPS는 정의된 트랜잭션 묶음의 완료 건수이고 QPS는 쿼리 실행 건수이므로, 포인트 조회의 QPS와 혼합 OLTP의 TPS를 같은 축에서 비교할 수 없다. 혼합 부하 안에 어떤 SQL이 들어 있는지와 실제 애플리케이션이 한 요청에서 수행하는 작업을 맞춰야 한다. 조회가 많다는 비율만으로는 같은 행에 대한 갱신 경합이나 긴 트랜잭션의 영향을 드러낼 수 없다.

JSON은 저장 가능 여부보다 검색 조건이 중요하다

PostgreSQL의 JSON 자료형 설명에 따르면 json은 입력 텍스트를 그대로 보관하지만 jsonb는 분해된 바이너리 형식으로 저장하고 직접 인덱싱을 지원한다. jsonb는 입력 때 변환 비용이 생기는 대신 처리할 때 텍스트를 다시 파싱하지 않는다. 원본의 공백과 키 순서, 중복 키를 그대로 남겨야 하는 요구가 있다면 json과 jsonb의 저장 차이도 설계 조건이 된다.

jsonb에 GIN 인덱스를 만들면 문서의 키나 키와 값의 조합을 찾는 쿼리에 활용할 수 있다. 기본 연산자 클래스는 키 존재 여부와 포함 검색 등을 지원하고, jsonb_path_ops는 지원 연산자가 더 좁은 대신 특정 포함 검색에서 작고 구체적인 인덱스를 만들 수 있다. 문서 전체를 색인하는 방식은 검색 경로를 유연하게 바꿀 수 있지만 인덱스에 담는 내용도 늘어난다. 특정 경로만 자주 찾는다면 그 표현식에 대한 인덱스가 더 적합할 수 있다.

MySQL의 JSON 자료형 설명도 JSON 문서를 내부 바이너리 형식으로 변환해 저장한다고 밝힌다. MySQL은 JSON 열 자체를 직접 색인하지 않고, 필요한 스칼라 값을 추출하는 생성 열에 인덱스를 둘 수 있다. InnoDB에서는 JSON 배열의 다중값 인덱스도 제공한다. 자주 검색하는 속성이 몇 개로 고정돼 있다면 생성 열은 어떤 값이 검색 경로인지 명시적으로 드러낸다.

결국 두 제품의 차이는 문서가 바이너리인지가 아니라 검색 조건을 어떻게 인덱스로 연결하느냐에 있다. 여러 키를 다양한 조합으로 탐색한다면 PostgreSQL의 jsonb 연산자와 GIN 구성이 편리할 수 있다. 정해진 속성을 반복해서 찾는다면 MySQL의 생성 열 방식으로도 요구를 충족할 수 있다. 어느 쪽이 빠른지는 문서 크기, 값의 분포, 검색식, 갱신 빈도까지 포함한 작업량에 좌우된다.

인덱스를 만들고도 쿼리가 쓰지 못할 수 있다

MySQL에서는 생성 열에 인덱스가 있어도 쿼리 표현식과 생성 열의 정의가 맞아야 옵티마이저가 이를 후보로 삼는다. 생성 열 인덱스 최적화 문서는 표현식의 형태와 결과 자료형이 같아야 한다고 설명하며, JSON에서 뽑은 문자열을 비교할 때 JSON_UNQUOTE()가 필요한 경우도 보여준다. 경로만 비슷한 표현식이나 자료형이 다른 비교는 같은 인덱스 사용을 보장하지 않는다.

이 제약은 애플리케이션의 조건식이 바뀌면 중요해진다. JSON 경로를 달리 쓰거나 문자열 처리 방식을 바꾸면 기존 생성 열이 여전히 검색에 활용되는지 실행 계획에서 확인해야 한다. PostgreSQL에서도 jsonb 열에 GIN 인덱스를 하나 만들었다고 모든 연산이 그 인덱스를 쓰는 것은 아니다. 문서의 일부 경로에 연산자를 적용하는 쿼리는 해당 표현식용 인덱스가 필요할 수 있다.

고객 식별자나 상태처럼 자주 필터링하고 조인하는 값이 거의 고정돼 있다면, 이를 JSON 내부에만 둘 필요가 있는지도 별도 판단이다. 일반 열로 분리하면 자료형, 제약 조건, 인덱스의 역할을 스키마에 직접 표현할 수 있다. 이 선택은 JSON 기능 경쟁보다 데이터 모델의 문제다. JSON을 많이 저장한다는 이유만으로 어느 제품이 더 적합하다고 결정할 수 없는 이유이기도 하다.

운영 경험과 이전 비용은 어떻게 반영할까

이미 MySQL에서 돌아가는 서비스에는 SQL과 데이터만 축적된 것이 아니다. 백업과 복구 절차, 모니터링 지표, 배포 순서, 장애 시 담당자의 판단도 현재 환경에 맞춰져 있다. PostgreSQL로 옮기면 이런 절차를 다시 구성하고 복구 가능한지 검증해야 한다. 따라서 현재 병목이 모호하다면 다른 제품의 벤치마크 결과보다 기존 환경에서 해결할 수 있는 범위를 먼저 보는 편이 합리적이다.

이전에는 자료형 변환, 기본값과 문자 비교, 트랜잭션 동작에 의존한 SQL과 애플리케이션 코드의 점검이 따른다. MySQL의 JSON 경로와 생성 열 인덱스에 맞춘 검색식도 PostgreSQL의 연산자와 인덱스 구조로 다시 설계해야 한다. 데이터 복사가 끝나도 같은 검색 결과와 응답 시간을 내는지, 문제가 생겼을 때 되돌릴 수 있는지가 별도 과제가 된다. 기대 성능 개선이 이 범위의 작업을 감당할 만큼 큰지 비교해야 한다.

새 서비스와 기존 서비스의 결정선

새 서비스의 선택에는 대표 트랜잭션이 중요하다. 같은 요청 안에서 무엇을 읽고 어떤 행을 바꾸는지, JSON의 어느 경로를 얼마나 자주 검색하는지에 따라 필요한 인덱스와 동시성 특성이 달라진다. 혼합 부하가 핵심인 경우에는 PostgreSQL을 강한 후보로 두되, 읽기 전용 수치의 근접함과 팀의 MySQL 운영 역량도 함께 반영해야 한다.

기존 서비스에서는 이전의 목적을 구체적인 병목에 묶는 편이 낫다. 느린 요청이 단순 조회인지, 복잡한 집계인지, 쓰기 경합이 있는 트랜잭션인지에 따라 공개 측정의 관련성이 달라진다. 해당 요청을 재현했을 때 얻을 개선 폭이 SQL 수정과 이전·검증·복구 비용을 넘어서는 경우에만 제품 교체의 실익이 분명해진다.

함께 읽기:

공유:

뉴스레터 구독

최신 Web3, AI, 암호화폐 뉴스를 이메일로 받아보세요.

0