Yürütme Planı INDEX KULLANMADI, Tablo Taraması Kullanıyor


9

Bir dizin veya tablo taraması söz konusu olduğunda, SQL Server'ın hangisinin daha iyi olduğunu görmek için istatistikleri kullandığını biliyorum.

20 milyon sıralı bir masam var. (SnapshotKey, Measure) bir dizin var ve bu sorgu:

select Measure, SnapshotKey, MeasureBand
from t1
where Measure = 'FinanceFICOScore'
group by Measure, SnapshotKey, MeasureBand

Sorgu 500 bin satır döndürür. Böylece sorgu tablonun satırlarının yalnızca% 2.5'ini seçer.

Soru, SQL Server'ın sahip olduğum kümelenmemiş dizini kullanmaması ve bunun yerine bir tablo taraması kullanmasıdır.

İstatistikler güncellenir.

Sorgu performansının iyi olduğunu belirtmek güzel.

Tablo Tarama

Tablo Tarama

Zorla Endeks

Kuvvet Endeksi

Tablo / Dizin Yapısı

CREATE TABLE [t1](
    [SnapshotKey] [int] NOT NULL,
    [SnapshotDt] [date] NOT NULL,
    [Measure] [nvarchar](30) NOT NULL,
    [MeasureBand] [nvarchar](30) NOT NULL,
    -- and many more fields
) ON [PRIMARY]

Veri ambarı olduğu için PK yok.

CREATE NONCLUSTERED INDEX [nci_SnapshotKeyMeasure] ON [t1]
(
    [SnapshotKey] ASC,
    [Measure] ASC
)

Yanıtlar:


16

Çok sayıda satır döndürürseniz ve / veya satırlar çok genişse dizin araması en iyi seçim olmayabilir. Dizininiz kapsamazsa aramalar pahalı olabilir. Bkz. # 2 .

Senaryonuzda, sorgu optimize edici, 50.000 ayrı arama gerçekleştirmenin tek bir taramadan daha pahalı olacağını tahmin eder. Optimize edicinin tarama ve arama arasındaki seçim (sorgu için gereken, ancak kümelenmemiş dizinde bulunmayan sütunlar için RID aramalarıyla), her bir alternatifin tahmini maliyetine dayanır .

Optimize edici her zaman dikkate aldığı en düşük maliyetli alternatifi seçer. İki yürütme planının kök düğümündeki Tahmini Alt Ağaç Maliyeti özelliğine bakarsanız , tarama planının arama planından tahmini maliyetin daha düşük olduğunu görürsünüz. Sonuç olarak, iyileştirici taramayı seçti. Bu aslında sorunuzun cevabıdır.

Şimdi, optimize edici tarafından kullanılan maliyet modeli, sisteminizin performans özelliklerine uyma olasılığı düşük olan varsayımlara ve "sihirli sayılara" dayanmaktadır. Özellikle, modelde yapılan bir varsayım, sorgunun zaten bellekte olan gerekli veri veya dizin sayfalarından hiçbiriyle yürütülmeye başlamamasıdır. Bir diğeri, sıralı G / Ç'nin (bir tarama için beklenen), RID Aramaları için varsayılan rastgele G / Ç modelinden daha ucuz olmasıdır. Burada ayrıntılı olarak ele alınamayacak kadar çok başka varsayım ve uyarılar var.

Bununla birlikte, maliyet modelinin bir bütün olarak çoğu sorgu için, çoğu veritabanı şemasında, çoğu donanım yapılandırmasında, çoğu zaman, her yerde genel olarak "yeterince iyi" planlar ürettiği gösterilmiştir. Eğer düşünürseniz, bu oldukça büyük bir başarıdır.

Model sınırlamaları ve diğer faktörler bazen optimize edicinin aslında "yeterince iyi" olmayan bir plan seçtiği anlamına gelir. "Performans iyidir" diye rapor edersiniz, bu yüzden burada böyle görünmüyor.


9

Aslında, verilerinizin yaklaşık% 3'ü olan 595.947 eşleşen satırınız var. Böylece arama maliyeti hızla artıyor. Tablonuzda sayfa başına 100 satır olduğunu, tablo taramasında okunacak 200.000 sayfa olduğunu varsayalım. Bu 595.947 arama yapmaktan çok daha ucuz.

İle GROUP BYsöz konusu maddede, sana (Ölçü, SnapshotKey, MeasureBand) üzerinde bir kompozit anahtar ile daha iyi durumda olacak düşünüyorum.

"Eksik dizin" önerisine bakın. Aramaları önlemek için sütun eklemenizi söyler. Daha genel olarak, sorgunuzdaki diğer sütunlara başvurursanız, bunların INCLUDEyeni dizinin anahtarlarında veya yan tümcesinde olması gerekir. Aksi takdirde, bu değerleri elde etmek için yine de 595.947 aramaları yapılması gerekecektir.

Örneğin, sorgu için:

select Measure, SnapshotKey, MeasureBand, SUM(NumLoans), SUM(PrinBal)
from t1
where Measure = 'FinanceFICOScore'
group by Measure, SnapshotKey, MeasureBand

...ihtiyacın olur:

CREATE INDEX ixWhatever 
ON t1 (Measure, SnapshotKey, MeasureBand) 
INCLUDE (NumLoans,PrinBal);

6
  1. WHERE koşulunuzdaki alan dizinin önde gelen alanı değil.

  2. Sen var measureDEPARTMENTNAME böylece ile değişmezi önüne olarak tanımlanır N: where Measure = N'FinanceFICOScore'.

Tarihinde bir Kümelenmiş Dizin oluşturmayı düşünün SnapshotKey. Benzersiz ise, bir PK (ve Kümelenmiş) olabilir. Benzersiz değilse, o zaman bir PK olamaz, ancak yine de benzersiz olmayan bir Kümelenmiş Dizin olabilir. Sonra kümelenmemiş dizininiz yalnızca measuresütunda olur.

Ve ilk alan düşünüldüğünde GROUP BYde measureayrıca sahip yararlanacak olduğunu, measurelider alan olabilir.

Aslında, bu işlem için, Kümelenmemiş Dizini, bu maddeyle Measure, SnapshotKey, MeasureBandtam olarak aynı sırada tanımlamanız gerekebilir GROUP BY. Yalnızca MeasureBandKümelenmemiş dizin zaten temel alındığından Measureve MeasureKeyartık Kümelenmiş Dizin anahtarı olduğu için dizine zaten dahil edildiğinden gerçekten eklenen boyut açısından (hayır, Kümelenmemiş Measuredizinde çoğaltılmaz).

@Rob, cevabının silinmiş olduğu bir yorumda, bu sorunun çözülmesinin yalnızca Kümelenmemiş Dizinin bu sırayla bu üç alanla tanımlanmasını gerektirdiğini ve üzerinde Kümelenmiş (benzersiz olmayan) bir Dizin oluşturmanın gerekliSnapshotKey olmadığını belirtti . Muhtemelen doğru olsa da (daha az alanın çalışacağını umuyordum), yine de Kümelenmiş Endeks'e sahip olmanın sadece bu işlem için değil, muhtemelen diğerlerinin çoğu için yararlı olduğunu iddia ediyorum.


Bu cevapla ilgili tartışma sohbete taşındı .
Paul White 9
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.