Tempdb olayları (yavaş sorgulara neden) dökülme olduğunda genellikle satır tahminleri belirli bir katılmak için yol olduğunu fark ettim. Dökülme olaylarının birleştirme ve karma birleştirmelerle gerçekleştiğini gördüm ve genellikle çalışma süresini 3x ila 10x artırdılar. Bu soru, dökülme olayları olasılığını azaltacağı varsayımı altında satır tahminlerinin nasıl iyileştirileceği ile ilgilidir.
Gerçek Sıra Sayısı 40k.
Bu sorgu için, plan hatalı satır tahmini gösterir (11.3 satır):
select Value
from Oav.ValueArray
where ObjectId = (select convert(bigint, Value) NodeId
from Oav.ValueArray
where PropertyId = 3331
and ObjectId = 3540233
and Sequence = 2)
and PropertyId = 2840
option (recompile);
Bu sorgu için, plan iyi satır tahmini gösterir (56 bin satır):
declare @a bigint = (select convert(bigint, Value) NodeId
from Oav.ValueArray
where PropertyId = 3331
and ObjectId = 3540233
and Sequence = 2);
select Value
from Oav.ValueArray
where ObjectId = @a
and PropertyId = 2840
option (recompile);
İlk vaka için satır tahminlerini iyileştirmek için istatistikler veya ipuçları eklenebilir mi? Belirli filtre değerleri (property = 2840) ile istatistik eklemeyi denedim ama ya kombinasyon doğru alamadım ya da ObjectId derleme zamanında bilinmediği ve belki de tüm ObjectIds üzerinde bir ortalama seçiyor çünkü yok sayılıyor.
Önce prob sorgusunu yapacak ve daha sonra bunu satır tahminlerini belirlemek için kullanacak herhangi bir mod var mı veya körü körüne uçmalı mı?
Bu özellik, birkaç nesne üzerinde birçok değere (40k) ve büyük çoğunlukta sıfır değerine sahiptir. Belirli bir birleştirme için beklenen maksimum satır sayısının belirtilebileceği bir ipucundan memnun olurum. Bazı parametreler birleştirme işleminin parçası olarak dinamik olarak belirlenebilir veya bir görünüme daha iyi yerleştirilebilir (değişkenler için destek yoktur), çünkü bu genellikle akıldan çıkmayan bir sorundur.
Dökülmelerin tempdb'ye düşme olasılığını en aza indirmek için ayarlanabilecek herhangi bir parametre var mı (örneğin sorgu başına minimum bellek)? Sağlam planın tahmin üzerinde bir etkisi yoktu.
2013.11.06'yı düzenleyin : Yorumlara ve ek bilgilere yanıt:
İşte sorgu planı görüntüleri. Uyarılar, convert () ile kardinalite / seek yüklemi ile ilgilidir:
@Aaron Bertrand'ın yorumuna göre, convert () yöntemini bir test olarak değiştirmeyi denedim:
create table Oav.SeekObject (
LookupId bigint not null primary key,
ObjectId bigint not null
);
insert into Oav.SeekObject (
LookupId, ObjectId
) VALUES (
1, 3540233
)
select Value
from Oav.ValueArray
where ObjectId = (select ObjectId
from Oav.SeekObject
where LookupId = 1)
and PropertyId = 2840
option (recompile);
Garip ama başarılı bir ilgi noktası olarak, aramaya kısa devre yapmasına izin verdi:
select Value
from Oav.ValueArray
where ObjectId = (select ObjectId
from Oav.ValueArray
where PropertyId = 2840
and ObjectId = 3540233
and Sequence = 2)
and PropertyId = 2840
option (recompile);
Her ikisi de uygun bir anahtar araması listeler, ancak yalnızca ilk olanlar ObjectId öğesinin "Çıktısını" listeler. Sanırım ikincisi gerçekten kısa devre mi?
Birisi, satır tahminlerine yardımcı olmak için tek sıra probların yapılıp yapılmadığını doğrulayabilir mi? Tek satırlı bir PK araması histogramdaki aramanın doğruluğunu büyük ölçüde artırabildiğinde (özellikle dökülme potansiyeli veya geçmişi varsa) optimizasyonu yalnızca histogram tahminleriyle sınırlamak yanlış görünüyor. Gerçek bir sorguda bu alt birleşimlerden 10 tanesi varsa, ideal olarak paralel olarak gerçekleşirler.
Yan not, sql_variant temel türünü (SQL_VARIANT_PROPERTY = BaseType) alanın kendisinde sakladığından, "doğrudan" dönüştürülebilir olduğu sürece (örn. int veya belki de bigint'e int). Bu derleme zamanında bilinmediğinden, ancak kullanıcı tarafından bilinebildiğinden, belki sql_variants için bir "AssumeType (type, ...)" işlevi daha şeffaf bir şekilde işlem görmelerine izin verir.
declare @a bigint =
yaptığınız gibi bölmek benim için doğal bir çözüm gibi görünüyor, bu neden kabul edilemez?
CONVERT()
sütunlarda kullanmaya ve daha sonra onlara katılmaya zorlayan (çok basit) bir EAV tasarımı . Bu kesinlikle verimli değildir çoğu durumda. Bu özel birinde, dönüştürülecek tek bir değerdir, bu muhtemelen bir sorun değildir, ancak tabloda hangi dizinler var? EAV tasarımları genellikle sadece uygun indeksleme ile iyi performans gösterir (bu genellikle dar tablolarda çok sayıda indeks anlamına gelir).