DBMS 2
DA, SQL, DB보안 등 실무자를 위한 위한 DB기술 바이블!
인덱싱된 뷰 생성을 위해 거쳐야 하는 단계들은 성공적인 뷰를 구현하는데 있어서도 매우 중요합니다. 쿼리가 실행될 때 현재 세션에서 다양한 SET 옵션이 지원될 경우 동일한 표현식을 평가해도 SQL Server 2005에서 다른 결과값이 나올 수 있습니다. 예를 들어, SET 옵션인 CONCAT_NULL_YIELDS_NULL이 ON으로 설정된 이후에는 표현식‘abc’+ NULL은 NULL 값을 반환합니다. 하지만, CONCAT_NULL_YIEDS_NULL이 OFF로 설정된 후에는 동일한 표현식으로‘abc’가 생성됩니다. 인덱싱된 뷰는 뷰가 올바르게 유지 관리되고 일관된 결과를 반환할 수 있도록 현재 세션에 대한 여러 SET 옵션과 뷰가 참조한 객체에 있어 고정 값을 요구합니다. 현재 세션의 SET 옵션인 ANSI_NULLS과 QUOTED_IDENTIFIER 은 인덱스를 만드려는 뷰가 생성될 때 모두 ON으로 설정되어야 합니다. 그 이유는 이들 두 옵션이 시스템 카탈로그에서 뷰 정의를 통해 저장되기 때문입니다. 다음과 같은 경우가 발생할 때마다 현재 세션의 SET 옵션을 현재 세션의 Required Value 열에 표시된 값으로 설정해야 합니다. 인덱싱된 뷰를 생성하기 위해서는있어야 합니다. 하지만, SQL Server 2005의 경우 일단 ANSI_WARNINGS가 ON으로 설정되면 ARITHABORT 옵션도 암묵적으로 ON으로 설정되기 때문에 별도의 명시적 설정이 필요하지 않습니다. .Net SqlClient, OLE DB 또는 ODBC 서버 연결을 사용하면 인덱싱된 뷰의 생성, 사용 및 유지 관리를 위해 기본 설정값에서 SET 옵션을 수정할 필요가 전혀 없습니다. sp_configure를 사용하는 서버 수준에서나 SET 명령어를 사용하는 응용 프로그램에서 모든 DB LIB 값을 올바르게 설정해야 합니다. SET 옵션에 대한 자세한 내용은 SQL Server Books Online의“SQL Server에서의 옵션 사용”을 참조하십시오. 인덱싱된 뷰에 대한 정의는 명확해야 합니다. WHERE 및 GROUP BY 구문을 비롯해 select 목록에 있는 모든 표현식이 명확하면 뷰도 명확합 니다. 특정한 입력값 세트를 통해 평가되는 모든 확정적 표현식은 항상 동일한 결과를 반환합니다. 확정적 함수만이 확정적 표현식에 참여하게 됩니다. 예를 들어, DATEADD은 3개의 매개변수에 대해 주어진 모든 인수값 세트에서 동일한 결과를 반환한다는 점에서 확정적 함수라 할 수 있습니다. GETDATE는 동일한 인수를 통해 호출되지만 실행시 마다 반환 값이 달라진다는 점에서 확정적이라ne의“확정적 함수 및 비확정적 함수”를 참조하십시오. 표현식이 확정적임에도 불구하고 float 표현식 아키텍처나 마이크로코드 버전에 의해 결정될 수 있습니다. SQL Server 2005에서는 시스템 간의 데이터베이스 이동 시 데이터 무결성을 보장하기 위해 이러한 표현식을 인덱싱된 뷰의 키 가 아닌 열로서만 참여시키고 있습니다. float 표현식을 포함하지 않은 확정적 표현식을 정확한 표현식이라고 합니다. 지속적인 확정적 표현식이나 정확한 표현식만이 인덱싱된 뷰의 키열 및 WHERE 또는 GROUP BY 구문에 포함될 수 있습니다. 지속적 표현식은 일반 열과 PERSISTED라고 표시된 계산된 열을 포함한 저장Y 함수와 IsDeterministic 속성을 사용하여 뷰 열이 확정적인지 확인하십시오. 또한 COLUMNPROPERTY 함수와 IsPrecise 속성을 사용해 SCHEMABINDING에서 뷰의 확정적 열이 정확한지 확인하십시오. COLUMNPROPERTY는 속성이 TRUE면 1을, FALSE나 유효하지 않은 입력을 뜻하는 NULL이면 0을 반환합니다. 예를 들어 이 스크립트에서 b 열이 real 유형이기 때문에 SELECT는 IsPrecise에 대해 0을 반환합니 정확한지 확인할 수 있습니다. 인덱싱 가능한 뷰 세트는 가능한 뷰 세트의 하위 집합이라 할 수 있습니다. 인덱싱이 가능한 모든 뷰는 인덱스 사용 여부에 관계없이 존재할 수 있습니다. 뷰에서 클러스터된 고유 인덱스를 생성하기 위해서는 설계 지침의“일관성있는 결과를 얻기 위한 SET 옵션 사용”과“확정적 함수 사용”부분 에서 언급한 요구 사항 외에도 아래와 같은 요구 사항을 충족해야 합니다. 뷰가 참조하는 기본 테이블은 테이블 생성 시 SET 옵션 ANSI_NULLS를 올바른 값으로 설정해야 합니다. OBJECTPROPERTY 함수를 사용해서 기존 테이블의 ANSI_NULLS 값을 확인할 수 있습니다. 뷰가 참조하는 사용자 정의 함수는 WITH SCHEMABINDING 옵션을 사용하여 생성해야 합니다. SQL Server 2005의 뷰에서 인덱스를 생성하려면 뷰 정의에 다음이 포함되지 않아야 합니다: 주 인덱싱된 뷰는 float 및 real 열을 포함할 수 있지만, 지속되지 않는 계산된 열일 경우에는 클러스터된 인덱스 키에 포함될 수 없습니다. GROUP BY가 존재할 경우 VIEW 정의에는 다음과 같은 제약이 따릅니다. 이러한 제약은 인덱싱된 뷰 정의에만 적용됩니다. 쿼리는 이러한 GROUP BY 제약을 충족하지 않은 경우에도 실행 계획에서 인덱싱된 뷰를 사용할 수 있습니다. 여기나와 있는 예제는 집계와 조인이라는 2개의 주요 쿼리 그룹에서의 인덱싱된 뷰 사용을 설명하기 위한 것입니다. 또한 인덱싱된 뷰의 적용 가능 여부를 판단할 때 쿼리 최적화 프로그램이 사용하는 조건을 보여주고 있습니다. 전체 조건 목록에 관한 내용은“쿼리 최적화 프로그램의 인덱싱된 뷰 사용 방법”을 참조하십시오. 쿼리는 SQL Server 2005에서 제공되는 샘플 데이터베이스인 AdventureWorks의 테이블을 토대로 하며 작성과 함께 실행 가능합니다. SQL Server Management Studio의 Display Estimated Execution Plan 도구를 사용해서 뷰 생성 이전이나 이후에 쿼리 최적화 프로그램이 선택한 계획을 보고자 할 수 있습니다. 여기 나와있는 예제들은 최적화 프로그램이 어떻게 비용이 낮은 실행 계획을 선택하는지 보여주기 위한 것이지만, AdventureWorks 샘플 데이터베이스는 성능 이점을 보여주기에는 너무 작습니다. 예제를 살펴보기 앞서 이러한 명령어를 실행하여 세션에 올바른 옵션이 설정되어 있는지 확인하십시오. 아래 쿼리는 Sales.SalesOrderDetail 테이블에서 총 할인율이 가장 큰 5개 제품을 반환하는 2가지 방법을 보여주고 있습니다. 쿼리 최적화 프로그램이 선택한 실행 계획에는 다음이 포함되어 있습니다. Rebate 열에 필요한 집계를 포함하는 인덱싱된 뷰를 추가하면 Query 1에 대한 쿼리 실행 계획이 변경됩니다. 대규모 테이블(수백만 개의 행)에서 쿼리 성능은 크게 개선됩니다. Query 1에 대한 실행 계획은 최적화 프로그램에서 Vdiscount1 뷰가 사용되고 있다는 것을 보여줍니다. 그러나, SUM(UnitPrice*OrderQty*UnitPriceDiscount) 집계를 포함하고 있지 않다는 점에서 이 뷰는 Query 2에서 사용되지 않을 것입니다. 두 쿼리 모두를 지원하는 또 다른 인덱싱된 뷰를 생성할 수 있습니다. 이러한 인덱싱된 뷰를 사용할 경우, Vdiscount1 삭제 이후 두 쿼리에 대한 쿼리 실행 계획에는 다음이 포함됩니다. 쿼않는 경우에도 최저의 실행 비용을 제공한다는 점에서 뷰를 선택했습니다. Query 3은 이전 쿼리와 유사하지만 ProductID가 뷰 정의에 포함되지 않는 SalesOrderID 열로 교체되었습니다. 이는 쿼리 계획에서 인덱싱된 뷰를 사용하기 위해서는 뷰 정의 시 테이블에 있는 쿼리 select 목록의 모든 표현식은 선택 뷰 목록에서 추론해야 한다는 조건에 위배되는 것입니다. 이러한 쿼리를 지원하기 위해서는 별도의 인덱싱된 뷰가 필요합니다. SalesOrderID를 포함하도록 Vdiscount2를 수정할 수 있었지만, 그 결과 뷰에는 원래 테이블 만큼이나 많은 열이 포함되었고 이로 인해 기본 테이블 사용과 비교해 성능 개선을 기대하기 어려웠습니다. 각 제품에 대한 평균 가격을 산출하는 쿼리입니다. 복잡한 집계(예: STDEV, VARIANCE, AVG)는 인덱스 뷰의 정의에 포함될 수 없습니다. 하지만, 결합을 통해 복잡한 집계 작업을 수행하는 단순 집계 함수를 포함시킴으로써 AVG를 포함한 쿼리를 실행하기 위해 인덱싱된 뷰를 사용할 수 있습니다. 이러한 인덱싱된 뷰에는 AVG 함수 실행에 필요한 단순 집계 함수가 포함됩니다. View 3 생성 후 Query 4가 실행되면 실행 계획은 사용 중인 뷰를 표시합니다. 최적화 프로그램은 뷰의 단순 집계 열인 Price와 Count에서 AVG 표현식을 추론할 수 있습니다. 이 쿼리는 1가지 검색 조건을 추가로 포함하고 있다는 점을 제외하고는 Query 4와 동일합니다. 추가 검색 조건이 뷰 정의에 포함되지 않은 테이블의 열만 참조함에도 불구하고 View 3은 이 쿼리를 위해 작동하게 됩니다. 쿼리 최적화 프로그램은 이 쿼리에서 View 3을 사용할 수 없습니다. 추가된 검색 조건 od.UnitPrice>10에는 뷰 정의 시 테이블의 열이 포함되지만, 이 열은 GROUP BY 목록에 표시되지 않고 검색 조건자도 뷰 정의에 표시되지 않습니다. 반대로, 새로운 검색 조건인 od.ProductID between 0 and 995에 정의된 열이 뷰 정의의 GROUP BY 구문에 포함되기 때문에 쿼리 최적화 프로그램은 Query 7에서 View 3을 사용할 수 있습니다. 이 뷰는 쿼리의 AVG가 계산되도록 뷰 정의에 SumPrice 및 Count 열을 포함시켜 Query 6에 대한 조건을 충족할 것입니다. Sales.SalesOrderHeader 테이블에 대한 조인이 추가되는 쿼리에서도 View 4의 동일 인덱스가 사용될 것입니다. 이 쿼리는 쿼리 FROM 구문에 열거된 테이블은 인덱싱된 뷰의 FROM 구문에 있는 테이블의 상위 집합이어야 한다는 조건을 충족합니다. 마지막 2개의 쿼리는 Query 8을 변형한 것입니다. 각각의 변형 쿼리는 최적화 프로그램 조건 가운데 하나에 위배되고 Query 8과 달리 View 4 를 사용할 수 없습니다. 뷰 정의의 UnitPrice > 10과 쿼리의 UnitPrice > 25 간의 WHERE 구문 불일치와 UnitPrice가 뷰에 나타나지 않는다는 사실 때문에 Q8a는 인덱싱된 뷰를 사용할 수 없습니다. 이러한 쿼리 검색 조건자는 뷰 정의에 있는 검색 조건자의 상위 집합이 되어야 합니다. Sales.SalesOrderHeader 테이블이 인덱싱된 뷰 V4 정의에 참여하지 않는다는 사실에 유의하십시오. 그럼에도 불구하고 이 테이블에 조건자를 추가하면 인덱싱된 뷰를 사용할 수 없게 됩니다. 추가된 조건자가 아래 Query 8b에 나타난 집계에 참여하는 추가 행을 변경 또는 제거할 수 있기 때문입니다. View 4a는 select 목록 및 GROUP BY 구문에 UnitPrice 열을 포함시킴으로써 View 4를 확장합니다. 25 이상의 값만 남겨 두도록 10 이상으로 알려진 UnitPrice 값이 추가 필터링되기 때문에 Query 8a는 View 4a를 사용할 View 5는 select 및 GROUP BY 목록에 표현식을 포함하고 있습니다. LineTotal은 계산된 열이기 때문에 그 자체가 표현식이라는 점에 주목하 십시오. 이 표현식은 FLOOR 함수에 대한 호출 내에서 중첩됩니다. Query 9는 select 및 GROUP BY 목록에 FLOOR(LineTotal) 표현식을 포함하고 있습니다. SQL Server 2005의 표현식으로 뷰 일치가 확장됨에 따라 이 쿼리는 View 5에서 인덱스를 사용할 수 있습니다. View 6은 매월 마지막 3일 간 품목 번호에 대한 정보를 저장합니다. 적은 수의 페이지에 이들 행을 클러스터하기 때문에 이 기간 동안의 Sales.SalesOrderDetail에 대한 쿼리를 신속하게 처리할 수 있습니다. 아래 쿼리는 View 6와 일치하며 시스템은 Sales.SalesOrderDetail 테이블 전체를 스캔하는 대신 뷰에서 VendJuly04Ind 인덱스를 스캔하는 계획을 생성할 수 있습니다. 또한 이는 표현식 동치(뷰가 아닌 쿼리에서 날짜 순서가 다르고 데이터 형식이 서로 다르기 때문)와 조건자 포함(뷰에 저장된 결과의 하위 집합에 대해 쿼리가 실행되기 때문)을 입증합니다. 또한 개발자들은 때때로 특수한 무결성 제약 조건을 적용하는 데 인덱싱된 뷰를 사용하는 것이 편리하다는 사실을 발견하게 됩니다. 예를 들 어, 인덱싱된 뷰에서는“열에 여러 개의 0 값이 있는 경우를 제외하고 테이블 T의 열 a는 고유하다”는 제약 조건을 적용할 수 있습니다. 아래에 나와있는 인덱싱된 뷰 View7은 이러한 제약 조건을 적용합니다. 다음과 같은 스크립트를 실행하면 View 7은 최종 삽입 작업 이전까지 성공적으로 실행됩니다. 이러한 명령문은 0이 아닌 중복 값을 추가할 수 있기 때문에 허용되지 않습니다. Q. 인덱스를 생성할 수 있는 뷰 종류에 제약이 있는 이유는 무엇입니까? A. 뷰 유지 관리를 점진적으로 확대하는 것이 논리적으로 가능하도록 하고 유지 관리에 대한 부담을 증가시키는 뷰 생성 기능을 제한하며 SQL Server 시스템의 복잡성을 줄이기 위한 것입니다. 대형 뷰 세트가 비확정적이고 컨텍스트 종속적이기 때문에 DML 연산에 따라 컨텐트가 ‘변경’됩니다. 이들 뷰는 인덱싱을 실행할 수 없습니다. GETDATE 또는 SUSER_SNAME라고 정의된 모든 뷰를 예로 들 수 있습니다. Q. 뷰의 첫번째 인덱스가 클러스터되어야 하고 고유해야 하는 이유는 무엇입니까? A. 인덱싱된 뷰를 유지 관리하는 동안 키 값으로 뷰 레코드를 손쉽게 검색할 수 있도록 하고 유지 관리에 특별 로직이 필요한 복제본이 포함된 뷰가 생성되는 것을 막기 위해서는 고유해야 합니다. 또한 클러스터된 인덱스만이 고유한 값을 갖도록 하고 동시에 여러 행을 저장할 수 있기 때문에 클러스터되어야 합니다. Q. 쿼리 최적화 프로그램이 쿼리 계획에서의 사용을 위해 인덱싱된 뷰를 선택하지 않는 이유는 무엇입니까? A. 최적화 프로그램이 인덱싱된 뷰를 선택하지 않는 이유는 크게 3가지로 볼 수 있습니다. Q. 일주일에 한 번 데이터 웨어하우스를 업데이트하고 있습니다. 인덱싱된 뷰 때문에 주간에는 쿼리 속도는 향상되었지만 업데이트 속도는 느려졌습니다. 어떻게 해야 합니까? A. 주 단위의 업데이트에 앞서 인덱싱된 뷰를 삭제하고 이후 이를 다시 생성하십시오. Q. 뷰 복제본이 있기는 하지만 실제로 이를 유지 관리하고 싶습니다. 어떻게 해야 합니까? A. 원하는 뷰의 모든 열이나 표현식을 그룹화해서 COUNT_BIG(*) 열을 추가한 뷰를 생성한 다음, 그룹화 열에서 클러스터된 고유 인덱스를 생성하십시오. 그룹화 프로세스는 고유성을 가져야 합니다. 이는 실제 동일한 뷰가 아니지만 사용자의 요구를 충족할 수 있습니다. Q. 다른 뷰 위에 정의된 뷰를 가지고 있습니다. SQL Server는 상위 레벨 뷰의 인덱싱을 지원하지 않을 것입니다. 어떻게 해야 합니까? A. 중첩된 뷰에 대한 정의를 상위 레벨 뷰까지 직접 확장하십시오. 그런 다음, 이를 인덱싱하거나 가장 안쪽의 뷰를 인덱싱하거나 뷰를 인덱싱하지 않을 수 있습니다. Q. 인덱싱된 뷰가 WITH SCHEMABINDING로 정의되어야 하는 이유는 무엇입니까? A. 사용자의 뷰 액세스에 관계없이 Q. 인덱싱된 뷰에서 OUTER JOIN을 사용할 수 없는 이유는 무엇입니까? A. 기본 테이블에 데이터를 삽입하면 OUTER JOIN에 따라 인덱싱된 뷰에서 행이 논리적으로 사라질 수 있습니다. 따라서, OUTER JOIN 뷰의 업데이트가 점차 복잡해지고 표준 (INNER) JOIN 기반의 뷰에 비해 업데이트 속도도 느려질 수 있습니다. Microsoft SQL Server 2005 Books Online에는 인덱싱된 뷰에 대한 자세한 정보가 포함되어 있습니다. 자세한 내용은 다음을 참조하십시오.인덱싱된 뷰 생성
인덱싱된 뷰 생성
일관된 결과를 얻기 위한 SET 옵션 사용
SET 옵션
필요한 값
기본 서버 값
Net SqlClient,
OLE DB 및
ODBC 값DB LIB 값
ANSI_NULLS
ON
OFF
ON
OFF
ANSI_PADDING
ON
OFF
ON
OFF
ANSI_WARNINGS
ON
OFF
ON
OFF
CONCAT_NULL_YIELDS_NULL
ON
OFF
ON
OFF
NUMERIC_ROUNDABORT
OFF
OFF
OFF
OFF
NUMERIC_ROUNDABORT
ON
OFF
ON
OFF
확정적 함수 사용
CREATE TABLE T(a int, b real, c as getdate(), d as a+b)
CREATE VIEW VT WITH SCHEMABINDING AS SELECT a, b, c, d FROM dbo.T
SELECT object_id‘( VT’), COLUMNPROPERTY(object_id‘( VT’),’b’,’IsPrecise’)
추가 요구 사항
기본 테이블 요구 사항
함수 요구 사항
뷰 요구 사항
뷰 제약
ANY, NOT ANY
OPENROWSET, OPENQUERY, OPENDATASOURCE
부정확한(float, real) 값에 대한 계산
OPENXML
COMPUTE, COMPUTE BY
ORDER BY
부정확한 결과를 생성하는 CONVERT
OUTER 조인
COUNT(*)
클러스터된 인덱스가 비활성화 되었을 경우 기본 테이블 참조
GROUP BY ALL
다른 데이터베이스의 테이블이나 함수 참조
추론된 테이블(FROM 목록의 하위 쿼리)
다른 뷰 참조
DISTINCT
ROWSET 함수
EXISTS, NOT EXISTS
자체 조인
집계 결과에 대한 표현식
(예: SUM(x)+SUM(x))STDEV, STDEVP, VAR, VARP, AVG
완전 텍스트 형식의 조건자
(CONTAINS, FREETEXT, CONTAINSTABLE, FREETEXTTABLE)하위 쿼리
부정확한 상수(예: 2.34e5)
nullable 표현식의 SUM
인라인 또는 테이블 반환 함수
테이블 힌트(예: NOLOCK)
MIN, MAX
text, ntext, image, filestream, XML 열
비확정적 표현식
TOP
비 유니코드 비교
UNION
SQL Server 2005가 탐지할 수 있는 모순으로 뷰가 비어있다는 것을 의미
(예: where 0=1 등 ...)
GROUP BY 제약
인덱스 요구 사항
예제
설치
SET ANSI_NULLS ON
SET ANSI_PADDING ON
SET ANSI_WARNINGS ON
SET CONCAT_NULL_YIELDS_NULL ON
SET NUMERIC_ROUNDABORT OFF
SET QUOTED_IDENTIFIER ON
SET ARITHABORT ON
Query 1
SELECT TOP 5 ProductID, Sum(UnitPrice*OrderQty) -
Sum(UnitPrice*OrderQty*(1.00-UnitPriceDiscount)) AS Rebate
FROM Sales.SalesOrderDetail
GROUP BY ProductID
ORDER BY Rebate DESC
Query 2
SELECT TOP 5 ProductID,
SUM(UnitPrice*OrderQty*UnitPriceDiscount) AS Rebate
FROM Sales.SalesOrderDetail
GROUP BY ProductID
ORDER BY Rebate DESC
View 1
CREATE VIEW Vdiscount1 WITH SCHEMABINDING AS
SELECT SUM(UnitPrice*OrderQty) AS SumPrice,
SUM(UnitPrice*OrderQty*(1.00-UnitPriceDiscount)) AS SumDiscountPrice,
COUNT_BIG(*) AS Count, ProductID
FROM Sales.SalesOrderDetail
GROUP BY ProductID
GO
CREATE UNIQUE CLUSTERED INDEX VDiscountInd ON Vdiscount1 (ProductID)
SQL Server 2005의 인덱싱된 뷰를 통한 성능 향상 15
View 2
CREATE VIEW Vdiscount2 WITH SCHEMABINDING AS
SELECT SUM(UnitPrice*OrderQty) AS SumPrice,
SUM(UnitPrice*OrderQty*(1.00-UnitPriceDiscount)) AS SumDiscountPrice,
SUM(UnitPrice*OrderQty*UnitPriceDiscount)AS SumDiscountPrice2,
COUNT_BIG(*) AS Count, ProductID
FROM Sales.SalesOrderDetail
GROUP BY ProductID
GO
CREATE UNIQUE CLUSTERED INDEX VDiscountInd ON Vdiscount2 (ProductID)
Query 3
SELECT TOP 3 SalesOrderID,
SUM(UnitPrice*OrderQty*UnitPriceDiscount) OrderRebate
FROM Sales.SalesOrderDetail
GROUP BY SalesOrderID
ORDER BY OrderRebate DESC
Query 4
SELECT p.Name, od.ProductID,
AVG(od.UnitPrice*(1.00-od.UnitPriceDiscount)) AS AvgPrice,
SUM(od.OrderQty) AS Units
FROM Sales.SalesOrderDetail AS od, Production.Product AS p
WHERE od.ProductID=p.ProductID
GROUP BY p.Name, od.ProductID
View 3
CREATE VIEW View3 WITH SCHEMABINDING AS
SELECT ProductID, SUM(UnitPrice*(1.00-UnitPriceDiscount)) AS Price,
COUNT_BIG(*) AS Count, SUM(OrderQty) AS Units
FROM Sales.SalesOrderDetail
GROUP BY ProductID
GO
CREATE UNIQUE CLUSTERED INDEX iv3 ON View3 (ProductID)Query 5
SELECT p.Name, od.ProductID,
AVG(od.UnitPrice*(1.00-UnitPriceDiscount)) AS AvgPrice,
SUM(od.OrderQty) AS Units
FROM Sales.SalesOrderDetail AS od, Production.Product AS p
WHERE od.ProductID=p.ProductID AND p.Name like‘ %Red%’
GROUP BY p.Name, od.ProductIDQuery 6
SELECT p.Name, od.ProductID,
AVG(od.UnitPrice*(1.00-UnitPriceDiscount)) AS AvgPrice,
SUM(od.OrderQty) AS Units
FROM Sales.SalesOrderDetail AS od, Production.Product AS p
WHERE od.ProductID = p.ProductID AND od.UnitPrice > 10
GROUP BY p.Name, od.ProductIDQuery 7
SELECT p.Name, od.ProductID,
AVG(od.UnitPrice*(1.00-UnitPriceDiscount)) AS AvgPrice,
SUM(od.OrderQty) AS Units
FROM Sales.SalesOrderDetail AS od, Production.Product AS p
WHERE od.ProductID = p.ProductID AND od.ProductID between 0 and 995
GROUP BY p.Name, od.ProductIDView 4
CREATE VIEW View4 WITH SCHEMABINDING AS
SELECT p.Name, od.ProductID,
SUM(od.UnitPrice*(1.00-UnitPriceDiscount)) AS SumPrice,
SUM(od.OrderQty) AS Units, COUNT_BIG(*) AS Count
FROM Sales.SalesOrderDetail AS od, Production.Product AS p
WHERE od.ProductID = p.ProductID AND od.UnitPrice > 10
GROUP BY p.Name, od.ProductID
GO
CREATE UNIQUE CLUSTERED INDEX VdiscountInd on View4 (Name, ProductID)Query 8
SELECT p.Name, od.ProductID,
AVG(od.UnitPrice*(1.00-UnitPriceDiscount)) AS AvgPrice,
SUM(od.OrderQty) AS Units
FROM Sales.SalesOrderDetail AS od, Production.Product AS p,
Sales.SalesOrderHeader AS o
WHERE od.ProductID = p.ProductID AND o.SalesOrderID = od.SalesOrderID
AND od.UnitPrice > 10
GROUP BY p.Name, od.ProductID
Query 8a
SELECT p.Name, od.ProductID, AVG(od.UnitPrice*(1.00-UnitPriceDiscount))
AvgPrice, SUM(od.OrderQty) AS Units
FROM Sales.SalesOrderDetail AS od, Production.Product AS p,
Sales.SalesOrderHeader AS o
WHERE od.ProductID = p.ProductID AND o.SalesOrderID = od.SalesOrderID
AND od.UnitPrice > 25
GROUP BY p.Name, od.ProductID
Query 8b
SELECT p.Name, od.ProductID, AVG(od.UnitPrice*(1.00-UnitPriceDiscount))
AS AvgPrice, SUM(od.OrderQty) AS Units
FROM Sales.SalesOrderDetail AS od, Production.Product AS p,
Sales.SalesOrderHeader AS o
WHERE od.ProductID = p.ProductID AND o.SalesOrderID = od.SalesOrderID
AND od.UnitPrice > 10 AND o.OrderDate >‘ 20040728’
GROUP BY p.Name, od.ProductID
View 4a
CREATE VIEW View4a WITH SCHEMABINDING AS
SELECT p.Name, od.ProductID, od.UnitPrice,
SUM(od.UnitPrice*(1.00-UnitPriceDiscount)) AS SumPrice,
SUM(od.OrderQty) AS Units, COUNT_BIG(*) AS Count
FROM Sales.SalesOrderDetail AS od, Production.Product AS p
WHERE od.ProductID = p.ProductID AND od.UnitPrice > 10
GROUP BY p.Name, od.ProductID
GO
CREATE UNIQUE CLUSTERED INDEX VdiscountInd
ON View4a (Name, ProductID, UnitPrice)
View 5
CREATE VIEW View5 WITH SCHEMABINDING AS
SELECT FLOOR(LineTotal) FloorTotal, COUNT_BIG(*) C
FROM Sales.SalesOrderDetail
GROUP BY FLOOR(LineTotal)
GO
CREATE UNIQUE CLUSTERED INDEX iView5 ON View5(FloorTotal)Query 9
SELECT TOP 5 FLOOR(LineTotal), Count(*)
FROM Sales.SalesOrderDetail
GROUP BY FLOOR(LineTotal)
ORDER BY COUNT(*) DESCView 6
CREATE VIEW View6 WITH SCHEMABINDING AS
SELECT SalesOrderID, SalesOrderDetailID, CarrierTrackingNumber, OrderQty,
ProductID, SpecialOfferID, UnitPrice, UnitPriceDiscount, rowguid,
ModifiedDate
FROM Sales.SalesOrderDetail
WHERE ModifiedDate IN ( convert(datetime,‘ 2004-07-31’, 120),
convert(datetime,‘ 2004-07-30’, 120),
convert(datetime,‘ 2004-07-29’, 120) )
GO
CREATE UNIQUE CLUSTERED INDEX VEndJulyO4Ind
ON View6(SalesOrderID, SalesOrderDetailID)
GO
Query 10
SELECT h.*, SalesOrderDetailID, CarrierTrackingNumber, OrderQty,
ProductID, SpecialOfferID, UnitPrice,UnitPriceDiscount, d.rowguid,
d.ModifiedDate
FROM Sales.SalesOrderHeader as h, Sales.SalesOrderDetail as d
WHERE (d.ModifiedDate =‘ 20040729’OR d.ModifiedDate =‘ 20040730’)
and d.SalesOrderID=h.SalesOrderID
View 7
USE tempdb
GO
CREATE TABLE T(a int)
GO
CREATE VIEW View7 WITH SCHEMABINDING
AS SELECT a
FROM dbo.T
WHERE a <> 0
GO
CREATE UNIQUE CLUSTERED INDEX IV on View7(a)
GO
-- legal:
INSERT INTO T VALUES(1)
INSERT INTO T VALUES(2)
INSERT INTO T VALUES(0)
INSERT INTO T VALUES(0) -- duplicate 0
-- dissalowed:
INSERT INTO T VALUES(2)
인덱싱된 뷰에 대한 FAQ
자세한 내용