Search

[필수:정합+성능]날짜 컬럼 자료형과 조건값 형식 불일치

① YYYYMMDD — VARCHAR(8) 컬럼

실제 컬럼: startdbpg.tr_ord_big.ord_ymd. 2024년 1월 주문 건수 조회.

BAD: 에러 없이 잘못된 결과(이 환경에서는 0건)

YYYYMMDD 컬럼에 하이픈 포함 조건
SELECT COUNT(*) AS ord_cnt FROM startdbpg.tr_ord_big o WHERE o.ord_ymd >= '2024-01-01' AND o.ord_ymd < '2024-02-01' ;
SQL
복사
SQL 결과 보기
•
저장된 값은 8자리 YYYYMMDD인데 하이픈이 들어간 조건값을 쓰면, 에러 없이 잘못된 결과가 나옵니다.
•
문자열은 앞 글자부터 하나씩 비교합니다. 다섯 번째 글자에서 '0'과 '-'를 비교하게 되어, '20240115'가 '2024-02-01'보다 크다고 판단합니다. 그래서 이 환경에서는 조건을 만족하는 행이 하나도 없습니다.

GOOD: 628,272건(정상)

문자열 저장 형식에 맞게 비교
SELECT COUNT(*) AS ord_cnt FROM startdbpg.tr_ord_big o WHERE o.ord_ymd >= '20240101' AND o.ord_ymd < '20240201' ;
SQL
복사
SQL 결과 보기
•
VARCHAR(8) 컬럼의 저장 형식에 맞춰 YYYYMMDD 8자리로 비교합니다. 유효한 날짜가 고정 길이로 일관되게 저장되어 있다면 문자열 정렬 순서가 날짜순과 일치합니다.

② DATE — 날짜 자료형

실제 컬럼: startdbpg.cm_base_dt.base_dt. 시간값 없이 일자만 저장합니다.

BAD: 11.200ms, hit=94, read=0

DATE 컬럼에 TO_CHAR 적용
SELECT d.base_dt FROM startdbpg.cm_base_dt d WHERE TO_CHAR(d.base_dt, 'YYYYMMDD') BETWEEN '20240101' AND '20240131' ;
SQL
복사
실행계획 보기
•
DATE 컬럼을 문자로 바꿔 비교해서 인덱스를 쓰지 못합니다. 1만 4천여 건을 모두 읽고 31건만 남깁니다(Seq Scan).
•
컬럼 변형 문제는 [필수:성능]WHERE 절 컬럼 변형 페이지를 참고합니다.

GOOD: 0.084ms, hit=4, read=0

DATE 컬럼을 직접 비교
SELECT d.base_dt FROM startdbpg.cm_base_dt d WHERE d.base_dt >= '2024-01-01' AND d.base_dt < '2024-02-01' ;
SQL
복사
실행계획 보기
•
DATE 컬럼을 변형하지 않고 DATE 리터럴과 직접 비교합니다. 시작일 이상·다음 기간 시작일 미만으로 조건을 작성합니다.

③ TIMESTAMP — 날짜+시간 자료형

실제 컬럼: startdbpg.tr_ord_big.ord_dtm (TIMESTAMP WITHOUT TIME ZONE). 2024년 1월 일자별 주문 건수 집계.

BAD: 6035.870ms, hit=0, read=35486

TIMESTAMP 컬럼에 TO_CHAR 적용
SELECT TO_CHAR(o.ord_dtm, 'YYYYMMDD') AS ord_ymd ,COUNT(*) AS ord_cnt FROM startdbpg.tr_ord_big o WHERE TO_CHAR(o.ord_dtm, 'YYYYMM') = '202401' GROUP BY TO_CHAR(o.ord_dtm, 'YYYYMMDD') ;
SQL
복사
실행계획 보기
•
날짜 컬럼을 문자로 바꿔서, 인덱스 전체 2,600만 건을 읽고 1월 데이터 62만 건만 남깁니다(Rows Removed by Filter: 25663500).

GOOD: 248.967ms, hit=757, read=0

TIMESTAMP 날짜 범위로 검색
SELECT TO_CHAR(o.ord_dtm, 'YYYYMMDD') AS ord_ymd ,COUNT(*) AS ord_cnt FROM startdbpg.tr_ord_big o WHERE o.ord_dtm >= '2024-01-01 00:00:00' AND o.ord_dtm < '2024-02-01 00:00:00' GROUP BY TO_CHAR(o.ord_dtm, 'YYYYMMDD') ;
SQL
복사
실행계획 보기
•
WHERE 절은 날짜 범위로 검색해 필요한 주문만 읽고, GROUP BY에서 일자 문자열로 변환해 건수를 집계합니다.
•
종료 경계와 소수 초 문제는 날짜 검색 종료 경계 오류 사례를 참고합니다.
💡

KEY POINT

•
날짜 조건은 먼저 컬럼의 자료형과 저장 형식을 확인합니다. (VARCHAR 'YYYYMMDD', DATE, TIMESTAMP)
•
문자 날짜 컬럼에 형식이 다른 값을 쓰면, 에러 없이 잘못된 결과가 나옵니다.
•
DATE·TIMESTAMP 컬럼은 문자로 바꾸지 말고, 시작 이상·다음 시작 미만으로 비교합니다.
📖 DEEP DIVE — SQL TUNER for PostgreSQL 기본원리편