Bildirilen birleştirme sütun sırasını değiştirmek neden bir sıralama getiriyor?


40

Aynı şekilde adlandırılmış, yazılmış ve dizine eklenmiş anahtar sütunlara sahip iki tablom var. Bunlardan biri benzersiz kümelenmiş bir dizine, diğeri ise benzersiz değil .

Test kurulum

Bazı gerçekçi istatistikler içeren kurulum betiği:

DROP TABLE IF EXISTS #left;
DROP TABLE IF EXISTS #right;

CREATE TABLE #left (
    a       char(4) NOT NULL,
    b       char(2) NOT NULL,
    c       varchar(13) NOT NULL,
    d       bit NOT NULL,
    e       char(4) NOT NULL,
    f       char(25) NULL,
    g       char(25) NOT NULL,
    h       char(25) NULL
    --- and a few other columns
);

CREATE UNIQUE CLUSTERED INDEX IX ON #left (a, b, c, d, e, f, g, h)

UPDATE STATISTICS #left WITH ROWCOUNT=63800000, PAGECOUNT=186000;

CREATE TABLE #right (
    a       char(4) NOT NULL,
    b       char(2) NOT NULL,
    c       varchar(13) NOT NULL,
    d       bit NOT NULL,
    e       char(4) NOT NULL,
    f       char(25) NULL,
    g       char(25) NOT NULL,
    h       char(25) NULL
    --- and a few other columns
);

CREATE CLUSTERED INDEX IX ON #right (a, b, c, d, e, f, g, h)

UPDATE STATISTICS #right WITH ROWCOUNT=55700000, PAGECOUNT=128000;

Repro

Kümelenme anahtarlarındaki bu iki tabloya katıldığımda, bir-çok MERGE katılımını beklerim, şöyle:

SELECT *
FROM #left AS l
LEFT JOIN #right AS r ON
    l.a=r.a AND
    l.b=r.b AND
    l.c=r.c AND
    l.d=r.d AND
    l.e=r.e AND
    l.f=r.f AND
    l.g=r.g AND
    l.h=r.h
WHERE l.a='2018';

İstediğim sorgu planı bu:

İstediğim bu.

(Uyarıları dikkate almayın, sahte istatistiklerle ilgili olmalıdırlar.)

Ancak, birleşimdeki sütunların sırasını değiştirirsem, bunun gibi:

SELECT *
FROM #left AS l
LEFT JOIN #right AS r ON
    l.c=r.c AND     -- used to be third
    l.a=r.a AND     -- used to be first
    l.b=r.b AND     -- used to be second
    l.d=r.d AND
    l.e=r.e AND
    l.f=r.f AND
    l.g=r.g AND
    l.h=r.h
WHERE l.a='2018';

... bu olur:

Birleşimde bildirilen sütun sırasını değiştirdikten sonra sorgu planı.

Sort işleci, akışları birleştirme işleminin bildirilmiş sırasına göre, yani c, a, b, d, e, f, g, hsorgu planıma engelleme işlemi ekleyen gibi görünüyor .

Baktığım şeyler

  • Sütunları NOT NULLaynı sonuçlarla değiştirmeyi denedim .
  • Orijinal tablo birlikte oluşturuldu ANSI_PADDING OFF, ancak birlikte oluşturulması ANSI_PADDING ONbu planı etkilemez.
  • Değişim INNER JOINyerine bunun yerine denedim LEFT JOIN.
  • Bunu bir 2014 SP2 Enterprise'da keşfettim, 2017 Geliştirici (şu anki CU) üzerinde bir repro oluşturdum.
  • WHERE yan tümcesini ana dizin sütunundan kaldırmak iyi bir plan oluşturur, ancak sonuçları etkileyebilir .. :)

Sonunda soruya geçiyoruz

  • Bu kasıtlı mı?
  • Sorgu değiştirmeden sıralama ortadan kaldırabilir miyim (ki satıcı kodu, bu yüzden gerçekten tercih ediyorum ...). Tablo ve indeksleri değiştirebilirim.

Yanıtlar:


28

Bu kasıtlı mı?

Tasarım gereği, evet. Bu iddia için en iyi kamu kaynağı, ne yazık ki, Microsoft Connect geribildirim sitesini emekli ederek, SQL Server ekibindeki geliştiricilerin birçok yararlı yorumunu ortadan kaldırırken kaybedildi.

Neyse, şimdiki iyileştirici tasarım değil aktif aramaya gereksiz türlü önlemek için se başına . Bu en sık pencereleme işlevleriyle ve benzerleriyle karşılaşılır, ancak sıralamaya ve özellikle de operatörler arasındaki korunmuş sıralamaya duyarlı diğer operatörlerle de görülebilir.

Bununla birlikte, optimize edici (çoğu durumda) gereksiz sıralamadan kaçınmakta oldukça iyidir, ancak bu sonuç normalde agresif olarak farklı sıralama kombinasyonları denemekten başka nedenlerle ortaya çıkar. Bu anlamda, genel plan kalitesini kabul edilebilir bir maliyetle arttırdığı gösterilen ortogonal optimize edici özellikler arasındaki karmaşık etkileşimlerden dolayı, 'arama alanı' meselesi değildir.

Örneğin, sıralama, ORDER BYmevcut bir dizine bir sipariş gereksinimi (örneğin, üst seviye ) eşleştirilerek basitçe önlenebilir . Öncelikle sizin durumunuzda eklemek anlamına gelebilir ORDER BY l.a, l.b, l.c, l.d, l.e, l.f, l.g, l.h;ama bu aşırı basitleştirmedir (ve sorguyu değiştirmek istemediğiniz için kabul edilemez).

Daha genel olarak, her not grubu, giriş sırasını içerebilecek gerekli veya istenen özelliklerle ilişkilendirilebilir. İçin makul bir neden yokken zorlamak , belirli bir düzen (örneğin bir tatmin etmek ORDER BYya da bir sipariş duyarlı fiziksel operatöründen doğru sonuçları sağlamak için), katılan 'şans' unsuru vardır. Bunun içinde (modunu birliğe veya katılmak) katılmak birleştirme ilgili olduğundan bunu özellikleri hakkında daha fazla yazmış Birleştirme Üyelik birleştirme ile sıralar kaçınmak . Bunların çoğu, ürünün desteklenen yüzey alanının ötesine geçiyor, bu yüzden onu bilgilendirme amaçlı ve değişime tabi tutuyor.

Özel durumunuzda, evet, jadarnel27'nin çeşitlerden kaçınmayı önerdiği gibi indekslemeyi ayarlayabilirsiniz ; gerçekte, burada bir birliği katılmak için çok az neden var. OPTION(HASH JOIN, LOOP JOIN)Verileri bildiğinize bağlı olarak sorguyu değiştirmeden Plan Kılavuzunu kullanarak hash veya loop fiziksel birleşimini ve en iyi, en kötü ve ortalama durum performansı arasındaki dengeyi önerebilirsiniz .

Son olarak, bir merak olarak, karmaşık bir kalıntı ile, ORDER BY l.bpotansiyel olarak daha az verimli çoktan çoğa birleştirme birleşimi pahasına, basit bir yöntemle çeşitlerden kaçınılabileceğini unutmayın b. Bunu daha önce bahsettiğim en iyileştirici özellikler ve en üst düzey gereksinimlerin nasıl yayılabileceği arasındaki etkileşimin bir örneği olarak görüyorum.


19

Sorgu değiştirmeden sıralama ortadan kaldırabilir miyim (ki satıcı kodu, bu yüzden gerçekten tercih ediyorum ...). Tablo ve indeksleri değiştirebilirim.

Dizinleri değiştirebiliyorsanız #right, birleştirme içindeki filtrelerin sırasına göre dizinin sırasını değiştirmek , sıralamayı kaldırır (benim için):

CREATE CLUSTERED INDEX IX ON #right (c, a, b, d, e, f, g, h)

Şaşırtıcı bir şekilde (bana göre, en azından), bu hiçbir sorgunun bir sıralama ile sonuçlanmamasına yol açmaz.

Bu kasıtlı mı?

Bazı tuhaf iz bayraklarından çıkan verilere bakıldığında , son Memo yapısında ilginç bir fark var:

Her sorgu için son not yapısının ekran görüntüsü

En üstte "Kök Grubu" nda görebileceğiniz gibi, her iki sorguda da bu sorguyu yürütmek için ana fiziksel işlem olarak Bir Birleştirme Birleştirme kullanma seçeneği vardır.

İyi sorgu

Sıralama olmadan birleştirme , grup 29 seçenek 1 ve grup 31 seçenek 1 (her biri ilgili dizinlerde aralık taramalarıdır) tarafından yürütülür. Birleşmeyi filtreleyen mantıksal karşılaştırma işlemlerinin serisi olan grup 27 (gösterilmiyor) tarafından filtrelenir.

Kötü sorgu

Sıralamaya sahip olan, bu iki grubun (29 ve 31) her birinin sahip olduğu (yeni) seçenek 3 tarafından yönlendirilir. Seçenek 3, daha önce bahsedilen aralık taramalarının sonuçları üzerinde fiziksel bir sıralama gerçekleştirir (bu grupların her biri için seçenek 1).

Neden?

Bazı nedenlerden dolayı, birleştirme birleşimi için doğrudan kaynak olarak 29.1 ve 31.1'i kullanma seçeneği, ikinci sorguda en iyi duruma getiriciye kullanılamaz. Aksi takdirde, diğer seçenekler arasında kök grupta yer alacağını düşünüyorum. Eğer hiç mevcut olsaydı, kesinlikle daha pahalı olan sıralama operasyonlarını seçerdi.

Sadece ikisini de söyleyebilirim:

  • bu, optimize edicinin arama algoritmasındaki bir hatadır (veya daha büyük olasılıkla bir sınırlamadır).
    • Dizinleri ve birleştirmeleri yalnızca 5 anahtarla değiştirmek, ikinci sorgunun sırasını kaldırır (6, 7 ve 8 anahtarların hepsinde sıralama vardır).
    • Bu, 8 tuşlu arama alanının o kadar büyük olduğu anlamına gelir; optimize edicinin, "yeterince iyi bir plan bulundu" nedeni ile erken sona ermeden önce, sıralama dışı çözümü uygun bir seçenek olarak tanımlamak için yeterli zamanı olmadığı anlamına gelir.
    • katılım şartlarının sırasının, optimizer'ın arama işlemini bu kadar etkilediği bana biraz üzücü geliyor, ama bu gerçekten benim başımın biraz üstünde
  • sonuçlarda doğruluğu sağlamak için sıralama gerekli
    • bu bir sorgu beri zor görünüyor olabilir daha az tuş varken türlü olmadan çalıştırmak veya anahtarlar farklı bir sırada belirtilen

Umarım birisi gelip neden sıralamanın gerekli olduğunu açıklayabilir , ancak Memo binasındaki farkın bir cevap olarak gönderecek kadar ilginç olduğunu düşündüm.


1
Arama alanı hakkındaki yorumunuzun aslında buradaki olduğuna inanıyorum. Sadece indeksleri kullanmak için, optimize edicinin şartlar için yeterli olduğunu doğrulaması gerekir, 5 anahtarın sonundan geriye düşmeden önce kontrol edilmesi gereken çok fazla olasılık vardır. Sorgunun tüm sipariş kombinasyonları iyileştirici sonbahar arka vs başarılı kaç, sayılan olsaydı ben merak olurdu
Mr.Mindor

Ve evet, tutarsızlık biraz fazla parazit gibi görünmüyor, ancak muhtemelen endekslerin yeterli olduğunu doğrulamak için kullanılan algoritmaya tamamen bağlı. Tüm kombinasyonlar test edildiyse, muhtemelen sonuçlardaki deseni görebilecek ve hangi algoritmanın kullanılacağını belirleyebileceksiniz. İddiaya girerim, daha tipik kullanım durumları için en iyi performansı sağlayacak şekilde yazılmıştır. 8 anahtar çözümü zaman içinde güvenilir bir şekilde bulabilecek alternatif olabilir, ancak söylenenden daha az anahtar varsa, mevcut çözümden daha yavaştır.
Mr.Mindor
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.