Önce kimlik: Bu en seçici (yani en benzersiz) alandır. Ancak bir otomatik artış alanı (veya hala GUID'ler kullanılıyorsa rasgele) olarak, her müşterinin verileri her tabloya yayılır. Bu, bir müşterinin 100 satıra ihtiyaç duyduğu zamanlar olduğu anlamına gelir ve bu, diskten Tampon Havuzuna (10 veri sayfasından daha fazla yer kaplar) okunan (hızlı değil) neredeyse 100 veri sayfası gerektirir. Ayrıca, birden çok müşterinin aynı veri sayfasını güncellemesi gerekeceğinden daha sık olacağı için veri sayfalarındaki çekişmeyi artırır.
Ancak, farklı kimlik değerlerindeki istatistikler oldukça tutarlı olduğundan, genellikle çok sayıda parametre koklama / kötü önbelleğe alınmış plan sorunuyla karşılaşmazsınız. En uygun planları alamayabilirsiniz, ancak korkunç planları alma olasılığınız daha düşük olacaktır. Bu yöntem, daha az sık karşılaşılan sorunlardan yararlanmak için tüm müşterilerdeki performansı (biraz) feda eder.
Önce Kiracı Kimliği:Bu hiç de seçici değil. Yalnızca 100 Kiracı Kimliğiniz varsa, 1 milyon satır arasında çok az değişiklik olabilir. SQL Server Kiracı A için bir sorgu 500.000 satır geri alacak ama bu Kiracı B için aynı sorgu sadece 50 satır olduğunu bilecektir, ancak bu sorguların istatistikleri daha doğrudur. Ana acı noktası burasıdır. Bu yöntem, Saklı Yordamın ilk çalıştırmasının Kiracı A için olduğu durumlarda parametre koklama sorunlarına sahip olma olasılığını büyük ölçüde artırır ve Sorgu Optimize Edici'nin bu istatistikleri görebilmesi ve 500 bin satır almanın verimli olması gerektiğini bilerek uygun şekilde hareket eder. Ancak, Kiracı B, sadece 50 sıra ile çalıştığında, bu icra planı artık uygun değildir ve aslında oldukça uygunsuzdur. VE, veriler öncü alan sırasına göre eklenmediğinden,
Bununla birlikte, ilk Kiracı Kimliği'nin Saklı Yordam çalıştırması için, veriler (en azından dizin bakımını yaptıktan sonra) fiziksel ve mantıksal olarak organize edilecek, böylece veriyi karşılamak için çok daha az veri sayfası gerekli olacaktır. sorguları. Bu, daha az fiziksel G / Ç, daha az mantıksal okuma, aynı veri sayfaları için Kiracılar arasında daha az çekişme, Arabellek Havuzunda daha az boşa harcanan alan (dolayısıyla Sayfa Yaşam Beklentisi) vb. Anlamına gelir.
Bu gelişmiş performansı elde etmenin iki ana maliyeti vardır. Birincisi o kadar zor değil: Artan parçalanmaya karşı koymak için düzenli indeks bakımı yapmanız gerekir . İkincisi biraz daha az eğlencelidir.
Artan parametre koklama sorunlarına karşı koymak için, yürütme planlarını Kiracılar arasında ayırmanız gerekir. Basit yaklaşım, WITH RECOMPILE
procs veya OPTION (RECOMPILE)
sorgu ipucunda kullanmaktır, ancak bu, TenantID
önce koyarak elde edilen tüm kazançları silebilecek performansta bir hit . En iyi çalıştığını bulduğum yöntem, parametreli Dinamik SQL'i kullanmaktır sp_executesql
. Dinamik SQL'e ihtiyaç duyulmasının nedeni, TenantID'yi sorgu metnine birleştirmeye izin vermektir, normalde parametreler olacağı diğer tüm tahminler hala parametrelerdir. Örneğin, belirli bir Sipariş arıyorsanız, şöyle bir şey yaparsınız:
DECLARE @GetOrderSQL NVARCHAR(MAX);
SET @GetOrderSQL = N'
SELECT ord.field1, ord.field2, etc.
FROM dbo.Orders ord
WHERE ord.TenantID = ' + CONVERT(NVARCHAR(10), @TenantID) + N'
AND ord.OrderID = @OrderID_dyn;
';
EXEC sp_executesql
@GetOrderSQL,
N'@OrderID_dyn INT',
@OrderID_dyn = @OrderID;
Bunun etkisi, yalnızca söz konusu Kiracı Kimliği için söz konusu Kiracı'nın veri hacmiyle eşleşecek yeniden kullanılabilir bir sorgu planı oluşturmaktır. Aynı Kiracı A, saklı yordamı bir başkası için yeniden yürütürse, @OrderID
önbelleğe alınan sorgu planını yeniden kullanır. Aynı Saklı Yordamı çalıştıran farklı bir Kiracı, yalnızca Kiracı Kimliği değerinde farklı bir sorgu metni oluşturur, ancak sorgu metnindeki herhangi bir fark farklı bir plan oluşturmak için yeterlidir. Ve Kiracı B için oluşturulan plan sadece Kiracı B için veri hacmiyle eşleşmeyecek, aynı zamanda Kiracı B için farklı değerleri için tekrar kullanılabilecektir @OrderID
(bu yüklem hala parametrelendirildiği için).
Bu yaklaşımın dezavantajları şunlardır:
- Sadece basit bir sorgu yazmaktan biraz daha fazla iştir (ancak tüm sorguların Dinamik SQL olması gerekmez, sadece parametre koklama problemine sahip olanlar).
- Bir sistemde kaç Kiracı bulunduğuna bağlı olarak, her sorgu artık onu çağıran her Kiracı Kimliği için 1 plan gerektirdiğinden, plan önbelleğinin boyutunu artırır. Bu bir sorun olmayabilir, ancak en azından farkında olunması gereken bir şeydir.
Dinamik SQL, sahiplik zincirini kırar; bu EXECUTE
, Kayıtlı Yordamda izin alınarak tablolara okuma / yazma erişiminin kabul edilemeyeceği anlamına gelir . Kolay ancak daha az güvenli düzeltme, Kullanıcıya tablolara doğrudan erişim sağlamaktır. Bu kesinlikle ideal değil, ama bu genellikle hızlı ve kolay bir şekilde takas. Daha güvenli yaklaşım, Sertifika tabanlı güvenliği kullanmaktır. Sertifika oluşturmak, Anlam, ardından Belgesi, hibe o bir kullanıcı oluşturup bu kullanıcı istenen izinleri (Sertifika tabanlı kullanıcı veya Giriş kendi başına SQL Server bağlanamıyor), ve daha sonra bu Dinamik SQL kullanmak Saklı yordamları imzalamak SIGNATURE EKLE aynı Sertifika .
Modül imzalama ve Sertifikalar hakkında daha fazla bilgi için lütfen bkz: ModuleSigning.Info