SQL Server tahminlerin ilişkili olduğunu nasıl biliyor?


15

Kötü kardinalite tahmini ile SQL Server 2008 R2 sorgularını (basit indeksleme, güncel istatistikler vb. Rağmen) ve dolayısıyla zayıf sorgu planlarını teşhis ederken, belki de ilgili bir KB makalesi buldum: Düzeltme: Bir sorgu çalıştırdığınızda düşük performans Server 2008 veya SQL Server 2008 R2 veya SQL Server 2012'de ilişkili VE tahminleri içeren

KB makalesinin "ilişkili" ile ne anlama geldiğini tahmin edebilirim, örneğin yüklem # 2 ve yüklem # 1 büyük ölçüde aynı satırları hedefler.

Ancak SQL Server'ın bu korelasyonları nasıl bildiğini bilmiyorum. Bir tablonun her iki tahminden de sütunlar içeren çok sütunlu bir dizine ihtiyacı var mı? SQL, bir sütundaki değerlerin diğeriyle ilişkili olup olmadığını kontrol etmek için istatistikleri kullanıyor mu? Yoksa başka bir yöntem kullanılıyor mu?

Bunu iki nedenden dolayı soruyorum:

  1. bu düzeltmeyi kullanarak hangi tablolarımın ve sorgularım geliştirilebileceğini belirlemek için
  2. # 1 etkilemek için indeksleme, istatistik, vb ne yapmalıyım bilmek

Yanıtlar:


20

Aşağıda gösterilen basit AdventureWorks sorgusu ve yürütme planını göz önünde bulundurun . Sorgu ile bağlantılı tahminler içeriyor AND. Optimize edicinin kardinalite tahmini 41.211 satırdır :

-- Estimate 41,211 rows
SELECT COUNT_BIG(*)
FROM Production.TransactionHistory AS TH
WHERE 
    TH.TransactionID BETWEEN 100000 AND 168336
    AND TH.TransactionDate BETWEEN '2007-09-01' AND '2008-03-13';

Varsayılan yürütme planı

Varsayılan istatistikleri kullanma

Yalnızca tek sütunlu istatistikler verildiğinde, optimize edici bu tahminin her bir yüklem için kardinaliteyi ayrı ayrı tahmin ederek ve elde edilen seçicilikleri çarparak üretir. Bu buluşsal yöntem, tahminlerin tamamen bağımsız olduğunu varsayar.

Sorguyu iki bölüme ayırmak, hesaplamanın daha kolay görülmesini sağlar:

-- Estimate 68,336.4 rows
SELECT COUNT_BIG(*)
FROM Production.TransactionHistory AS TH
WHERE 
    TH.TransactionID BETWEEN 100000 AND 168336;

İşlem Geçmişi tablosu toplam 113.443 satır içerir, bu nedenle 68.336.4 tahmini bu yüklem için 68336.4 / 113443 = 0.60238533 seçiciliğini temsil eder . Bu tahmin, TransactionIDsütun için histogram bilgileri ve sorguda belirtilen sabit değerler kullanılarak elde edilir .

-- Estimate 68,413 rows
SELECT COUNT_BIG(*)
FROM Production.TransactionHistory AS TH
WHERE 
    TH.TransactionDate BETWEEN '2007-09-01' AND '2008-03-13';

Bu yüklemin tahmini 68413.0 / 113443 = 0.60306056 seçiciliği vardır . Yine, yüklemin sabit değerlerinden ve hedefin histogramından hesaplanır.TransactionDate istatistik nesnesinin .

Tahminlerin tamamen bağımsız olduğunu varsayarsak, iki tahminin seçiciliğini birlikte çarparak tahmin edebiliriz. Nihai kardinalite tahmini, sonuçtaki seçiciliğin temel tablodaki 113,443 satır ile çarpılmasıyla elde edilir:

0.60238533 * 0.60306056 * 113443 = 41210.987

Yuvarlamadan sonra, bu, orijinal sorguda görülen 41.211 tahmindir (optimize edici ayrıca kayan nokta matematiğini dahili olarak kullanır).

Büyük bir tahmin değil

TransactionIDVe TransactionDatesütunlar (monoton artan tuşları ve tarih sütunları sık yapmak gibi) belirlenen AdventureWorks verilerinde yakın bir korelasyon vardır. Bu korelasyon, bağımsızlık varsayımının ihlal edildiği anlamına gelir. Sonuç olarak, yürütme sonrası sorgu planı, tahmin edilen 41.211 yerine 68.095 satır gösterir:

İcra sonrası plan

İzleme bayrağı 4137

Bu izleme bayrağını etkinleştirmek, tahminleri birleştirmek için kullanılan buluşsal yöntemleri değiştirir. Optimize edici, tam bağımsızlığı varsaymak yerine, iki tahminin seçiciliğinin, ilişkilendirilebilecek kadar yakın olduğunu düşünür:

-- Estimate 68,336.4
SELECT COUNT_BIG(*)
FROM Production.TransactionHistory AS TH
WHERE 
    TH.TransactionID BETWEEN 100000 AND 168336
    AND TH.TransactionDate BETWEEN '2007-09-01' AND '2008-03-13'
OPTION (QUERYTRACEON 4137);

Hatırlatma; TransactionIDyüklem tek başına 68,336.4 satırları tahmin ve TransactionDateyüklem tek başına 68.413 satır tahmin. Optimize edici, seçicilikleri çarpmak yerine bu iki tahminin altını seçmiştir.

Bu sadece farklı bir sezgisel taramadır, ancak ilişkili tahminlere sahip sorgular için tahminlerin iyileştirilmesine yardımcı olabilecek bir yöntemdir AND. Her yüklem, olası korelasyon için düşünülür ve birçok ANDcümle dahil edildiğinde yapılan başka düzenlemeler de vardır, ancak bu örnek, bunun temellerini göstermeye hizmet eder.

Çok sütunlu istatistikler

Bunlar korelasyonlarla ilgili sorgularda yardımcı olabilir, ancak histogram bilgileri hala sadece istatistiklerin önde gelen sütununa dayanmaktadır. Bu nedenle, aşağıdaki aday çok sütunlu istatistikler önemli bir şekilde farklılık gösterir:

CREATE STATISTICS
    [stats Production.TransactionHistory TransactionID TransactionDate]
ON Production.TransactionHistory
    (TransactionID, TransactionDate);

CREATE STATISTICS
    [stats Production.TransactionHistory TransactionDate TransactionID]
ON Production.TransactionHistory
    (TransactionDate, TransactionID);

Bunlardan sadece birini alarak, sadece ekstra bilginin, 'hepsi' yoğunluğunun fazladan seviyeleri olduğunu görebiliriz. Histogram hala TransactionDatesütun hakkında ayrıntılı bilgi içerir .

DBCC SHOW_STATISTICS
    (
        'Production.TransactionHistory', 
        'stats Production.TransactionHistory TransactionDate TransactionID'
    );

Çok sütunlu istatistik

Bu çok sütunlu istatistiklerle ...

SELECT COUNT_BIG(*)
FROM Production.TransactionHistory AS TH
WHERE 
    TH.TransactionID BETWEEN 100000 AND 168336
    AND TH.TransactionDate BETWEEN '2007-09-01' AND '2008-03-13';

... yürütme planı, yalnızca tek sütunlu istatistiklerin mevcut olduğu durumla tamamen aynı olan bir tahmin gösterir :

Çok sütunlu istatistik planı

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.