Kalıcı bir hesaplanmış sütundaki dizin aranamıyor


15

Ben denilen bir tablo var denilen Addresskalıcı bir hesaplanmış sütun var Hashkey. Sütun deterministiktir, ancak kesin değildir. Üzerinde aranamayan benzersiz bir indeks vardır. Bu sorguyu çalıştırırsam, birincil anahtarı döndürürseniz:

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

Bu planı alıyorum:

BasicPlan

Eğer indeksi zorlarsam, bu daha kötü bir plan elde ederim:

ForceIndex

Denemek ve hem dizin hem de bir arama zorlamak, bir hata alıyorum:

Sorgu işlemcisi, bu sorguda tanımlanan ipuçları nedeniyle bir sorgu planı üretemedi. Herhangi bir ipucu belirtmeden ve kullanmadan sorguyu yeniden gönderinSET FORCEPLAN

Bu sadece kesin olmadığı için mi? Bunun devam edip etmediğinin önemli olmadığını düşündüm.

Bu dizini hesaplanmamış bir sütun haline getirmeden aranabilir kılmanın bir yolu var mı?

Herkes bu konuda bilgi bağlantıları var mı?

Gerçek tablo oluşturma gönderemiyorum, ama burada aynı sorunu olan bir test tablosu:

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 

Yanıtlar:


12

Sorun [TestGeocode].[ToString]()bir maxveri türü ( nvarchar(max)) döndüren gerçeği ile ilgili gibi görünüyor .

Ben de bu daha basit bir sürümü ile sorunla karşılaşabilir (tanımını değiştirerek c1etmek varchar(8000)veya kullanma COALESCEyerine ISNULLgiderir o)

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

Hesaplanan sütun başvuruları temel tanımla genişletilir ve daha sonra sütuna geri eşleştirilir. Bu, hesaplanan sütunların adlarına hiç başvurmadan eşleştirilmesine ve basitleştirmenin temel tanımlarda çalışmasına olanak tanır.

ISNULLilk parametrenin veri türünü döndürür (örneğimde VARCHAR(MAX)). Geri dönüş türü COALESCEde VARCHAR(MAX)burada olacak, ancak sorunu önleyecek şekilde farklı değerlendiriliyor gibi görünüyor.

Sorgunun izleme bayrağı çıktısının başarılı olduğu durumlarda aşağıdakiler bulunur

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

Başarısız olduğunda bunun yerini

ScaOp_Identifier COL: ConstExpr1003 

Başarısız olduğu durumlarda (örtük) sadece bir kez yapıldığını ve bunun bir çalışma zamanı sabiti ( daha fazla bilgi ) olarak değerlendirildiğini tahmin ediyorum . Ancak, gerçek dize değişmez değeri yerine bu çalışma zamanı sabit etiketine yapılan başvuru, hesaplanan sütun tanımıyla eşleşmesini engeller.CAST('ABC' AS VARCHAR(MAX))

Bu yeniden yazma, sorgunuzdaki sorunu önler

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

Bu tür belirtiler, veri türü @HashKey . CASTİstenen veri türünü zorlamak için hesaplanan sütun ifadesinde bir açık olması gerekebilir .

Senin repro dayanarak, bunun bir hata olduğundan şüpheleniyorum. Bağlan hata, Hesaplanmış Sütun Dizini Kullanılmıyor , Martin geçici çözümünün bir sürümü ile dosyaladım . Oy kullanmaktan çekinmeyin.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.