검색 할 수없는 지속 형 계산 열의 인덱스


15

라는 Address영구 계산 열이있는 이라는 테이블 이 있습니다 Hashkey. 열은 결정적이지만 정확하지는 않습니다. 검색 할 수없는 고유 인덱스가 있습니다. 이 쿼리를 실행하면 기본 키를 반환합니다.

SELECT @ADDRESSID= ISNULL(AddressId,0)
FROM dbo.[Address]
WHERE HashKey = @HashKey

나는이 계획을 얻는다 :

기본 계획

색인을 강요하면이 더 나쁜 계획을 얻습니다.

ForceIndex

인덱스와 탐색을 모두 시도하고 강제하면 오류가 발생합니다.

이 쿼리에 정의 된 힌트로 인해 쿼리 프로세서가 쿼리 계획을 생성 할 수 없습니다. 힌트를 지정하지 않고 사용하지 않고 쿼리를 다시 제출하십시오.SET FORCEPLAN

이것이 정확하지 않기 때문입니까? 그것이 지속된다면 그것이 중요하지 않다고 생각 했습니까?

계산되지 않은 열로 만들지 않고이 인덱스를 검색 할 수있는 방법이 있습니까?

누구든지 이것에 관한 정보에 대한 링크가 있습니까?

실제 테이블 생성을 게시 할 수 없지만 다음은 동일한 문제가있는 테스트 테이블입니다.

drop TABLE [dbo].[Test]

CREATE TABLE [dbo].[Test]
  (
     [test]        [VARCHAR](100) NULL,
     [TestGeocode] [geography] NULL,
     [Hashkey] AS CAST(
                        ( hashbytes
                            ('SHA', 
                                ( RIGHT(REPLICATE(' ', (100)) + isnull([test], ''), ( 100 )) ) 
                                + RIGHT(REPLICATE(' ', (100)) + isnull([TestGeocode].[ToString](), ''), ( 100 ))
                            ) 
                        ) AS BINARY(20)                                                                                                        
                      ) PERSISTED
    CONSTRAINT [UK_Test_HashKey] UNIQUE NONCLUSTERED([Hashkey])
  )    
GO    
DECLARE @Hashkey BINARY(20)

SELECT [Hashkey]
FROM   [dbo].[Test] WITH (FORCESEEK) /*Query processor could not produce a query plan*/
WHERE  [Hashkey] = @Hashkey 

답변:


12

문제 [TestGeocode].[ToString]()max데이터 유형 ( nvarchar(max)) 을 반환하는 사실과 관련이있는 것 같습니다 .

또한의 정의 변경 (이 간단한 버전으로 문제가 발생 c1하는 varchar(8000)또는 사용을COALESCE 대신 ISNULL결의 그것을)

DROP TABLE dbo.Test

CREATE TABLE dbo.Test
  (
     c1        VARCHAR(
                          MAX    --Fails
                        --  8000 --Works fine
                          ) NULL,
     comp1 AS CAST(ISNULL(c1, 'ABC') AS VARCHAR(100))
    CONSTRAINT UK_Test_comp1 UNIQUE NONCLUSTERED(comp1)
  )

GO

DECLARE @comp1 VARCHAR(100)

SELECT comp1
FROM   dbo.Test WITH (FORCESEEK)
WHERE  comp1 = @comp1 
OPTION (QUERYTRACEON 3604, QUERYTRACEON 8606); 

계산 열 참조는 기본 정의로 확장 된 다음 나중에 다시 열과 일치합니다. 이를 통해 계산 된 열을 이름으로 전혀 참조하지 않고 일치시킬 수 있으며 기본 정의에서 단순화 할 수도 있습니다.

ISNULL(첫 번째 매개 변수의 데이터 유형 돌려 VARCHAR(MAX)내 예에서는). 의 반환 유형COALESCEVARCHAR(MAX)여기에 있지만 문제를 피하는 방식으로 다르게 평가되는 것 같습니다.

쿼리가 성공한 경우 추적 플래그 출력에는 다음이 포함됩니다.

ScaOp_Convert varchar(max) collate 49160,Null,Var,Trim,ML=65535

    ScaOp_Const TI(varchar collate 49160,Var,Trim,ML=3) 
                      XVAR(varchar,Owned,Value=Len,Data = (3,ABC))

실패하면 다음으로 대체됩니다.

ScaOp_Identifier COL: ConstExpr1003 

나는 그것이 실패한 경우 (암시 적) 이 한 번만 수행되고 이것이 런타임 상수로 평가 된다고 추측 한다.CAST('ABC' AS VARCHAR(MAX)) 자세한 정보 ) . 그러나 실제 문자열 리터럴 값 대신이 런타임 상수 레이블을 참조하면 계산 된 열 정의와 일치하지 않습니다.

이 다시 쓰기는 쿼리의 문제를 피합니다

CREATE TABLE [dbo].[Test]
  (
     [test]        [VARCHAR](100) NULL,
     [TestGeocode] [geography] NULL,
     [Hashkey] AS CAST(
                        ( hashbytes
                            ('SHA', 
                                ( RIGHT(SPACE(100) + isnull([test], ''), 100) ) 
                                + RIGHT(SPACE(100) + isnull(CAST(RIGHT([TestGeocode].[ToString](),100) AS VARCHAR(100)), ''),100)
                            ) 
                        ) AS BINARY(20)                                                                                                        
                      ) PERSISTED
    CONSTRAINT [UK_Test_HashKey] UNIQUE NONCLUSTERED([Hashkey])
  )

0

의 데이터 유형 @HashKey이 인덱싱 된 열의 데이터 유형과 일치하지 않는 경우, 표현할 수없는 표현식으로 인해 이러한 증상이 나타납니다 . 명시 적으로 필요할 수 있습니다CAST원하는 데이터 유형을 강제하려면 계산 열 표현식에 적이 .

당신의 재현에 따르면, 이것이 버그라고 생각합니다. Martin의 대안 버전으로 Connect 버그 Computed Column Index Not Used를 제출했습니다 . 자유롭게 투표하십시오.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.