Chỉ mục trên một cột được tính toán bền bỉ không thể tìm kiếm


15

Tôi có bảng, được gọi Address, có một cột được tính toán bền vững được gọi Hashkey. Cột là xác định nhưng không chính xác. Nó có một chỉ số duy nhất trên đó là không thể tìm kiếm. Nếu tôi chạy truy vấn này, trả về khóa chính:

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

Tôi có kế hoạch này:

BasicPlan

Nếu tôi buộc chỉ số, tôi nhận được kế hoạch thậm chí còn tồi tệ hơn:

Force Index

Nếu tôi cố gắng và buộc cả chỉ mục và tìm kiếm, tôi sẽ gặp lỗi:

Bộ xử lý truy vấn không thể tạo ra một kế hoạch truy vấn vì các gợi ý được xác định trong truy vấn này. Gửi lại truy vấn mà không chỉ định bất kỳ gợi ý nào và không sử dụngSET FORCEPLAN

Đây có phải chỉ vì nó không chính xác? Tôi nghĩ rằng nó không quan trọng nếu nó vẫn tồn tại?

Có cách nào để làm cho chỉ mục này có thể tìm kiếm mà không làm cho cột này không được tính toán không?

Có ai có bất kỳ liên kết đến thông tin về điều này?

Tôi không thể đăng việc tạo bảng thực tế, nhưng đây là bảng thử nghiệm có cùng một vấn đề:

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 

Câu trả lời:


12

Vấn đề dường như có liên quan đến thực tế [TestGeocode].[ToString]()trả về một maxkiểu dữ liệu ( nvarchar(max)).

Tôi cũng gặp phải vấn đề với phiên bản đơn giản này (thay đổi định nghĩa về c1đến varchar(8000)hoặc sử dụng COALESCEthay vì ISNULLgiải quyết nó)

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); 

Tham chiếu cột được tính toán được mở rộng ra định nghĩa cơ bản sau đó khớp lại với cột sau. Điều này cho phép các cột được tính toán được khớp mà không cần tham chiếu chúng theo tên và cũng cho phép đơn giản hóa để hoạt động trên các định nghĩa cơ bản.

ISNULLtrả về kiểu dữ liệu của tham số đầu tiên ( VARCHAR(MAX)trong ví dụ của tôi). Kiểu trả về COALESCEcũng sẽ VARCHAR(MAX)ở đây nhưng dường như nó được đánh giá khác theo cách tránh vấn đề.

Trong trường hợp truy vấn thành công, đầu ra cờ theo dõi bao gồm các điều sau đây

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))

Trường hợp thất bại, điều này được thay thế bởi

ScaOp_Identifier COL: ConstExpr1003 

Tôi suy đoán rằng trong các trường hợp nó thất bại (ngầm) CAST('ABC' AS VARCHAR(MAX))chỉ được thực hiện một lần và điều này được đánh giá là hằng số thời gian chạy ( thêm thông tin ). Tuy nhiên, tham chiếu đến nhãn hằng số thời gian chạy này, thay vì chính giá trị chuỗi ký tự thực tế, ngăn nó khớp với định nghĩa cột được tính toán.

Điều này viết lại tránh vấn đề trong truy vấn của bạn

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

Bạn sẽ nhận được các triệu chứng này do biểu thức không thể nói được nếu loại dữ liệu @HashKeykhông khớp với cột được lập chỉ mục. Bạn có thể cần một CASTbiểu thức rõ ràng trong biểu thức cột được tính toán để ép buộc kiểu dữ liệu mong muốn.

Dựa trên lời trách móc của bạn, tôi nghi ngờ đây là một lỗi. Tôi đã gửi một lỗi Connect, Chỉ mục cột được tính toán không được sử dụng , với một phiên bản sửa lỗi của Martin. Hãy bình chọn.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.