SQL Server 쿼리 처리 아키텍처 _ SQL 문 처리 (2/4)

– 뷰(View) 확인

 

  • Version : SQL Server 2005, 2008, 2008R2, 2012

 

SQL Server 쿼리 프로세서에서는 인덱싱된 뷰와 인덱싱 되지 않은 뷰가 다르게 처리 된다.

인덱싱된 뷰의 행은 테이블과 동일한 형식으로 데이터베이스에 저장 된다. 쿼리 프로세서에서 쿼리 계획에 인덱싱된 뷰를 사용하기로 결정하면 인덱싱된 뷰는 기본 테이블과 동일한 방법으로 처리 된다.

인덱싱되지 않은 뷰는 뷰의 정의만 저장되고 뷰의 행은 저장되지 않는다. 쿼리 최적화 프로그램은 인덱싱되지 않은 뷰를 참조하는 SQL문에 대해 작성하는 실행 계획에 뷰 정의의 논리를 추가 한다.

 

SQL Server 쿼리 최적화 프로그램에서 인덱싱된 뷰의 사용 여부를 결정하는 논리는 테이블 인덱스를 결정하는 데 사용되는 논리와 유사하다. SQL문 전체나 일부가 인덱싱된 뷰의 데이터를 포괄하고 해당 뷰의 인덱스가 저렴한 비용의 액세스 경로로 확인되면 쿼리의 이름이 이 뷰를 참조하는지 여부와 관계 없이 인덱스가 선택 된다.

 

SQL 문에서 인덱싱되지 않은 뷰를 참조할 경우 파서와 쿼리 최적화 프로그램은 SQL문의 원본과 뷰의 원본을 모두 분석하고 단일 실행계획을 세운다.

SQL문과 뷰의 별도 실행 계획이 있는 것은 아니다.

 

[뷰 생성]

USE AdventureWorks2008R2;

GO

CREATE VIEW EmployeeName AS

SELECT h.BusinessEntityID, p.LastName, p.FirstName

FROM HumanResources.Employee AS h

JOIN Person.Person AS p

ON h.BusinessEntityID = p.BusinessEntityID;

GO

 

 

 

[뷰를 사용한 실행 계획]

위에서 생성한 뷰를 기반으로 아래 스크립트에서 두 SQL문이 모두 기본 테이블에 대해 동일한 작업을 수행하고 동일한 결과를 생성한다.

/* SELECT referencing the EmployeeName view. */

SELECT LastName AS EmployeeLastName, SalesOrderID, OrderDate

FROM AdventureWorks2008R2.Sales.SalesOrderHeader AS soh

JOIN AdventureWorks2008R2.dbo.EmployeeName AS EmpN

ON (soh.SalesPersonID = EmpN.BusinessEntityID)

WHERE OrderDate > '20020531';

 

 

 

/* SELECT referencing the Person and Employee tables directly. */

SELECT LastName AS EmployeeLastName, SalesOrderID, OrderDate

FROM AdventureWorks2008R2.HumanResources.Employee AS e

JOIN AdventureWorks2008R2.Sales.SalesOrderHeader AS soh

ON soh.SalesPersonID = e.BusinessEntityID

JOIN AdventureWorks2008R2.Person.Person AS p

ON e.BusinessEntityID =p.BusinessEntityID

WHERE OrderDate > '20020531';

 

 

 

[뷰 힌트]

쿼리의 뷰에 힌트를 넣으면 뷰가 확장되어 기본 테이블에 액세스할 때 발견되는 다른 힌트와 서로 충돌 할 수 있다. 이경우 쿼리에서 오류를 반환 한다.

 

다음 예제 스크립트는 뷰에 적용된 SERIALIZABLE 힌트가 뷰 확장시 원본 테이블의 Person.Address, Person.StateProvince 테이블에 모두 전파되기 때문에 이 쿼리는 Person.Address의 LOCK 힌트와 충돌로 인하여 오류를 반환 한다.

 

아래 스크립트는 뷰 생성시 NOLOCK 힌트를 사용하였다.

--CREATE VIEW

CREATE VIEW Person.AddrState WITH SCHEMABINDING AS

SELECT a.AddressID, a.AddressLine1,

s.StateProvinceCode, s.CountryRegionCode

FROM Person.Address a WITH (NOLOCK), Person.StateProvince s

WHERE a.StateProvinceID = s.StateProvinceID;

 

아래 스크립트는 데이터 조회 시 NOLOCK이 사용하여 생성된 뷰를 SERIALIZABLE 힌트를 사용하여 조회한 결과 이다.

SELECT AddressID, AddressLine1, StateProvinceCode, CountryRegionCode

FROM Person.AddrState WITH (SERIALIZABLE)

WHERE StateProvinceCode = 'WA';

 

 

이 외에 다양한 잠금 힌트가 서로 충돌하여 오류를 발생 한다. 중첩된 뷰의 경우에도 뷰가 확장 할 때 상속 받은 뷰는 영향을 받게 된다.

 

 

[뷰 사용과 테이블 조인 순서]

뷰를 포함하는 쿼리에 FORCE ORDER 힌트를 사용하면 정렬된 구조체에서의 뷰 위치에 따라 뷰 내의 테이블 조인 순서가 결정 된다.

-- CREATE TABLE

CREATE TABLE TBL_A(ID NVARCHAR(50),NAME NVARCHAR(50))

CREATE TABLE TBL_B(ID NVARCHAR(50),NAME NVARCHAR(50))

CREATE TABLE TBL_C(ID NVARCHAR(50),NAME NVARCHAR(50))

CREATE TABLE TBL_D(ID NVARCHAR(50),NAME NVARCHAR(50))

CREATE TABLE TBL_E(ID NVARCHAR(50),NAME NVARCHAR(50))

CREATE TABLE TBL_F(ID NVARCHAR(50),NAME NVARCHAR(50))

GO

 

INSERT INTO TBL_A VALUES ('KANG SW', 'HTTP://SQLMVP.KR')

INSERT INTO TBL_B VALUES ('KANG SW', 'HTTP://SQLMVP.KR')

INSERT INTO TBL_C VALUES ('KANG SW', 'HTTP://SQLMVP.KR')

INSERT INTO TBL_D VALUES ('KANG SW', 'HTTP://SQLMVP.KR')

INSERT INTO TBL_E VALUES ('KANG SW', 'HTTP://SQLMVP.KR')

INSERT INTO TBL_F VALUES ('KANG SW', 'HTTP://SQLMVP.KR')

GO

 

-- CREATE VIEW

CREATE VIEW VIEW1 AS

SELECT C.ID, D.NAME

FROM TBL_C AS C INNER JOIN TBL_D AS D

ON C.ID = D.ID

 

 

 

 

실행 결과 쿼리 계획에서 조인 순서는 TBL_A, TBL_B, VIEW1, TBL_E, TBL_F로 실행 된 것을 확인 할 수 있다.

 

 

[참고 자료]

http://msdn.microsoft.com/ko-kr/library/ms190237(v=sql.105).aspx

http://msdn.microsoft.com/ko-kr/library/ms187864(v=sql.105).aspx

http://sqlmvp.kr/140181977090



강성욱 / jevida@naver.com
Microsoft SQL Server MVP
Blog : http://sqlmvp.kr
Facebook : http://facebook.com/sqlmvp

No. Subject Author Date Views
Notice SQL강좌: 챗GPT와 함께 배우는 SQL Server 무료 강좌 목차와 소개 (2023년 9월 업데이트) 코난(김대우) 2023.08.18 36189
Notice Python 무료 강좌 - 기초, 중급, 머신러닝(2023년 6월 업데이트) 코난(김대우) 2021.01.01 18743
1774 SQL Server 쿼리 처리 아키텍처_실행 계획 캐싱 및 다시 사용 jevida(강성욱) 2016.09.28 1500
1773 DMV를 이용한 캐시된 저장 프로시저 통계 정보 확인 jevida(강성욱) 2016.09.28 1055
1772 SQL Server 쿼리 처리 아키텍처_저장 프로시저 및 트리거 실행 jevida(강성욱) 2016.09.27 988
1771 SQL Server 쿼리 처리 아키텍처 _ SQL 문 처리 (4/4) – 분산형 분할 뷰(View) 확인 jevida(강성욱) 2016.09.27 1386
1770 SQL Server 쿼리 처리 아키텍처 _ SQL 문 처리 (3/4) – 뷰(View)의 인덱스 확인 jevida(강성욱) 2016.09.27 1020
» SQL Server 쿼리 처리 아키텍처 _ SQL 문 처리 (2/4) – 뷰(View) 확인 jevida(강성욱) 2016.09.27 1492
1768 SQL Server 쿼리 처리 아키텍처 _ SQL 문 처리 (1/4) – SQL 문 최적화 및 Worktables jevida(강성욱) 2016.09.27 984
1767 SQL Server DMV를 이용한 통계 정보 확인 jevida(강성욱) 2016.09.27 2224
1766 DMV를 이용한 플랜 캐시 사용 정보 확인 jevida(강성욱) 2016.09.27 1270
1765 SQL Server 테이블 및 인덱스 구조 아키텍처(4/4) – 비클러스터형 인덱스 구조 jevida(강성욱) 2016.09.27 1151
1764 SQL Server 테이블 및 인덱스 구조 아키텍처(3/4) – 클러스터형 인덱스 구조 jevida(강성욱) 2016.09.27 1443
1763 SQL Server 테이블 및 인덱스 구조 아키텍처(2/4) – 힙 구조 jevida(강성욱) 2016.09.27 1148
1762 SQL Server 테이블 및 인덱스 구조 아키텍처(1/4) – 테이블 및 인덱스 구성 jevida(강성욱) 2016.09.27 1219
1761 SQL Server 트랜잭션 로그 아키텍처(4/4) – 미리 쓰기 트랜잭션 로그 jevida(강성욱) 2016.09.27 1596
1760 SQL Server 트랜잭션 로그 아키텍처(3/4) – 검사점 및 로그의 활성 부분 jevida(강성욱) 2016.09.27 1103
1759 SQL Server 트랜잭션 로그 아키텍처(2/4) – 트랜잭션 로그 물리 아키텍처 jevida(강성욱) 2016.09.27 1149
1758 SQL Server 트랜잭션 로그 아키텍처(1/4) – 트랜잭션 로그 논리 아키텍처 jevida(강성욱) 2016.09.27 1297
1757 파일 및 파일 그룹 아키텍처 jevida(강성욱) 2016.09.27 849
1756 SQL Server 페이지 및 익스텐트 아키텍처(4/4) – 수정된 익스텐트 추적 jevida(강성욱) 2016.09.27 1186
1755 SQL Server 페이지 및 익스텐트 아키텍처(3/4) – 개체에서 사용하는 공간 관리 jevida(강성욱) 2016.09.27 1034





XE Login