Spring Boot 프로젝트를 진행하다 보면 QueryDSL과 Paging을 활용하여 성능을 개선하려고 하지만, 데이터가 많아지면 여전히 한계를 경험할 수 있습니다.
이러한 문제를 해결해 나가는 방법을 모색하던 중 View를 활용하면 성능을 더욱 개선할 수 있다는 점을 알게 되었습니다.
이번 포스팅에서는 View를 활용하여 성능을 최적화하는 방법을 소개하고, 실습을 통해 직접 구현해 보겠습니다.
1. View란?
View는 하나 이상의 테이블의 결과를 저장하는 가상의 테이블입니다.
실제 데이터를 저장하지 않지만, 복잡한 쿼리를 단순하게 만들어주고, 성능을 최적화할 수 있는 기능을 제공합니다.
2. View를 사용하는 이유
View를 사용하는 이유에는 다음과 같습니다.
- 쿼리 단순화 : 복잡한 SQL을 미리 정의하여 코드에서 단순하게 조회할 수 있습니다.
- 성능 개선 : 인덱스를 적용하거나 최적화된 조회를 제공할 수 있습니다.
- 보안 강화 : 특정 컬럼만 노출하는 등의 제한을 둘 수 있습니다.
3. View를 활용한 최적화
먼저 최적화 실습을 진행하기 앞서 테이블을 생성하겠습니다.
3-1. 테이블 생성
CREATE TABLE orders (
id BIGINT PRIMARY KEY AUTO_INCREMENT,
user_id BIGINT NOT NULL,
product_id BIGINT NOT NULL,
quantity INT NOT NULL,
total_price DECIMAL(10,2) NOT NULL,
order_date DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
status VARCHAR(20) NOT NULL
);
CREATE INDEX idx_orders_order_date ON orders(order_date);
3-2. 데이터 삽입
프로시저를 활용해서 실제 성능 측정에 사용할 데이터들을 삽입하겠습니다.
DELIMITER $$
CREATE PROCEDURE InsertOrders()
BEGIN
DECLARE i INT DEFAULT 0;
WHILE i < 1000000 DO
INSERT INTO orders (user_id, product_id, quantity, total_price, order_date, status)
VALUES (FLOOR(RAND() * 10000), FLOOR(RAND() * 10000), FLOOR(RAND() * 10) + 1, RAND() * 500, NOW() - INTERVAL FLOOR(RAND() * 365) DAY, 'COMPLETED');
SET i = i + 1;
END WHILE;
END $$
DELIMITER ;
CALL InsertOrders();
3-3. View 생성 전 성능 테스트
먼저, 특정 기간 동안의 주문을 조회하는 쿼리를 실행하고 성능을 측정합니다.
SELECT * FROM orders WHERE order_date BETWEEN '2024-01-01' AND '2024-12-31' ORDER BY order_date DESC LIMIT 50;
EXPLAIN ANALYZE SELECT * FROM orders WHERE order_date BETWEEN '2024-01-01' AND '2024-12-31' ORDER BY order_date DESC LIMIT 50;
-> Sort: orders.order_date (cost=1.03e+6 rows=9.96e+6) (actual time=10424..10994 rows=8.04e+6 loops=1) -> Filter: (orders.order_date between '2024-01-01' and '2024-12-31') (cost=1.03e+6 rows=9.96e+6) (actual time=1.38..6957 rows=8.04e+6 loops=1)
3-4. View 생성 및 성능 테스트
조회 성능을 개선하기 위해 뷰(View)를 생성합니다.
CREATE VIEW recent_orders AS
SELECT id, user_id, product_id, quantity, total_price, order_date, status
FROM orders
WHERE order_date >= NOW() - INTERVAL 1 YEAR;
SELECT * FROM recent_orders ORDER BY order_date DESC LIMIT 50;
EXPLAIN ANALYZE SELECT * FROM recent_orders ORDER BY order_date DESC LIMIT 50;
-> Sort: order_date DESC (cost=1.03e+6 rows=9.96e+6) (actual time=9868..10736 rows=10e+6 loops=1) -> Filter: (orders.order_date >= <cache>((now() - interval 1 year))) (cost=1.03e+6 rows=9.96e+6) (actual time=1.57..5046 rows=10e+6 loops=1)
4. 결과 비교 및 분석
View를 사용하기 전에는 원본 테이블에서 데이터를 직접 조회하면 인덱스를 활용하더라도 많은 데이터에서 필터링이 필요하여 성능 저하가 발생할 수 있습니다.
하지만 View를 사용하면 미리 필터링 된 데이터를 기반으로 조회가 이루어지므로 불필요한 데이터 스캔이 줄어들어 성능이 향상됩니다.
실행 결과로 차이점을 확인해보자면 약 1.6초 정도 차이가 발생했습니다.
5. View 사용시 유의할 점
View를 사용하면 항상 성능이 향상되는 건 아닙니다. 다음과 같은 경우에는 오히려 성능을 떨어트릴 수 있습니다.
1. View가 복잡한 경우(Join이 많거나 서브쿼리가 있는 경우)
- View 내부에서 여러 개의 테이블을 Join 하면, 원본 테이블에서 데이터를 조회할 때마다 매번 조인이 발생해서 성능이 오히려 나빠질 수 있습니다.
2. View를 중첩해서 사용할 경우
- View 내부에서 다른 View를 참조하면, MySQL이 최적화를 제대로 하지 못해서 성능이 저하될 수 있습니다.
3. View를 잘못 설계한 경우
- View에서 특정 데이터를 미리 필터링한다고 해도 쿼리가 최적화되지 않으면 결국 전체 테이블을 읽는 것과 다를 바가 없습니다.
- 적절한 인덱스와 필터링 조건이 함께 있어야 그 성능이 극대화됩니다.
이번 포스팅에서는 온전히 View를 사용해서 성능을 최적화 시키는 방법에 대해서 알아보았습니다.
다음 포스팅에서는 더 확실한 성능 비교를 위한
View를 사용한 경우 vs Index로 튜닝한 경우 vs 서브쿼리를 직접 사용한 경우 이렇게 3가지 방법을 비교해 보겠습니다.
'Database' 카테고리의 다른 글
[서평] Do it! 오라클로 배우는 SQL 입문 (0) | 2025.03.23 |
---|---|
Oracle 데이터베이스 스키마(유저) 생성 (0) | 2025.03.05 |
Sharding & Partitioning (0) | 2025.03.04 |
Window11 Oracle Database 설치 (2) | 2024.12.14 |
Error Code: 2013. Lost connection to MySQL server during query (0) | 2024.12.01 |