정규화만으로는 실무 성능 요구를 모두 만족시키기 어렵다. 특히 주문 내역, 주문 상세, 통계처럼 조회 빈도가 높은 기능에서는 JOIN과 복잡한 집계를 매번 수행하면 성능이 급격히 떨어진다.

그래서 적절한 범위에서 **역정규화(denormalization)**를 적용한다.

3-1. 파생 컬럼 추가 – total_amount

orders 테이블에는 주문 시점마다 다음과 같은 집계가 필요하다.

이를 매번 조회할 때마다 SUM()으로 계산하면, 주문 상세가 많은 경우 상당한 부하가 발생한다. 그래서 주문 생성 시에 아예 총 주문 금액을 orders.total_amount에 저장해 둔다.

UPDATE orders
SET total_amount = (
  SELECT SUM(order_price * order_quantity)
  FROM order_item
  WHERE order_id = :orderId
)
WHERE order_id = :orderId;

이제 주문 목록 화면에서 총 금액을 보여줄 때는 복잡한 집계가 아니라 단순 읽기만 수행한다.

SELECT order_id, member_id, total_amount, order_status, ordered_at
FROM orders
WHERE member_id = :memberId
ORDER BY ordered_at DESC;

3-2. 주문 상세에서 상품명/가격 역정규화

order_item 테이블은 원래라면 product_id만 가지고 있고, 상품명이나 가격을 조회하려면 product와 JOIN을 해야 한다.

하지만 주문 상세 조회는 매우 빈번하고, 상품명과 주문 당시 가격은 히스토리 보존 관점에서도 주문에 붙어 있는 것이 의미가 있다.

그래서 order_item에 다음 컬럼을 추가한다.

이제 주문 상세를 조회할 때는 이런 쿼리가 가능하다.

SELECT
  order_item_id,
  product_name,
  order_price,
  order_quantity
FROM order_item
WHERE order_id = 3;

상품명과 가격을 위해 더 이상 product 테이블과 JOIN할 필요가 없다.

만약 역정규화를 하지 않았다면, 매번 다음과 같이 조인을 수행해야 한다.

SELECT
  oi.order_item_id,
  p.product_name,
  oi.order_price,
  oi.order_quantity
FROM order_item oi
JOIN product p ON oi.product_id = p.product_id
WHERE oi.order_id = 3;