Contents
see List작성일 2015. 06. 02.
Oracle UPDATE JOIN 빠른 업데이트
Oracle에서 다른 테이블의 값을 참조하여 UPDATE할 때, 서브쿼리 대신 UPDATE JOIN을 사용하면 성능을 크게 향상시킬 수 있습니다.
1. 일반적인 서브쿼리 UPDATE (느림)
-- 서브쿼리 방식 (비효율적)
UPDATE tb_order o
SET o.customer_name = (
SELECT c.name
FROM tb_customer c
WHERE c.customer_id = o.customer_id
)
WHERE EXISTS (
SELECT 1 FROM tb_customer c
WHERE c.customer_id = o.customer_id
);
-- 문제: 행마다 서브쿼리 실행2. UPDATE JOIN (Updatable View)
-- 인라인 뷰를 이용한 UPDATE
UPDATE (
SELECT
o.customer_name AS old_name,
c.name AS new_name
FROM tb_order o
JOIN tb_customer c ON o.customer_id = c.customer_id
)
SET old_name = new_name;
-- 조건 추가
UPDATE (
SELECT
o.price AS old_price,
p.new_price AS new_price
FROM tb_order o
JOIN tb_product p ON o.product_id = p.product_id
WHERE o.order_date >= TRUNC(SYSDATE)
)
SET old_price = new_price;3. Key Preserved 조건
-- 오류 발생 시
ORA-01779: cannot modify a column which maps to a non key-preserved table
-- 해결: 조인 대상 테이블에 PK/UK 필요
-- tb_customer.customer_id가 PK여야 함
-- 힌트로 우회 (주의 필요)
UPDATE /*+ BYPASS_UJVC */ (
SELECT o.price, p.new_price
FROM tb_order o
JOIN tb_product p ON o.product_id = p.product_id
)
SET price = new_price;4. MERGE 문 활용
-- MERGE를 이용한 UPDATE
MERGE INTO tb_order o
USING tb_customer c
ON (o.customer_id = c.customer_id)
WHEN MATCHED THEN
UPDATE SET o.customer_name = c.name;
-- 조건부 MERGE
MERGE INTO tb_order o
USING (
SELECT customer_id, name, grade
FROM tb_customer
WHERE grade = "VIP"
) c
ON (o.customer_id = c.customer_id)
WHEN MATCHED THEN
UPDATE SET
o.customer_name = c.name,
o.discount_rate = 0.1;5. 성능 비교
| 방식 | 10만 건 기준 | 특징 |
|---|---|---|
| 서브쿼리 | 느림 (분 단위) | 행별 쿼리 실행 |
| UPDATE JOIN | 빠름 (초 단위) | 한 번에 조인 |
| MERGE | 빠름 (초 단위) | 유연한 조건 |
6. 대량 UPDATE 최적화
-- 병렬 처리
ALTER SESSION ENABLE PARALLEL DML;
UPDATE /*+ PARALLEL(o, 4) */ (
SELECT o.amount, c.credit_limit
FROM tb_order o
JOIN tb_customer c ON o.customer_id = c.customer_id
)
SET amount = credit_limit * 0.1;
COMMIT;
-- 배치 처리
DECLARE
CURSOR c_batch IS
SELECT ROWID AS rid, customer_id FROM tb_order;
TYPE t_batch IS TABLE OF c_batch%ROWTYPE;
v_batch t_batch;
BEGIN
OPEN c_batch;
LOOP
FETCH c_batch BULK COLLECT INTO v_batch LIMIT 10000;
EXIT WHEN v_batch.COUNT = 0;
FORALL i IN 1..v_batch.COUNT
UPDATE tb_order SET ... WHERE ROWID = v_batch(i).rid;
COMMIT;
END LOOP;
CLOSE c_batch;
END;주의사항
- 조인 테이블에 PK/UK 있어야 UPDATE 가능
- BYPASS_UJVC 힌트는 데이터 무결성 주의
- 대량 UPDATE 전 백업 필수
- 인덱스 많으면 UPDATE 느려짐
database
| No | 작성일 | Title |
|---|---|---|
| 3380 | 2026. 08. 20. | PostgreSQL 느린 조회를 진단하는 방법: EXPLAIN ANALYZE와 복합 인덱스 실전 가이드 |
| 3348 | 2026. 08. 11. | PostgreSQL 잠금 대기 줄이기: 트랜잭션 범위와 lock_timeout 설정 실전 가이드 |
| 3316 | 2026. 08. 03. | PostgreSQL 백업 복구 실전 가이드: pg_dump·pg_restore로 장애 복구 절차 만들기 |
| 3284 | 2026. 07. 26. | PostgreSQL 인덱스가 있는데도 느린 쿼리 해결하기: EXPLAIN ANALYZE와 복합 인덱스 설계 |
| 3254 | 2026. 07. 18. | PostgreSQL 잠금 대기 진단 가이드: pg_stat_activity로 블로킹 쿼리 찾고 장애 줄이기 |
| 3202 | 2026. 07. 09. | PostgreSQL 백업 복구 검증 가이드: pg_dump와 psql로 실제 복원까지 확인하기 |
| 3170 | 2026. 07. 01. | MySQL 느린 쿼리 원인 찾기: EXPLAIN과 복합 인덱스 점검 가이드 |
| 3116 | 2026. 06. 23. | PostgreSQL 트랜잭션 충돌 줄이기: 잠금 순서와 짧은 재시도로 데드락 대응하기 |
| 3058 | 2026. 06. 15. | PostgreSQL JSONB 조회 튜닝: GIN 인덱스와 생성 컬럼으로 느린 검색 줄이기 |
| 2971 | 2026. 06. 07. | MySQL/MariaDB 복합 인덱스 설계: 느린 목록 조회를 줄이는 WHERE·ORDER BY 점검법 |