인덱스 튜닝

조건이 동적으로 변하는 쿼리 문제

gw1 2025. 12. 6. 21:22

CREATE TABLE `orders` (
  `id` bigint unsigned NOT NULL DEFAULT '0',
  `user_id` int DEFAULT NULL,
  `is_paid` enum('Y','N') NOT NULL DEFAULT 'N',
  `is_cancelled` enum('Y','N') NOT NULL DEFAULT 'N',
  `is_delivered` enum('Y','N') NOT NULL DEFAULT 'N',
  `order_date` datetime DEFAULT NULL,
  PRIMARY KEY (`id`),
  KEY `idx_orders_user_id` (`user_id`),
  KEY `idx_orders_is_paid_cancel_date` (`is_paid`,`order_date`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci

 
기존 쿼리

SELECT COUNT(*)
FROM test.orders
WHERE order_date BETWEEN '2025-11-01 00:00:00' AND '2025-11-30 23:59:59'
  AND is_paid      = 'Y';

 

 
 
is_paid = 'Y' 인 orders를 카운트하는 쿼리
 
관리자 페이지에서 한달동안 총 주문 수를 카운트 하여 보여주는 쿼리로
0.2초 정도 걸려서 아무런 문제가 없었음


 
기획 요구 사항이 변경되어
 

 
필터링 조건을 설정하면 체크 박스 조건에 맞게 카운트를 하도록 요구됨
 
즉, is_paid / is_cancelled / is_delivered 의 Y N 값이 동적으로 변경됨

미 선택 시 조건 자체가 없을 수도 있음
 
Y N 비율은 전부 50 : 50으로 랜덤하게 세팅함
 
변경 후 동적 쿼리로
if문으로 조건 유무가 붙는 형태

<select id="getOrderCount">
  SELECT COUNT(*)
  FROM test.orders
  WHERE order_date BETWEEN #{start} AND #{end}
  
  <if test="paid != null and paid != ''">
    AND is_paid = #{paid}
  </if>

  <if test="delivered != null and delivered != ''">
    AND is_delivered = #{delivered}
  </if>

  <if test="cancelled != null and cancelled != ''">
    AND is_cancelled = #{cancelled}
  </if>
</select>

 
예시) is_paid = 'Y' and is_delivered = 'Y'

SELECT COUNT(*)
FROM test.orders
WHERE order_date BETWEEN '2025-11-01 00:00:00' AND '2025-11-30 23:59:59'
  AND is_paid      = 'Y'
  AND is_delivered = 'Y';
  
  SELECT COUNT(*)
FROM test.orders
WHERE order_date BETWEEN '2025-11-01 00:00:00' AND '2025-11-30 23:59:59'
  
    AND is_delivered = 'Y';

 

 
20초 걸려서 이대론 배포가 불가능함
 
관리자 페이지가 조금 느려도 괜찮은데 20초는 너무 오래걸림
 
1. 실시간 반영이 되어야함 캐싱 및 주기적인 배치로 집계 불가능
 
2. DB 내에서만 해결하세요.

'인덱스 튜닝' 카테고리의 다른 글

품절 soldout 뒤쪽으로 문제  (0) 2025.10.28
인덱스 다양한 선택의 관한 문제  (0) 2025.10.15
조인 최적화 문제  (0) 2025.10.04
주문 관련 인덱스 설계 문제  (3) 2025.09.30
like 조건에 대한 문제  (0) 2025.09.15