문제

간단한 인덱스보기가 있습니다. 내가 그것에 반대 할 때, 그것은 매우 느립니다. 먼저 스키마와 인덱스를 보여줍니다. 그런 다음 간단한 쿼리. 마지막으로 쿼리 계획 Screnie.

업데이트 :이 게시물 하단의 솔루션 증명.

개요

이것은 다음과 같은 것입니다 :-

CREATE view [dbo].[PostsCleanSubjectView] with SCHEMABINDING AS
    SELECT PostId, PostTypeId, 
        [dbo].[ToUriCleanText]([Subject]) AS CleanedSubject
    FROM [dbo].[Posts]

내 UDF ToUriCleanText 다양한 캐릭터를 빈 캐릭터로 대체합니다. 예를 들어. 모든 '#'숯을 대체합니다.

그런 다음 다음에 두 가지 인덱스를 추가했습니다.

인덱스

1 차 키 인덱스 (예 : 클러스터 된 인덱스)

CREATE UNIQUE CLUSTERED INDEX [PK_PostCleanSubjectView] ON 
    [dbo].[PostsCleanSubjectView] 
(
    [PostId] ASC
)
WITH (PAD_INDEX  = OFF, STATISTICS_NORECOMPUTE  = OFF, 
      SORT_IN_TEMPDB = OFF, IGNORE_DUP_KEY = OFF, DROP_EXISTING = OFF,
      ONLINE = OFF, ALLOW_ROW_LOCKS  = ON, ALLOW_PAGE_LOCKS  = ON) ON [PRIMARY]
GO

및 비 클러스터 인덱스

CREATE NONCLUSTERED INDEX [IX_PostCleanSubjectView_PostTypeId_Subject] ON 
    [dbo].[PostsCleanSubjectView] 
(
    [CleanedSubject] ASC,
    [PostTypeId] ASC
)
WITH (PAD_INDEX  = OFF, STATISTICS_NORECOMPUTE  = OFF, 
      SORT_IN_TEMPDB = OFF, IGNORE_DUP_KEY = OFF, DROP_EXISTING = OFF,
      ONLINE = OFF, ALLOW_ROW_LOCKS  = ON, ALLOW_PAGE_LOCKS  = ON) ON [PRIMARY]
GO

이제 이것은 약 25K 행이 있습니다. 전혀 큰 것은 없습니다.

다음 쿼리를 할 때는 모두 약 4 초가 걸립니다. WTF? 이것은 .. 기본적으로 즉시!

쿼리 1

SELECT a.PostId
FROM PostsCleanSubjectView a 
WHERE a.CleanedSubject = 'Just-out-of-town'

쿼리 2 (다른 위치 조항 항목 추가)

SELECT a.PostId
FROM PostsCleanSubjectView a 
WHERE a.CleanedSubject = 'Just-out-of-town' AND a.PostTypeId = 1

내가 무엇을 잘못 했습니까? UDF가 물건을 망치고 있습니까? 나는이 견해가 색인을 가지고 있기 때문에 구체화 될 것이라고 생각했다. 따라서 해당 문자열 열을 계산할 필요가 없습니다.

다음은 도움이된다면 다음은 다음과 같은 쿼리 계획의 선별입니다.alt text

또한 사용중인 인덱스를 주목하십니까? 왜 그 지수를 사용하고 있습니까?

그 지수는 ...

CREATE NONCLUSTERED INDEX [IX_Posts_PostTypeId_Subject] ON [dbo].[Posts] 
(
    [PostTypeId] ASC,
    [Subject] ASC
)
WITH (PAD_INDEX  = OFF, STATISTICS_NORECOMPUTE  = OFF, 
      SORT_IN_TEMPDB = OFF, IGNORE_DUP_KEY = OFF, DROP_EXISTING = OFF, 
      ONLINE = OFF, ALLOW_ROW_LOCKS  = ON, ALLOW_PAGE_LOCKS  = ON) ON [PRIMARY]
GO

그래, 어떤 아이디어가 있습니까?

업데이트 1 : UDF에 대한 스키마가 추가되었습니다.

CREATE FUNCTION [dbo].[ToUriCleanText]
(
    @Subject NVARCHAR(300)
)
RETURNS NVARCHAR(350) WITH SCHEMABINDING
AS 
BEGIN
   <snip>
   // Nothing insteresting in here. 
   //Just lots of SET @foo = REPLACE(@foo, '$', ''), etc.
END

업데이트 2 : 솔루션

그렇습니다.보기에서 인덱스를 사용하지 않았고 수동으로보기를 확장하지 않아야했기 때문입니다. 서버는 SQL Server 2008 Standard Edition입니다. 전체 답변은 다음과 같습니다. 증거는 다음과 같습니다. WITH (NOEXPAND) alt text

이 문제를 해결하도록 도와 주셔서 감사합니다. :)

도움이 되었습니까?

해결책

SQL Server의 어떤 판? Enterprise and Developer Edition만이 인덱스 뷰를 자동으로 사용하는 반면 다른 사람들은 쿼리 힌트를 사용하여 지원한다고 생각합니다.

SELECT a.PostId
FROM PostsCleanSubjectView a WITH (NOEXPAND)
WHERE a.CleanedSubject = 'Just-out-of-town' AND a.PostTypeId = 1

에서 MSDN의 쿼리 힌트 (Transact SQL):

인덱스 뷰는 쿼리의 선택 부분에 직접 참조되고 (NoExpand) 또는 (noExpand, index (index_value [, ... n]))가 지정된 경우에만 뷰가 확장되지 않습니다.

다른 팁

실행 계획의 쿼리 코드에 @ 사인이 표시됩니다. 문자열 변수가 관련되어 있습니다.

SQL Server는 문자열 변수 유형이 인덱스의 문자열 열 유형과 일치하지 않으면 불쾌한 동작을 갖습니다. SQL Server는 ... 전체 열을 변환합니다 이 유형으로 빠른 조회를 수행 한 다음 변환 된 색인을 버리면 다음 쿼리를 다시 수행 할 수 있습니다.


Simon은 그것을 알아 냈지만 여기에 더 유용한 세부 사항이 있습니다. http://msdn.microsoft.com/en-us/library/ms187373.aspx

쿼리에 인덱스 뷰 및베이스 테이블 모두에 존재하는 열에 대한 참조가 포함 된 경우 쿼리 Optimizer는 인덱스 뷰를 사용하여 쿼리를 실행하는 최상의 메소드를 제공한다고 판단하면 쿼리 옵티마이저는보기에서 인덱스를 사용합니다. 이 기능이 호출됩니다 인덱스 뷰 매칭, SQL Server Enterprise 및 Developer Edition에서만 지원됩니다.

그러나 Optimizer가 일치하는 인덱스 뷰를 고려하거나 NoExpand 힌트로 참조되는 인덱스 뷰를 사용하려면 다음 옵션을 다음으로 설정해야합니다.

그래서 여기서 일어나는 일은 그 것입니다 인덱스 뷰 매칭 작동하지 않습니다. SQL Server의 Enterprise 또는 Developer Edition을 사용하고 있는지 확인하십시오 (가능성이 높습니다). 그런 다음 기사에 따라 세트 옵션을 확인하십시오.

최근에 수억 개의 통화 세부 사항 레코드가 포함 된 대형 데이터베이스를 구축했으며 쿼리와 뷰에서 사용했던 기능이 지속되는 열로 바뀌 었습니다. 계산 된 열에서 색인 할 수 있기 때문에 이것은 훨씬 더 잘 작동했습니다.

SQL Enterprise를 사용하지 않았으므로 인덱스 뷰를 사용할 기회를 얻지 못했습니다. 인덱스 뷰는 UDF의 결정 론적 결과를 색인화 할 수 있어야합니까?

Where 절에서 비교를하기 전에 모든 행에 대해 해당 기능을 호출해야한다고 생각합니다. 나는 주제를 노출시키고, 쿼리 확인을 직접 확인하고, 시간이 어떻게 작동하는지 확인했습니다. 나는 일반적으로 함수를 사용하여 값을 수정 한 다음 Where 절에서 사용 할 때마다 많은 속도가 느려졌습니다.

인덱스 뷰를 사용하여 어떤 이점을 찾고 있습니까? 테이블 자체를 올바르게 색인 할 수 없습니까? 정당화가 좋지 않으면 복잡성을 추가하고 최적화에 유연성이 적은 데이터베이스 개체를 다루도록 요청합니다.

표준 색인과 동일한 쿼리 로직을 평가 했습니까?

UDF 논리의 혼합은 더 많은 것들을 더 많이합니다.

UDF의 반환 값을 유지하는 것만 원하시면 인덱스 된 뷰 대신 지속 된 계산 열을 고려하십시오.

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top