9-1-1. VIEW
대부분의 DBMS는 뷰(View)라는 기능의 객체(Object)를 지원한다. 뷰는 가상의 테이블이다. 테이블에는 실제 데이터가 저장되어 있지만, 가상의 테이블인 뷰에는 실제 데이터는 없고 뷰를 생성할 때 정의한 SQL만 DBMS 내부적으로 보관하고 있다.
아래는 상품(Item)의 모든 정보를 조회하는 SQL이다. 상품카테고리(ItemCat)와 기준코드(BaseCd)까지 조인해 관련 명칭도 가져오도록 처리하고 있다.
-- [SQL-9-1-1-a]
SELECT T1.ItemId ,T1.ItemNm
,T1.ItemCat ,T2.ItemCatNm
,T1.ItemSizeCd ,T3.BaseCdNm ItemSizeCd_NM
,T1.HotColdCd ,T4.BaseCdNm HotColdCd_NM
FROM startdb.Item T1
INNER JOIN startdb.ItemCat T2
ON (T2.ItemCat = T1.ItemCat)
LEFT OUTER JOIN startdb.BaseCd T3
ON (T3.BaseCdDv = 'ItemSizeCd' AND T3.BaseCd = T1.ItemSizeCd)
LEFT OUTER JOIN startdb.BaseCd T4
ON (T4.BaseCdDv = 'HotColdCd' AND T4.BaseCd = T1.HotColdCd);
SQL
복사
상품 정보를 조회할 때마다 위와 같이 조인을 작성해야 한다면 번거로울 수 있다. 번거로움을 피하기 위해 아래와 같은 뷰를 만들어 볼 수 있다. 아래 SQL을 실행하면 vw_ItemFull이라는 뷰가 만들어진다.
-- [SQL-9-1-1-b]
DROP VIEW IF EXISTS startdb.vw_ItemFull;
CREATE VIEW startdb.vw_ItemFull AS
SELECT T1.ItemId ,T1.ItemNm
,T1.ItemCat ,T2.ItemCatNm
,T1.ItemSizeCd ,T3.BaseCdNm ItemSizeCd_NM
,T1.HotColdCd ,T4.BaseCdNm HotColdCd_NM
FROM startdb.Item T1
INNER JOIN startdb.ItemCat T2
ON (T2.ItemCat = T1.ItemCat)
LEFT OUTER JOIN startdb.BaseCd T3
ON (T3.BaseCdDv = 'ItemSizeCd' AND T3.BaseCd = T1.ItemSizeCd)
LEFT OUTER JOIN startdb.BaseCd T4
ON (T4.BaseCdDv = 'HotColdCd' AND T4.BaseCd = T1.HotColdCd);
SQL
복사
만들어진 뷰는 아래와 같이 FROM 절에 테이블처럼 사용할 수 있다.
-- [SQL-9-1-1-c]
SELECT T1.*
FROM startdb.vw_ItemFull T1
WHERE T1.ItemId = 'AMB';
SQL
복사
뷰를 사용한 위 SQL은 DB 내부적으로 다음과 같이 실행된다. 뷰를 만들 때 사용한 SQL에 ItemId 조건이 추가되어 실행이 되는 것이다.
-- [SQL-9-1-1-d]
SELECT T1.ItemId ,T1.ItemNm
,T1.ItemCat ,T2.ItemCatNm
,T1.ItemSizeCd ,T3.BaseCdNm ItemSizeCd_NM
,T1.HotColdCd ,T4.BaseCdNm HotColdCd_NM
FROM startdb.Item T1
INNER JOIN startdb.ItemCat T2
ON (T2.ItemCat = T1.ItemCat)
LEFT OUTER JOIN startdb.BaseCd T3
ON (T3.BaseCdDv = 'ItemSizeCd' AND T3.BaseCd = T1.ItemSizeCd)
LEFT OUTER JOIN startdb.BaseCd T4
ON (T4.BaseCdDv = 'HotColdCd' AND T4.BaseCd = T1.HotColdCd)
WHERE T1.ItemId = 'AMB'; -- > 뷰에 대한 조건이 뷰로 파고들어 SQL이 만들어져 실행된다.
SQL
복사
뷰는 실제 데이터가 아닌 SQL만 저장되어 있으며, 실행 시점에 정의된 SQL이 실행되는 방식입니다. 추가로 오라클에는 Materialized View라는 실제 데이터를 저장하는 방식의 뷰도 있다. Materialized View는 데이터 변경, 입력시 뷰가 갱신되는 부담이 있으므로 성능적으로 철저한 검증과 함께 사용해야 한다.
뷰의 장점으로 다음과 같은 것들을 이야기 해볼 수 있다.
•
SQL 개발을 쉽게 해준다.
•
표준화된 형태의 데이터 제공
◦
복잡한 SQL을 하나의 뷰로 만들어, 누가 사용하든 동일한 형태의 데이터로 조회
•
데이터 보안
◦
테이블이 아닌 뷰에만 권한을 주어서 불필요한 정보에 접근 차단
위와 같은 장점이 있지만 개인적으로 뷰 사용을 선호하거나 추천하지 않는다. 각각의 장점에 다음과 같이 반론해볼 수 있다.
•
SQL 개발을 쉽게 해준다. → SQL 실력이 늘기 어렵다.
•
표준화된 형태의 데이터 제공 → 로직이 감쳐져 있어 응용과 변경이 어렵다. 데이터 출처 파악이 어렵다.
•
데이터 보안 → 최근에는 데이터 마스킹과 DB 접근 제어를 위한 별도 툴들을 주로 사용한다.
뷰의 가장 큰 문제는, 출처와 의도를 모른채 카피해서 사용하는데서 발생한다. 어떤 개발자가 특정 고객 한 명의 통합된 모든 정보를 보는 뷰를 개발했다. 한 명의 고객을 조회할 때는 성능상 부하가 크게 없는 뷰다. 문제는 이 뷰를 여기저기서 사용하기 시작했고, 한 명이 아닌 여러 명을 조회하는데도 이 뷰를 사용하기 시작했다. 결국 심각한 성능 저하가 있었으며 뷰 자체를 사용하지 않도록 모두 변경해야만 했다.
뷰를 사용한 SQL은 SQL의 내부적인 처리 과정을 제어하기가 어렵다. 성능에 문제가 있을 때 성능을 개선하기 어렵다는 뜻이다. 성능을 위해서 가능하면 뷰 사용을 자제하는 것을 권장한다.
9-1-2. INLINE VIEW
우리는 앞에서 서브쿼리를 배웠다. 이러한 서브쿼리를 FROM 절에서도 사용할 수 있다. FROM 절에 사용한 서브쿼리를 인라인 뷰(INLINE-VIEW)라고 부른다.(주로 오라클에서 인라인 뷰란 용어를 많이 쓴다.)
아래는 앞에서 살펴봤던 뷰를 사용해 아이템을 조회하는 SQL이다.
-- [SQL-9-1-2-a]
SELECT T1.*
FROM startdb.vw_ItemFull T1
WHERE T1.ItemId = 'AMB';
SQL
복사
위와 같이 뷰를 사용한 SQL은, 아래와 같이 인라인 뷰 형태로 작성할 수 있다. 뷰를 생성할 때 사용했던 SQL을 FROM 절의 서브쿼리로 그대로 사용하면 된다.
-- [SQL-9-1-2-b]
SELECT X.*
FROM (
SELECT T1.ItemId ,T1.ItemNm
,T1.ItemCat ,T2.ItemCatNm
,T1.ItemSizeCd ,T3.BaseCdNm ItemSizeCd_NM
,T1.HotColdCd ,T4.BaseCdNm HotColdCd_NM
FROM startdb.Item T1
INNER JOIN startdb.ItemCat T2
ON (T2.ItemCat = T1.ItemCat)
LEFT OUTER JOIN startdb.BaseCd T3
ON (T3.BaseCdDv = 'ItemSizeCd' AND T3.BaseCd = T1.ItemSizeCd)
LEFT OUTER JOIN startdb.BaseCd T4
ON (T4.BaseCdDv = 'HotColdCd' AND T4.BaseCd = T1.HotColdCd)
) X
WHERE X.ItemId = 'AMB';
SQL
복사
이처럼 FROM 절에 서브쿼리를 사용한 것을 인라인 뷰라고 한다. 서브쿼리는 상관 서브쿼리와 단독 서브쿼리가 있다. 상관 서브쿼리는 메인 쿼리의 값을 조건으로 받아 처리한다. 반면에 단독 서브쿼리는 메인 쿼리에서 값을 받지 않고 단독으로 처리가 가능한다. FROM 절에 작성하는 인라인 뷰는 기본적으로 단독 서브쿼리 형태로만 작성이 가능하다. 메인 쿼리에서 조건을 받는 구조로 작성할 수 없다는 뜻이다.
LATERAL JOIN
나중에 LATERAL JOIN을 설명할 예정이다. LATERAL 조인을 사용하면 인라인 뷰 안에서도 메인 쿼리(외부 쿼리)의 조건 값을 받아오는 형태로 SQL을 작성할 수 있다. LATERAL JOIN은 최근의 DBMS에서 조금씩 지원하는 기능이다.
개인적으로 아래와 같은 사유로 뷰 보다는 인라인 뷰의 사용을 권장한다.
•
SQL 실력 향상
•
향후 성능 이슈 있을 때 대처 가능성이 높아짐
•
전체 SQL 로직을 이해하는데 유리