Birleştirme operatörü neden girdilerinden daha az satır tahmin ediyor?


20

Aşağıdaki sorgu planı snippet'inde, Concatenationişleç için satır tahmininin ~4.3 billion rowsveya iki girişi için satır tahminlerinin toplamının olması gerektiği açıktır .

Bununla birlikte, yüzlerce GB veriyi tempdb'ye döken ~238 million rowsbir alt optimal Sort/ Stream Aggregatestratejiye yol açan bir tahmin üretilir . Bu durumda mantıksal olarak tutarlı bir tahmin, bir a Hash Aggregate, döküntüyü kaldıracak ve sorgu performansını önemli ölçüde artıracaktır .

Bu SQL Server 2014'te bir hata mı? Girdilerden daha düşük bir tahminin makul olabileceği herhangi bir geçerli koşul var mı? Hangi geçici çözümler kullanılabilir?

resim açıklamasını buraya girin

İşte tam sorgu planı (anonimleştirilmiş). Ben QUERYTRACEON 2363veya benzer izleme bayraklarından çıktılar sağlamak için bu sunucuya sysadmin erişimim yok , ancak yararlı olurlarsa bu çıktıları bir yönetici alabilirsiniz.

Veritabanı uyumluluk düzeyi 120'dir ve bu nedenle yeni SQL Server 2014 Kardinalite Tahmincisi'ni kullanmaktadır.

Veriler her yüklendiğinde istatistikler manuel olarak güncellenir. Veri hacmi göz önüne alındığında, şu anda varsayılan örnekleme oranını kullanıyoruz. Daha yüksek bir örnekleme hızının (veya FULLSCAN) bir etkisi olabilir.

Yanıtlar:


21

Campbell Fraser'ı bu Connect öğesinde alıntılamak için :

Bu "kardinalite tutarsızlıkları", birleşik durumlarda da dahil olmak üzere bir dizi durumda ortaya çıkabilir. Nihai plandaki belirli bir alt ağacın tahmini, farklı yapılandırılmış ancak mantıksal olarak eşdeğer bir alt ağaç üzerinde gerçekleşmiş olabileceği için ortaya çıkabilir. Kardinalite tahmininin istatistiksel doğası gereği, farklı fakat mantıksal olarak eşdeğer ağaçlarda tahminin aynı tahminde bulunması garanti edilmez. Dolayısıyla, genel olarak beklenen tutarlılık garantisi verilmemektedir.

Bunu biraz genişletmek için: Açıklamak istediğim yol, ilk kardinalite tahmininin (maliyete dayalı optimizasyon başlamadan önce gerçekleştirildi) daha fazla "tutarlı" kardinalite tahminleri ürettiğini söylemektir. doğrudan bir öncekine bağlı olarak tahmin.

Maliyet esaslı optimizasyonu sırasında, Plan ağacı (bir veya daha fazla operatörleri) bölümleri araştırdı edilebilir ve her biri alternatifleri ile değiştirilmiştir olabilir yeni bir önem düzeyi tahmini gerektirir. Hangi tahminin genellikle diğerinden daha iyi olacağını söylemenin genel bir yolu yoktur, bu nedenle "tutarsız" görünen nihai bir planla sonuçlanmak oldukça mümkündür. Bu sadece son düzenlemeyi oluşturmak için "plan parçalarını" birleştirmenin sonucudur.

Tüm bunlar, SQL Server 2014'te tanıtılan yeni kardinalite tahmincisinde (CE), bunu orijinal CE'deki durumdan biraz daha az yaygın hale getiren bazı ayrıntılı değişiklikler yapıldı.

En son Toplu Güncelleştirmeye yükseltme ve 4199 ile iyileştirici düzeltmelerinin açık olup olmadığını denetlemenin yanı sıra, ana seçenekleriniz istatistik / dizin değişikliklerini (eksik dizinler için uyarıları not ederek) ve güncellemeleri denemek veya sorguyu farklı şekilde ifade etmektir. Amaç, ihtiyacınız olan davranışı gösteren bir plan elde etmektir. Bu daha sonra örneğin bir plan kılavuzu ile dondurulabilir.

Anonimleştirilmiş plan detayı değerlendirmeyi zorlaştırır, ancak aynı zamanda 'optimize edilmiş' (Opt_Bitmap) veya optimizasyon sonrası (Bitmap) çeşitliliği olup olmadığını görmek için bitmap'lere de dikkatle bakarım. Filtrelerden de şüpheliyim.

Satır sayısı doğru gibi bir şeyse, bu sütun deposundan yararlanabilecek bir sorgu gibi görünüyor. Her zamanki avantajlardan başka, toplu iş operatörleri için dinamik bellek yardımından faydalanabilirsiniz ( izleme bayrağı 9389 gerekebilir).


7

SQL Server 2012 (11.0.6020) üzerinde oldukça basit bir test yatağı oluşturmak, bir plan ile birleştirilen iki karma eşleştirilmiş sorgu ile bir plan oluşturmamı sağlar UNION ALL. Test yatağımda gördüğünüz yanlış tahmin görüntülenmiyor. Belki de bu olduğunu bir SQL Server 2014 CE sorunu.

Ben aslında 280 satır döndüren bir sorgu için 133.785 satır bir tahmin olsun, ancak biz daha aşağıda göreceğiz gibi bekleniyor:

IF OBJECT_ID('dbo.Union1') IS NOT NULL
DROP TABLE dbo.Union1;
CREATE TABLE dbo.Union1
(
    Union1_ID INT NOT NULL
        CONSTRAINT PK_Union1
        PRIMARY KEY CLUSTERED
        IDENTITY(1,1)
    , Union1_Text VARCHAR(255) NOT NULL
    , Union1_ObjectID INT NOT NULL
);

IF OBJECT_ID('dbo.Union2') IS NOT NULL
DROP TABLE dbo.Union2;
CREATE TABLE dbo.Union2
(
    Union2_ID INT NOT NULL
        CONSTRAINT PK_Union2
        PRIMARY KEY CLUSTERED
        IDENTITY(2,2)
    , Union2_Text VARCHAR(255) NOT NULL
    , Union2_ObjectID INT NOT NULL
);

INSERT INTO dbo.Union1 (Union1_Text, Union1_ObjectID)
SELECT o.name, o.object_id
FROM sys.objects o;

INSERT INTO dbo.Union2 (Union2_Text, Union2_ObjectID)
SELECT o.name, o.object_id
FROM sys.objects o;
GO

SELECT *
FROM dbo.Union1 u1
    INNER HASH JOIN sys.objects o ON u1.Union1_ObjectID = o.object_id
UNION ALL
SELECT *
FROM dbo.Union2 u2
    INNER HASH JOIN sys.objects o ON u2.Union2_ObjectID = o.object_id;

Bence bunun sebebi BİRLİKTE ortaya çıkan iki birleşme için istatistik eksikliğidir. SQL Server, istatistik eksikliği ile karşılaşıldığında çoğu zaman sütunların seçiciliği konusunda eğitimli tahminler yapmalıdır.

Joe Sack burada ilginç bir okumaya sahip .

Bir için UNION ALL, biz ancak SQL Server beri satır kullanıyor, birliğin her bileşen tarafından döndürülen satır tam olarak toplam sayısını görürsünüz söylemek güvenli tahminleri iki bileşenleri için UNION ALL, gördüğümüz toplam ekler tahmini hem satırları birleştirme işleci için tahmin bulmak için sorgular.

Yukarıdaki UNION ALLörneğimde, her bir bölümü için tahmini satır sayısı 66.8927'dir; bu, toplandığında, birleştirme operatörü için tahmini satır sayısı için gördüğümüz 133.785'e eşittir.

Yukarıdaki birleşim sorgusunun gerçek yürütme planı şuna benzer:

resim açıklamasını buraya girin

"Tahmini" ve "gerçek" satır sayısını görebilirsiniz. Benim durumumda, iki karma eşleme işleci tarafından döndürülen "tahmini" satır sayısını eklemek, tam olarak birleştirme işleci tarafından gösterilen miktara eşittir.

Sorunuzda gösterdiğiniz Paul White'ın gönderisinde önerildiği gibi izleme 2363 vb.'den çıktı almaya çalışacağım. Alternatif olarak, soruna "sorunu giderip düzeltmediğini" görmek için 70 CE sürümüne geri dönmekOPTION (QUERYTRACEON 9481) için sorguyu kullanmayı deneyebilirsiniz .


1
Teşekkürler. Kesinlikle "nedeni, birleşmiş olan iki birleşim için istatistik eksikliği civarında" sonraki birleşimler veya birleşmeler üzerinde büyük bir etkiye sahip olduğunu gördüm (sendikadan sonra). SQL 2014 bunu deneyimlerime göre SQL 2012'den daha iyi işler. İşte geçmişte kullandığım basit bir test komut dosyası: gist.github.com/anonymous/1497112d8b25ab8fb782a04569959c68 Ancak, bir Zincirleme operatörünün birleştirme değerlerinin dağılımı hakkında aynı tür bilgilere ihtiyaç duyacağını düşünmüyorum ihtiyaç olabilir.
Geoff Patterson

Birleştirme işleminin doğru bir şekilde yapılması için istatistiğe ihtiyaç duymaması gerektiğini kabul ediyorum . Çıkarılacak satır sayısını iyi anlamak için gelen satır tahminlerini güvenilir bir şekilde ekleyebilmelidir. @PaulWhite'ın cevabında gösterdiği gibi, şaşırtıcı bir şekilde her zaman böyle değildir. Benim için buradaki paket basit görünebilir, ancak gerçekte olmayabilir. Soruyu yaptığınız gibi sorduğunuza gerçekten sevindim, keşke sadece planı anonimleştirmek zorunda kalmadınız - asıl sorguyu görmek ilginç olurdu.
Max Vernon
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.