Sorularınızı, sizden istediklerinden farklı bir sırayla cevaplayacağım.
4. Bu daha büyük bir sorunun belirtisi mi?
Yeni kardinalite tahmincisi SQL Server 2016 yılında soruna katkıda edilebilir. SQL Server 2012, eski CE'yi kullanır ve sorununuzu bu sürümde yaşamadınız. Yeni kardinalite tahmincisi verileriniz hakkında farklı varsayımlar yapar ve aynı SQL için farklı sorgu planları oluşturabilir. Sorgunuza ve verilerinize bağlı olarak eski CE ile bazı sorgular için daha iyi performans elde edebilirsiniz. Bu nedenle, veri modelinizin bazı bölümleri yeni CE için en uygun olmayabilir. Sorun değil, ama şimdilik yeni CE üzerinde çalışmanız gerekebilir.
Günlük istatistik güncellemelerinde bile tutarsız sorgu performansı ile ilgilenirim. Dikkat edilmesi gereken önemli bir nokta, tüm tablolarda istatistik toplamanın tüm sorgu planlarını önbellekten etkili bir şekilde sileceğidir, bu nedenle istatistiklerle ilgili bir sorununuz olabilir veya parametre koklamasıyla ilgili olabilir. Veri modeliniz, veri değişim oranı, istatistik güncelleme politikaları, kodunuzu nasıl çağırdığınız vb. Hakkında çok fazla bilgi vermeden bir belirleme yapmak zordur. SQL Server 2016, parametre koklaması için yardımcı olabilecek bazı veritabanı seviyesi ayarları sunar , ancak bu yalnızca tek sorunlu sorgu yerine uygulamanızı etkileyebilir.
Bu davranışa yol açabilecek örnek bir senaryo oluşturacağım. Dedin:
Bazı kullanıcıların 1 izin kaydı olabilir, bazıları 20k'ye kadar.
Tüm sorgu planlarını silen tüm tablolarda istatistikleri topladığınızı varsayalım. Yukarıda belirtilen faktörlere bağlı olarak, günün ilk sorgusu sadece 1 izin kaydı olan bir kullanıcıya karşı ise, SQL Server 1 kaydı olan kullanıcılar için iyi çalışan ancak 20k kaydı olan kullanıcılarla çok iyi çalışan bir planı önbelleğe alabilir. Günün ilk sorgusu 20 bin kayıtlı bir kullanıcıya karşı ise, 20 bin kayıt için iyi bir plan alabilirsiniz. Kod 1 kaydı olan bir kullanıcıya karşı çalıştırıldığında, en uygun sorgu olmayabilir ancak ms olarak bitebilir. Gerçekten parametre koklama gibi geliyor. Sorunu neden her zaman görmediğinizi veya neden bazen görünmesinin saatler sürdüğünü açıklar.
1. Yeni endeks sorunu düzelterek bir daha kötü planı bir daha seçmeyecek mi?
Eklediğiniz dizinlerden birinin sorunu önleyeceğini düşünüyorum, çünkü gerekli verilere dizin aracılığıyla erişmek, özellikle tarama erken sonlandırılamadığında tabloya göre kümelenmiş bir dizin taraması yapmaktan daha ucuz olacaktır. Sorgu planının kötü kısmını yakınlaştıralım:
SQL Server, birleşimden [Permission]
ve öğelerinden yalnızca bir satırın döndürüleceğini tahmin eder [Project]
. Dış girişteki her satır için kümelenmiş bir dizin taraması yapar [Appointment]
. Tüm satırlar bu tablodan taranacaktır, ancak yalnızca filtrelemeyle eşleşen satırlar [Start]
birleştirme operatörüne döndürülecektir. Birleştirme operatörü içinde sonuçlar daha da azaltılır.
Birleştirmenin dış girişine gerçekten yalnızca bir satır gönderilmişse, yukarıda açıklanan sorgu planı iyi olabilir. Ancak, birleşimden gelen kardinalite tahmini yanlışsa ve diyelim ki 1000 satır alırsak, SQL Server 1000 kümelenmiş dizin taraması yapar [Appointment]
. Sorgu planının performansı tahmin sorunlarına çok duyarlıdır.
Bir daha asla bu sorgu planını almanın en doğrudan yolu [Appointment]
tabloya karşı bir kaplama dizini oluşturmak olacaktır . Bir dizin gibi bir şey [ProjectId]
ve [Start]
bunu yapmak gerekir. Bu [idx_appointment_start]
, sorunu çözmek için oluşturduğunuz dizindir. Sorgu planını alarak gelen SQL sunucusu vazgeçirmek için bir başka yolu üzerinden birleştirmek gelen önem düzeyi tahmini düzeltmek için olduğunu [Permission]
ve [Project]
. Kodun değiştirilmesi, istatistiklerin güncellenmesi, eski CE'nin kullanılması, çok sütunlu istatistiklerin oluşturulması, SQL Server'a RECOMPILE
ipucu gibi yerel değişkenler hakkında daha fazla bilgi verilmesi veya bu satırların geçici bir tablo haline getirilmesi için tipik yollar . MS düzeyinde yanıt süresine ihtiyaç duyduğunuzda veya bir ORM aracılığıyla kod yazmanız gerektiğinde bu tekniklerin çoğu iyi bir yaklaşım değildir.
Oluşturduğunuz dizin [AppointmentAttendee]
, sorunu ele almanın doğrudan bir yolu değildir. Ancak, dizinde çok sütunlu istatistikler alırsınız ve bu istatistikler bozuk sorgu planını engelleyebilir. Dizin, kötü sorgu planını da engelleyebilecek verilere erişmek için daha etkili bir yol sağlayabilir, ancak bunun yalnızca dizinle tekrar olmayacağının herhangi bir garantisi olduğunu düşünmüyorum [AppointmentAttendee]
.
3. Bunun başka bir sorguya / plana gerçekleşmediğinden nasıl emin olabilirim?
Bu soruyu neden sorduğunuzu anlıyorum ama bu çok geniş bir soru. Tek tavsiyem, sorgu planı kararsızlığının temel nedenini daha iyi anlamaya çalışmak, iş yükünüz için doğru dizinlere sahip olduğunuzu doğrulamak ve iş yükünüzü dikkatle test etmek ve izlemek. Microsoft, SQL Server 2016'daki yeni CE'nin neden olduğu sorgu planı gerilemeleriyle nasıl başa çıkılacağı konusunda bazı genel önerilere sahiptir :
Sorgu işlemcisini kodun en son sürümüne yükseltmek için önerilen iş akışı:
Veritabanı uyumluluk düzeyini değiştirmeden bir veritabanını SQL Server 2016'ya yükseltin (önceki düzeyde tutun)
Veritabanında sorgu deposunu etkinleştirin. Sorgu deposunu etkinleştirme ve kullanma hakkında daha fazla bilgi için, bkz. Sorgu Deposunu Kullanarak Performansı İzleme.
İş yükünün temsili verilerini toplamak için yeterli süre bekleyin.
Veritabanının uyumluluk düzeyini 130 olarak değiştirin
SQL Server Management Studio'yu kullanarak, uyumluluk düzeyi değişikliğinden sonra belirli sorgularda performans gerilemeleri olup olmadığını değerlendirin
Regresyonların olduğu durumlarda, sorgu deposunda önceki planı zorlayın.
Zorlamayan sorgu planları varsa veya performans hala yetersizse, uyumluluk düzeyini önceki ayara getirmeyi ve ardından Microsoft Müşteri Desteği'ni kullanmayı düşünün.
SQL Server 2012'ye geçmeniz ve baştan başlamanız gerektiğini söylemiyorum, ancak açıklanan genel teknik sizin için yararlı olabilir.
2. Şimdi iyi çalışan planı "zorlamalı mıyım?"
Tamamen size kalmış. Tüm olası giriş parametreleri için iyi çalışan bir sorgu planınız olduğuna inanıyorsanız, sorgu deposunun işlevselliği ile rahatınız ve bir sorgu planını zorlamakla birlikte gelen gönül rahatlığını istiyorsanız, bunun için gidin. Gerileme olan sorgu planlarını zorlamak, Microsoft'un SQL Server 2016'ya yükseltme ilkesini önermesinin bir parçasıdır.