[PostgreSQL] MyBatis foreach + UNION ALL 쿼리의 성능 문제와 PostgreSQL 최적화
·
개발 (Development)/PostgreSQL
최근 프로젝트에서 MyBatis를 사용하여 여러 자산(asset) 정보를 기준으로 태그(tag) 데이터를 조회하는 기능을 구현하던 중, 성능 저하 문제가 발생했습니다. 문제의 원인을 추적해보니 foreach 루프 안에서 UNION ALL로 다수의 SELECT 구문을 반복 생성하는 방식이 주요 원인이었습니다. 본 글에서는 해당 구조의 문제점과 PostgreSQL에 적합한 최적화 방법을 실제 경험을 바탕으로 정리하였습니다.문제 상황: MyBatis foreach + UNION ALL 사용처음 작성한 쿼리는 아래와 같은 형태였습니다. SELECT item_code, tag_code, tag_name, #{item.assetId} AS asset_physical_na..
[Java/Spring Boot] Spring Boot + MyBatis 환경에서 쿼리 조회용 API를 만들기 전에 꼭 고려해야 할 5가지
·
개발 (Development)/Java
회사 내부 시스템에서 데이터를 빠르게 조회하기 위한 목적으로 Spring Boot + MyBatis + PostgreSQL 기반 백엔드 앱에 간단한 쿼리 조회용 API를 추가하고자 했습니다.하지만 단순히 API를 만드는 것만으로 끝나지 않고, 실무에서는 몇 가지 중요한 점들을 반드시 고려해야 한다는 사실을 알게 되었습니다. 이 글에서는 조회용 API를 만들기 전 꼭 고민해야 할 사항들을 정리해봅니다.1. 보안 이슈가장 주의해야 할 부분입니다.조회 전용이라고 해도 다음과 같은 보안 취약점에 노출될 수 있습니다.SQL 인젝션 위험: 입력받은 쿼리를 그대로 실행하면 악의적인 요청이 DB를 손상시킬 수 있습니다.인증/인가 없이 데이터 노출: 내부용이라도 인증 없이 공개되면 사용자 정보, 로그 등 민감한 데이터가..
[PostgreSQL] PostgreSQL JSON 쿼리 성능 개선과 Java에서의 활용
·
개발 (Development)/PostgreSQL
대용량 JSON 데이터를 PostgreSQL에서 조회하면서 분석 지표를 만들던 중, 생각보다 쿼리 속도가 느리고 결과가 기대와 다르게 나오는 문제가 있었습니다. 특히 JSON 필드 안의 특정 값들을 기준으로 통계 데이터를 구하고, 그 결과를 Java + MyBatis 환경에서 리스트 형태로 받아야 했기 때문에, 정렬이나 형식까지 모두 신경 써야 했습니다.문제 상황초기에 작성한 쿼리는 다음과 같은 형태였습니다:WITH filtered_data AS ( SELECT t."timestamp", (t."json_field" ->> 'target_metric')::double precision AS value FROM "data_table" t WHERE ..
[Java/MyBatis] MyBatis <foreach>에서 #{}와 ${} 차이, 그리고 item 두 번 쓰기
·
개발 (Development)/Java
MyBatis에서 는 IN 조건이나 다중 INSERT와 같이 반복적인 SQL을 작성할 때 아주 유용하게 쓰입니다. 하지만 이 안에서 item을 여러 번 참조하거나, #{}와 ${} 중 어떤 걸 써야 하는지 헷갈릴 수 있습니다. 이 글에서는 그 차이점과 실전에서 어떻게 써야 안전하고 효율적인지 정리해보겠습니다.#{} vs ${} 차이점구분#{}${}방식PreparedStatement 방식문자열 치환 방식용도값 바인딩 (WHERE, VALUES 등)컬럼명, 테이블명 등 SQL 조각 삽입장점SQL 인젝션 방지, 자동 타입 변환, 성능 최적화동적인 SQL 문 구조 만들기 가능단점컬럼명/테이블명 등 SQL 구조에는 사용 불가SQL 인젝션 위험 있음, 성능 저하 가능보안안전검증 없으면 매우 위험예시 비교 #{id..
[PostgreSQL] MyBatis에서 PostgreSQL JSON 데이터 처리하기
·
개발 (Development)/PostgreSQL
1. PostgreSQL에서 JSONB 데이터 평균 구하기JSONB 컬럼이 포함된 테이블에서 특정 키(예: "efficiency") 값을 필터링하고 평균을 구하는 기본적인 SQL 쿼리는 다음과 같습니다.SELECT key AS tag_name, AVG(value::NUMERIC) AS avg_valueFROM sensor_data, LATERAL jsonb_each_text(outputs)WHERE timestamp_col BETWEEN '2024-01-01 00:00:00' AND '2024-01-31 23:59:59' AND key ILIKE '%efficiency%' AND (value::NUMERIC) BETWEEN 0 AND 100GROUP BY key;이 쿼리는..