Değişen Veritabanı Uyumluluk Düzeyinin Önbellek Üzerindeki Etkisi SQL Server dünyasında, veritabanı uyumluluk düzeyi, sorgu yürütme ve yürütme planlarını optimize etme söz konusu olduğunda bir veritabanının nasıl davranacağını belirlemede hayati bir rol oynar. SQL Server, her yeni sürümde yeni algoritmalar ve geliştirmeler benimseyerek sürekli olarak performansı ve sorgu optimizasyonunu iyileştirmeye çalışır. Sonuç olarak, en son özelliklerden ve iyileştirmelerden yararlanmak için uyumluluk düzeyini değiştirmek gerekli hale gelir. Bu blog gönderimizde, uyumluluk düzeyini değiştirmenin sorgu önbelleğini nasıl etkilediğini ve etkisinin farkında olmanın neden önemli olduğunu beraber keşfedeceğiz. Bu tartışmayı genellikle Kapsamlı Veritabanı Healt Check Kontrolü sırasında yaparız. Önbellek Yönetimi ve Sorgu Optimizasyonu: Anlama ve Uygulama Uyumluluk düzeyini değiştirmenin etkilerine dalmadan önce, SQL Server’daki sorgu önbelleğini kısaca tartışalım. Plan önbelleği olarak da bilinen sorgu önbelleği, SQL Server sorgu iyileştiricisi tarafından oluşturulan yürütme planlarını depolar. Bir sorgu yürütüldüğünde, SQL Server önce söz konusu sorgu için mevcut bir yürütme planı olup olmadığını görmek için önbelleği kontrol eder. Bulunursa, önbelleğe alınan plan kullanılır ve yeni bir plan oluşturma ek yükünden tasarruf edilir. Bu, sorgu performansını önemli ölçüde artırır ve sorgu işleme süresini azaltır. Örnek Yürütme Planları Oluşturma: Uyumluluk düzeyini değiştirmenin etkisini göstermek için, AdventureWorks2019 veritabanındaki sorgular için bazı örnek yürütme planları oluşturalım.
USE AdventureWorks2019; — Query 1 SELECT p.ProductID, p.Name AS ProductName, c.Name AS CategoryName FROM Production.Product AS p JOIN Production.ProductSubcategory AS sc ON p.ProductSubcategoryID = sc.ProductSubcategoryID JOIN Production.ProductCategory AS c ON sc.ProductCategoryID = c.ProductCategoryID; GO 5 — Query 2 SELECT SalesOrderID, SUM(LineTotal) AS TotalSalesAmount FROM Sales.SalesOrderDetail GROUP BY SalesOrderID; GO 5 — Query 3 SELECT p.ProductID, p.Name AS ProductName, AVG(sod.OrderQty) AS AvgOrderQuantity, SUM(sod.LineTotal) AS TotalSalesAmount FROM Production.Product AS p JOIN Sales.SalesOrderDetail AS sod ON p.ProductID = sod.ProductID GROUP BY p.ProductID, p.Name; GO 5
  Önbellek Durumunu Kontrol Etme: Ardından, aşağıdaki sorguları kullanarak önbellek durumunu inceleyelim:  
USE AdventureWorks2019; — Check the buffer cache usage SELECT COUNT(*) AS CachedPagesCount, COUNT(*) * 8 / 1024 AS CachedSizeMB FROM sys.dm_os_buffer_descriptors WHERE database_id = DB_ID(); GO — Check the plan cache usage SELECT objtype AS CacheObjectType, COUNT(*) AS CachedPlansCount, SUM(size_in_bytes) / 1024 AS CachedSizeKB FROM sys.dm_exec_cached_plans GROUP BY objtype; GO — Check the procedure cache usage SELECT cacheobjtype AS CacheObjectType, COUNT(*) AS CachedObjectsCount FROM sys.dm_exec_cached_plans GROUP BY cacheobjtype; GO
  İşte göreceğimiz sonuç aşağıda verilmiştir. Uyumluluk Düzeyini Değiştirmenin Etkisi: Şimdi, aşağıdaki sorguları kullanarak uyumluluk düzeyini değiştirmeye geçelim:  
— For SQL Server 2019: ALTER DATABASE [AdventureWorks2019] SET COMPATIBILITY_LEVEL = 150; GO
  Burada 150, SQL Server 2019 anlamına gelir. Uyumluluk seviyesini SQL Server 2022 olarak değiştirmek isterseniz 150 yerine 160 kullanabilirsiniz. Aynı şekilde SQL Server 2017 için de 140 kullanabilirsiniz. Uyumluluk seviyesini değiştirip sorgu önbelleğini tekrar kontrol ettiğinizde, neredeyse boş olduğunu göreceksiniz. Analiz ve Sonuç Sonuç olarak, bir SQL Server veritabanının uyumluluk düzeyi, sorgu optimizasyon davranışını ve performansını belirlemede çok önemli bir rol oynar. Uyumluluk düzeyini değiştirmek, önbelleğe alınan yürütme planlarını etkileyebilir ve dolayısıyla genel sorgu performansını etkileyebilir. Kapsamlı Veritabanı Performansı Healt Check’in bir parçası olarak, müşterilerimizin SQL Server veritabanlarının tüm potansiyelinden yararlanmalarını sağlamak için her zaman veritabanı uyumluluk düzeyini göz önünde bulundururuz.  

Size ve Veritabanlarınıza Yardımcı Olmak İçin Bekliyoruz!

İletişime geçerek hemen destek alabilirsiniz.

İletişim

WHERE Clause içindeki Tarih Matematiği

Herkesin bir Full Metal Pocket Protector’a sahip olmadığının ve hepimizin günlerimizi sunucularımızdan her CPU döngüsünü ve I/O işlemini çıkarmak için sorgu ve dizin ayarlamanın derinliklerine dalmakla geçiremeyeceğimizin farkındayız.

Peki bunun bizimle ne ilgisi var?

Bizimle ilgisi var, çünkü WHERE cümlenizi hala kötü biçilendirebiliyoruz. Hala sütunların etrafına ifadeler koyuyor ve bu çıktıyı bir değerle veya başka bir ifadeyle karşılaştırıyoruz.

First_Name + ‘ ‘ + Last_Name = ‘Fahrettin Cüreklibatur’ gibi bir şey yaptığınız veya daha da kötüsü, bir tarihi tamamen YEAR(), MONTH() ve DAY() olarak ayırdığımız ve hepsini değerlerle karşılaştırdığımız zamanları düşünün.

Daha Yaygın

Bazen insanlar DATEADD’nin var olduğunu unuturlar. Doğrudan DATEDIFF’e gidiyorlar, çünkü kulağa daha mantıklı geliyor.

Ancak bu, özellikle çok fazla veriyle uğraşıyorsanız ya da WHERE cümlesi daha karmaşık bir JOIN serisinin parçasıysa başınızı büyük belaya sokabilir. Sadece herhangi bir dizini verimli bir şekilde kullanmamakla kalmaz, aynı zamanda diğer işlemler için kardinalite tahminini gerçekten mahvedebilir. Bu tehlike neye benziyor?

1

2

3

SELECT COUNT(*)

FROM dbo.SalesOrders AS so

WHERE DATEDIFF(DAY, CONVERT(DATE, so.OrderDate), GETUTCDATE()) = 55

Her şey yolunda gözüküyor

Yine de bununla ilgili bazı sorunlar var.

Your mom.

 

Burada cardinality estimator konusunda fena iş çıkarmadık. Sihirli Matematik 10.000 satırlık tablomuz için yaklaşık olarak doğru tahminde bulundu. Ancak Gelişmiş Sorgu Planı Teknolojisindeki gelişmeler (ipucu: SQL SERVER 2008R2’DEN ÇIKIN), gerçekte ihtiyacımız olan 5003 satırı almak yerine, dizindeki bu satırların 10.000’ini okuduğumuzu görmemizi sağlıyor. Nasıl daha iyisini yapabiliriz?

İşleri biraz tersine çevireceğiz! Fonksiyonu sütundan alıp yüklemimizin üzerine koyacağız. Bunun neden iyi olduğunu bilirsiniz. Optimizer ifadeyi sorguya katlamasına ve dizin erişimine doğru itmesine olanak tanır.

1

2

3

SELECT COUNT(*)

FROM dbo.SalesOrders AS so

WHERE CONVERT(DATE, so.OrderDate) = DATEADD(DAY, -55, CONVERT(DATE, GETUTCDATE()))

Şimdi daha ucuz bir dizin araması elde ediyoruz, fazladan 4997 satır okumuyoruz ve cardinality estimator doğru. Yine, orijinalinde çok kötü değildi, ancak burada kolay kurtulduk.

Just you, and nobody else but you.

Aşağıdaki planlara göz atabiliriz;

Gateway Goth

 

Her iki plana da OrderDate sütunundaki  dizinimiz yardımcı oluyor.Tam satır sayılarını bulmak için bu tabloyu şişirmedik, ancak başka bir yerde çalıştığını gördük. İkinci sorgu da tarama yapsa bile daha ucuz olacaktır.

COUNT() fonksiyonu, belirtilen ölçütlerle eşleşen satır sayısını döndürür. Kısacası veritabanındaki kayıtları sayabilmek için yerleşik COUNT() fonksiyonunu kullanırız.

Parantez içinde tanımlanan kriterleri karşılayan satır sayısını sayar. Satırların kendisini döndürmez; kriterlerinize uyan satır sayısını gösterir.

Peki SQL COUNT() işlevinin farklı varyasyonları olduğunu fark etmiş miydiniz? Bu makalede çeşitli bağımsız değişkenleri ve bunların kullanımlarını açıklamış olacağım.

COUNT(*) – COUNT(1) karşılaştırması

COUNT(*) ve COUNT(1) arasındaki farklar hakkında çeşitli tartışmalar görmüş olabilirsiniz. Ve belki de cevabı bulmaya çalışmak kafanızı daha da karıştırmış olabilir. Herhangi bir fark var mı diye soracak olursanız cevap basit. Hayır – hiçbir fark yok.

COUNT(*), NULL değerler de dahil olmak üzere tablodaki toplam satırları sayar.

COUNT(1) , sorgu sonuç kümesindeki tüm kayıtları 1 değeriyle değiştirir. NULL değerleriniz varsa, bu da 1 ile değiştirilir. Bu nedenle, COUNT(1) ayrıca toplam kayıt sayısını (NULL’lar dahil) döndürür.

Ancak, COUNT(*) ve COUNT(1) için sonuçlar aynıdır.

Bu iddiayı örnek bir sorgu kullanarak test edelim. İçinde 11 kayıt bulunan ofis adında geçici bir tablomuz olduğunu varsayalım. İlk 10 kayıt NOT NULL iken, son kayıtlar NULL.

No alt text provided for this image

Fonksiyon olarak * kullanıldığında, NULL’lar da dahil olmak üzere toplam satır sayısını sayar.

Örnekte, tabloda 11 satırımız olduğu için sonuç olarak 11 alacağız.

No alt text provided for this image

COUNT(1) ile ilgili kayıtları ilk sütundan itibaren saydığı şeklinde yanlış bir kanı vardır. COUNT(1)’in gerçekte yaptığı şey, sorgu sonucundan elde ettiğiniz tüm kayıtları 1 değeriyle değiştirip satırları saymaktır, yani bir NULL’u bile 1 ile değiştirerek sayarken NULL’ları dikkate alır.

Uygulamalı olarak görecek olursak, aşağıdaki resimde 11. satıra dikkat edin. Tablomuzda, sütun adı için 11. satır NULL’dur, ancak SELECT 1 FROM #office yaptığımızda, bu NULL’u 1 ile değiştirir ve bu nedenle satırları saydığımızda 10 değil 11 elde ederiz.

No alt text provided for this image

Dolayısıyla, her ikisi de sayarken NULL’ları dikkate aldığından, COUNT(1) ve COUNT(*) her zaman aynı sayıda satır döndürecektir.

No alt text provided for this image

Peki COUNT(column_name) Fonksiyonu Ne Yapar?

Fonksiyon olarak bir sütun adı (column_name) kullanıldığında, NULL’lar hariç toplam satır sayısını sayar, yani NULL’ları dikkate almaz.

Örneğimizde id sütununu saydığımızda 11, name sütununu saydığımızda ise 10 elde edeceğiz. Ofis tablosunu sorgulayarak kontrol edelim.

No alt text provided for this image

No alt text provided for this image

Son olarak çok merak edilen bir soru ile makaleyi tamamlamak istiyorum.

COUNT(*) COUNT(1)  Arasında Performans Farkı Var Mı?

Sonuç olarak COUNT(1) ve COUNT(*) birbirinin yerine kullanılabilen ve aynı sonucu döndüren yapılardır. Her ikisi de NULL değerleri göz ardı etmez ve her ikisi de belirli bir tablonun satır sayısını döndürür. Kolon sayısı fazla olan tablolarda COUNT(*) kullandığınızda performans kaybı yaşayabileceğiniz için COUNT(*) fonksiyonu dikkatli kullanılmalıdır.

Özetle;

COUNT(*) NULL’lar dahil tüm satırları sayar,

COUNT(1) NULL’lar dahil tüm satırları sayar,

COUNT(sütun_adı) tüm satırları sayar ancak NULL’ları saymaz

Raporlama Sunucusu Eklemenin Maliyeti

“Raporlama sorgularımızı ayrı bir SQL Server’a aktarmak istiyoruz.”

İlk maliyetler oldukça açıktır.

Donanım ve depolama – sanal bir makinede çalıştırıyor olsanız bile, örneğin 4 çekirdek ve 32 GB RAM maliyetlerini hesaba katmanız gerekir. Yalnızca veritabanları için depolama alanına ihtiyacınız olmayacak, aynı zamanda bu sunucunun yedeklenip yedeklenmeyeceğine ve bir felaket kurtarma veri merkezine kopyalanıp kopyalanmayacağına da karar vermeniz gerekecek.

Yazılım lisanslama – Standard Edition çekirdek başına ~2 bin dolar, Enterprise Edition ise çekirdek başına ~7 bin dolar. Windows’u (özellikle artık çekirdek başına lisanslandığı için), yönetim/yedekleme/antivirüs araçlarınızı ve izleme yazılımınızı da ekleyin.

Proje planlama – Always On Availability Groups, log shipping ya da transactional replication gibi yöntemlerle verileri üretimden raporlama sunucusuna nasıl aktaracağınızı tasarlamanız gerekecektir.

Uygulama değişiklikleri – raporlama sorgularını çalıştıran uygulamanın yeni bir connection string’e ihtiyacı olacaktır.  SQL Server’dan yalnızca okuma yapacağınız durumda aşağıda belirtilen kodu connection string parametresinde kullanmanız gerekir. Hem okuma hem de yazma yapan tek bir uygulamanız varsa ve yalnızca bazı sorguları devre dışı bırakmak istiyorsanız, bu sorguları yeni connection string’e geçirmek için kodu gözden geçirmeniz gerekecektir.

ApplicationIntent = ReadOnly

Bir sorun giderme süreci eklemek – er ya da geç veri replikasyon süreci bozulacaktır. Yönteme (AGs, log shipping, replication) ve hata türüne bağlı olarak, farklı şekillerde başarısız olacaktır – belki tüm veriler eskidir, belki sadece bir kısmı eskidir veya belki raporlara hiç erişilemez. Arıza yöntemlerini listelemek ve belirtilerin neye benzeyeceğini açıklamak isteyeceksiniz. Bu, iş kullanıcılarının raporlarının ne zaman yanlış olduğunu anlamalarına ve uygun şekilde tepki vermelerine yardımcı olur. Bu adımı atmazsanız, ilk başarısızlıktan sonra insanlar her zaman rapor verilerinde bir hata olduğunu düşüneceklerdir.

Başarısızlığa hazırlanın – bu başarısızlık yöntemlerinin her biri için nasıl tepki vereceğinize karar verin. Örneğin, AG replikasyonu bozulursa ve raporlar güncelliğini yitirirse, sorun çözülene kadar raporları primary sisteme mi yönlendireceksiniz yoksa siz sorun giderirken veya replikaları yeniden senkronize ederken kullanıcılar kullanılamayan raporlarla mı uğraşmak zorunda kalacak? Bu adımı atmazsanız, her seferinde boşa kürek çekmiş olursunuz ve raporlar hatalı veya çalışmaz durumdayken hazırlıksız görünürsünüz.

RPO ve RTO için gerçekçi beklentiler belirleyin – sürecinize ve hazırlığınıza bağlı olarak, iş kullanıcılarının işler bozulduğunda raporlarının ne kadar süre kapalı kalacağını anladıklarından emin olun.

Replikasyonun ek yükünü ölçün – AG’ler ve transactional replication, eskiden raporların maliyetinin ötesinde performans yavaşlamaları ekleyebilir. Örneğin, saatte yalnızca birkaç rapor çalıştırıyorsanız ve yalnızca verilerin bir alt kümesine ulaşıyorsanız, aniden her bir silme/güncelleme/ekleme işlemini çoğaltmak büyük bir ek yük getirebilir.

Monitoring ekleyin – raporlama sunucusunun ne kadar geride olduğunu ve her ikisinde de performansın nasıl gittiğini izlemeye başlamanız gerekir. Performans sorunlarını gidermek de çok daha zor hale gelir – örneğin, dizin ayarlaması yaparken, doğru dizin karışımını bulmak için hem birincil hem de raporlama sunucularındaki verileri birleştirmeniz gerekir.

Raporlamayı gerçekten yapmanız gerektiğinden emin misiniz?

Bu pahalı projeye başlamadan önce şunu sorun:

– Karşılaştığımız primary wait type nedir?

– Bu wait type’ı azaltmanın en ucuz/kolay yolu nedir?

Zaman zaman PAGEIOLATCH beklemeleriyle (bir veri dosyasından veri sayfalarını okumak için beklemek anlamına gelir) karşılaşan insanlar görüyorum ve 16-32GB RAM ile 1TB’lık bir veritabanıyla uğraşıyorlar. Bu sorunu çözmek için on binlerce dolar harcamayın – 1.000 dolarlık RAM satın alın ve dizin ayarlaması yapmak için biraz zaman harcayın.

En Fazla Karşılaştığımız 2 Büyük SQL Server Sorunu

Şirketler bizi performans veya yüksek kullanılabilirlik sorunları için arıyor, ancak tekrar tekrar bulduğumuz ilk iki şey şunlar oluyor:

  1. İşletmenin RPO (recovery point objective) ve RTO’suna (recovery time objective) uyacak şekilde yedekleme yapmıyorlar.
  2. CHECKDB’yi haftalık olarak ya da hiç yapmıyorlar ve bunun neden bir sorun olduğunu anlamıyorlar

Şimdi basit bir senaryo üzerinden gidelim ve nasıl yapacağınızı görelim.

Perşembe sabahı saat 11 ve bir e-posta alıyorsunuz: kullanıcılar kritik bir tabloda SELECT çalıştırdıklarında corruption hataları bildiriyorlar. Sorguyu çalıştırıyorsunuz ve tablodaki kümelenmiş dizinde corruption olduğu ortaya çıkıyor.

İşte bakım programınız:

Corruption gerçekleştiğinde onaramazsınız (bu bir clustered index ve tüm sütunları kapsayacak kadar non-cluster index yok) ve işletmenin bu verilere geri ihtiyacı vardır. Sıra sizde: bu soruları yanıtlayın:

  1. Sırayla hangi yedekleri geri yüklüyorsunuz?
  2. Bunlar bozulma içermeyecek mi?
  3. Ne kadar veri kaybetmiş olacaksınız?
  4. Bu süreç ne kadar sürecek?
  5. Buna göre, etkili RPO ve RTO’nuz nedir?
  6. İşletme bunun yeterince iyi olmadığını söylerse, para harcamadan bu rakamları iyileştirmek için hangi özel adımları atabilirsiniz?

Asynchronous Database Mirroring vs. Asynchronous Availability Groups

SQL Server 2005 Service Pack 1’de Database Mirroring çıktığında, Felaket Kurtarma çözümümüz olarak Log Shipping’i hızla bırakıldı. Log Shipping iyi bir özellik, ancak Asynchronous Database Mirroring ile Log Shipping’den daha hızlı yük devretme yapabiliyoruz.

SQL Server 2012’de Always On Availability Groups (AG) çıktığında, Transactional Replication, Failover Clustering ve Database Mirroring’den kurtulduğumuz için heyecanlandık. Raporlama ihtiyaçlarımızı (size göre değişebilir), Yüksek Erişilebilirlik ihtiyaçlarımızı ve Felaket Kurtarma ihtiyaçlarımızı çözdü.

Peki ya yalnızca Felaket Kurtarma ihtiyaçlarınız varsa ve Veritabanı Yansıtma kullanımdan kaldırıldığı için Availability Groups kullanmak istiyorsanız? Çekirdek kurulumunu düzgün yaptığınızdan emin olun!

Asynchronous Database Mirroring ve Asynchronous Availability Groups arasındaki büyük farka bakalım.

ASYNCHRONOUS DATABASE MIRRORING

Asynchronous Database Mirroring için tek ihtiyacımız olan iki sunucu: primary bölgesi asıl ve DR bölgesi üzerinde secondary. İkisi arasında async mirroring kurun ve işiniz bitti. Secondary sunucu çökerse üretim devam eder. Transaction backup operasyonları gerçekleştiğinde işlem günlüğü temizlenmez çünkü asıl sunucunun bu günlük kayıtlarını secondary sunucuya göndermesi gerekir. Log dosyalarının bulunduğu yerde secondary sunucu tekrar çevrimiçi olana kadar bunu destekleyecek yeterli disk alanınız olduğu sürece üretim devam eder. Elbette disk alanınız tükenirse kullanıcılar hata almaya başlayacaktır. Ancak bu biraz zaman alabilir ve çoğu zaman secondary sunucunun tekrar çevrimiçi olması için yeterli bir süredir.

ASYNCHRONOUS AVAILABILITY GROUPS

Asynchronous AG için hala iki sunucuya ihtiyacımız var: primary sunucu üzerindeki primary replika ve DR bölgesindeki secondary replika. İki sunucu aynı Windows Server Failover Cluster (WSFC) olduğunda, Availability Group iki replica’yıda kurun ve availability mode için asenkron-commit’i belirtin. Şimdi secondary replica’yı kapatın ve ne olduğuna bakın. Primary replika da çöktü mü? Birçok kişiden, secondary replikalarında bakım yaptıklarında primary replikalarının çöktüğünü ve nedeninden emin olmadıklarını duyduk. Bunun nedeni quorum ve/veya voting’in düzgün ayarlanmamış olmasıdır. Availability Groups, quorum gerektiren WSFC’yi kullanır. Yeter sayıya ulaşmak için primary sunucuda başka bir kaynağa ihtiyacınız olacaktır. Bunlar kurulduktan sonra, WSFC’nin yeter sayısını seçtiğiniz şekilde değiştirin. Örneğin, ” Node ve File Share Majority ” ya da “Node ve Disk Majority “. Artık secondary kopya kapandığında, cluster üzerinde hala bir quorum olduğundan (2’si açık, 1’i kapalı) üretim primary kopya üzerinde devam eder.

Windows 2012 R2 kullanıyorsanız, Dynamic Quorum yapısına sahipsiniz! Oylar gerektiğinde cluster tarafından dinamik olarak ayarlanabilir. Dynamic Quorum bahsettiğimiz sistem için kullanışlı olabilirdi, ancak bu Windows 2012 R2 çıkmadan önceydi.

 

Selective XML Index’ler: Hiçte Kötü Değil

Hiçbir şekilde bu konuda dünyanın en önde gelen otoritesi değiliz, sadece sorgumuz için en iyi olanı bulana kadar basit bir örnekle oynadık. Böylece hepiniz evinizde oynayabilirsiniz, hepimizin erişebildiği XML’i kullanıyoruz: Sorgu Planları!

Eğer herhangi biriniz sp_BlitzCache kullandıysanız, bir ton XQuery’nin işin içinde olduğunu bilirsiniz. Yakın gelecekte XML indeksleri ekleneceğini bilemiyoruz. Seçici XML Index leri 2012+, bu yüzden 2008R2’nin desteğinin bitmesini beklemek gerekecek. Bu gidişle, SQL Server’ı pencereden atıp sadece arkadaşlarımızın içmesine izin verdiğimiz bir bar açana kadar bu gerçekleşmeyecek.

XML Indexlerinin diğer biçimleri oldukça büyük olabilir ve genellikle varsayılan olarak sınırladığımız nispeten az miktarda XML işleme için oluşturmak için kaynak harcamaya değmez. Performans kazançları orada olmayacaktır.

Peki Seçici XML Indexi nedir? Bu bir Index! XML için! XML’in indekslenecek kısımlarını seçtiğiniz yer. Diğer XML indeksleri ya hep ya hiç şeklindedir ve belgelerinizin boyutuna bağlı olarak oldukça büyük olabilirler. Yanlış hatırlamıyorsak en az veri boyutunda olduklarını düşünüyoruz. Bazı örneklere bir göz atalım.

1

2

3

4

5

6

7

8

SELECT

ID = IDENTITY(INT,1,1),

deq.query_plan

INTO #xml_index_test

FROM sys.dm_exec_cached_plans AS dec

CROSS APPLY sys.dm_exec_query_plan(dec.plan_handle) AS deq

 

ALTER TABLE #xml_index_test ADD CONSTRAINT pk_id PRIMARY KEY CLUSTERED (ID)

Temp table üzerinde 225 query planı var gözüküyor.

1

2

3

4

5

6

7

8

9

10

11

SET STATISTICS TIME, IO ON

 

;WITH XMLNAMESPACES(‘http://schemas.microsoft.com/sqlserver/2004/07/showplan’ AS p)

SELECT xit.ID,

SerialDesiredMemory = xit.query_plan.value(‘sum(//p:MemoryGrantInfo/@SerialDesiredMemory)’, ‘float’) ,

SerialRequiredMemory = xit.query_plan.value(‘sum(//p:MemoryGrantInfo/@SerialRequiredMemory)’, ‘float’),

CachedPlanSize = xit.query_plan.value(‘sum(//p:QueryPlan/@CachedPlanSize)’, ‘float’) ,

CompileTime = xit.query_plan.value(‘sum(//p:QueryPlan/@CompileTime)’, ‘float’) ,

CompileCPU = xit.query_plan.value(‘sum(//p:QueryPlan/@CompileCPU)’, ‘float’) ,

CompileMemory = xit.query_plan.value(‘sum(//p:QueryPlan/@CompileMemory)’, ‘float’)

FROM #xml_index_test AS xit;

Ancak aldığım sorgu planı çok saçma görünüyor ve 1355 sorgu parasına mal oluyor. XML ile çalıştığım için şimdiden pişman olacağız gibi.

I'd rather be querying .jpgs

Deneyebileceğimiz ilk Seçici XML dizini türü, sorguladığımız iki node üzerinde tanımlanır. Bunu şu şekilde oluşturabilirsiniz:

1

2

3

4

5

6

CREATE SELECTIVE XML INDEX ix_xml_selective ON #xml_index_test(query_plan)

WITH XMLNAMESPACES(‘http://schemas.microsoft.com/sqlserver/2004/07/showplan’ AS p)

FOR (

MemorygrantInfoNode = ‘//p:MemoryGrantInfo’ AS XQUERY ‘node()’,

QueryPlanNode = ‘//p:QueryPlan’ AS XQUERY ‘node()’

);

Sorgumuzu tekrar çalıştırırsak… Hiçbir şey değişmiyor, sadece daha da kötüleşiyor. Tam anlamıyla kötüleşmiyor. Plan ve maliyet aynı, ancak artık işe yaramaz bir dizinimiz var.

1

2

3

4

5

6

7

8

9

10

CREATE SELECTIVE XML INDEX ix_xml_value ON #xml_index_test(query_plan)

WITH XMLNAMESPACES(‘http://schemas.microsoft.com/sqlserver/2004/07/showplan’ AS p)

FOR (

SerialDesiredMemory = ‘//p:MemoryGrantInfo/@SerialDesiredMemory’ AS SQL INT SINGLETON,

SerialRequiredMemory = ‘//p:MemoryGrantInfo/@SerialRequiredMemory’ AS SQL INT SINGLETON,

CachedPlanSize = ‘//p:QueryPlan/@CachedPlanSize’ AS SQL INT SINGLETON,

CompileTime = ‘//p:QueryPlan/@CompileTime’ AS SQL INT SINGLETON,

CompileCPU = ‘//p:QueryPlan/@CompileCPU’ AS SQL INT SINGLETON,

CompileMemory = ‘//p:QueryPlan/@CompileMemory’ AS SQL INT SINGLETON

);

Bu da hiçbir fark yaratmıyor. Her yolu döndürdüğümüz SQL türü olarak tanımlamayı denedik. Yine aynı plan, aynı maliyet. Sırada ne var?

1

2

3

4

5

6

7

8

9

10

CREATE SELECTIVE XML INDEX ix_xml_selective ON #xml_index_test(query_plan)

WITH XMLNAMESPACES(‘http://schemas.microsoft.com/sqlserver/2004/07/showplan’ AS p)

FOR (

SerialDesiredMemory = ‘//p:MemoryGrantInfo/@SerialDesiredMemory’ AS XQUERY ‘xs:double’ SINGLETON,

SerialRequiredMemory = ‘//p:MemoryGrantInfo/@SerialRequiredMemory’ AS XQUERY ‘xs:double’ SINGLETON,

CachedPlanSize = ‘//p:QueryPlan/@CachedPlanSize’ AS XQUERY ‘xs:double’ SINGLETON,

CompileTime = ‘//p:QueryPlan/@CompileTime’ AS XQUERY ‘xs:double’ SINGLETON,

CompileCPU = ‘//p:QueryPlan/@CompileCPU’ AS XQUERY ‘xs:double’ SINGLETON,

CompileMemory = ‘//p:QueryPlan/@CompileMemory’ AS XQUERY ‘xs:double’ SINGLETON

);

Son olarak, her bir yolu veri türüyle birlikte onları almak için kullandığımız XQuery ifadesi olarak tanımlamayı denedik. Bu nihayet bir fark yarattı, hem de çok büyük bir fark. Sorgu maliyeti 0,55’e düştü. Bir dizin için hiç de fena değil.

What time is it, even?

Sadece XML Seçme

.exist(), .nodes() veya .query() gibi diğer olası XQuery yöntemlerine ya da herhangi bir yerdeki verileri birleştirmek için sql:column kullanımına girmiyorumuz. Bu, bir blog yazısında uğraşmak istediğimden daha fazla XML demek. XML’i çok kullanıyorsanız ve SQL Server 2012+ kullanıyorsanız, SXI’lere bir şans vermek isteyebilirsiniz. Çalışmalarını sağladığınızda oldukça havalı olabilirler.

 

Sql serverın kaynak kullanımının göz önünde bulundurularak aynı makine üzerine birden çok kurulumun yapılmamasını öneriyoruz. Ancak iş ihtiyaçlarınıza göre bu duruma karar verebilirsiniz.

Instance stacking tekniği, aynı Windows üzerinde birden fazla SQL Server Instance yükleme tekniğidir. Örneğin, SQLPROD1 adında bir sanal makineniz veya sunucunuz olabilir:

Instance Stacking Tekniğinin Faydaları

Daha düşük SQL lisanslama maliyetleri – yalnızca bir lisans için ödeme yapmanız gerekir ve Standard Edition bile aynı Windows tabanına düzinelerce Instance yüklemenize izin verir.

Daha düşük Windows lisanslama maliyetleri – yalnızca bir Windows için ödeme yapmanız gerekir.

Daha kolay Windows Patch – yalnızca bir işletim sistemi yüklemeniz gerektiğinden.

Instance Stacking Tekniğinin Dezavantajları

Performans ayarlaması çok daha zordur – tüm Instance’lar aynı CPU, memory, network ve depolama alanını paylaşır. SQL Server ilk ikisini hafifletmek için affinity masking ve bellek ayarları gibi hileler sunsa da, ikinci ikisi için hiçbir cevabı yoktur. Bir Instance üzerindeki backup, ne kadar ayarlama çalışması yaparsanız yapın diğer Instance’ların performansını düşürecektir. Instance’lardan hiçbiri performansa duyarlı değilse, bu önemli değildir – ancak bu ne sıklıkla olur? Ve “doğru” bellek veya CPU ayarlarının ne olduğunu nasıl anlarsınız? O kadar çok insan çalışması ve deneme gerektirir ki, ancak sunucu başına DBA başına bolca boş zamanınız olduğunda gerçekten mantıklıdır.

Çok daha zor reboot planlaması – tüm Instance’ların tüm müşterilerin Windows’u patch geçmek için belirli bir zaman üzerinde anlaşmasını sağlamanız gerekir.

Güvenlik zorlukları – bazen, veritabanlarını barındıran Windows Instance’ına RDP ile girebilmekte ısrar eden korkunç insanlar oluyor. Bu kişiler kutunun tamamında sistem yöneticisi olmakta ısrar ederlerse, çalışan diğer Instance’larına zarar veren değişiklikler yapabilirler.

Alternatif: Sanallaştırma

Tek bir sunucuyu daha küçük parçalara ayırmayı düşündüğünüzde, bunun yerine sanallaştırmayı düşünün. Yeni SQL Sunucuları için harika bir varsayılan yerdir.

Her SQL Server kendi Windows örneğini hak eder. Evet, bu daha yüksek lisans maliyetleri anlamına gelir – SQL Server Enterprise Edition’ı donanım ana bilgisayarı düzeyinde lisanslamanız gerekir ve ardından ana bilgisayara mümkün olduğunca çok sayıda sanal makine yerleştirebilirsiniz.

Ardından, her sanal makine kendi performans yönetimine, yama programlarına ve güvenliğine sahip olur. Artı, sürpriz bonus: her sanal makine, en küçükleri bile Enterprise Edition’ın tüm özelliklerine sahip olur.

 

[vc_row][vc_column][vc_column_text]

SQL Server Databases

SQL Server üzerinde veritabanları bizim için her şeydir. Bu veritabanlarında oluşabiliecek en sorun bizim verdiğimiz hizmetin tamamen kesilmesine vesile olabilir. SQL Server üzerinde bulunan veritabanlarının ve bu veritabanlarında dikkat etmemiz gereken yerler ile ilgili yerleri bu postumuzda anlatacağız.

Veritabanı Türleri

  1. Kullanıcı Veritabanları: Kullanıcı veritabanları, bir kuruluşun iş süreçleri için özel olarak tasarlanmış veritabanlarıdır. Kullanıcı veritabanları, genellikle uygulama verileri, iş akışı verileri ve kullanıcıların oluşturduğu verileri depolar. Kullanıcı veritabanlarının özellikleri arasında şunlar yer alır:
  1. Sistem Veritabanları: Sistem veritabanları, SQL Server’ın kendisi tarafından kullanılan ve yönetilen özel veritabanlardır. Sistem veritabanları, SQL Server Instance’ın sağlıklı bir şekilde çalışmasını sağlamak için gereklidir. Sistem veritabanlarının özellikleri arasında şunlar yer alır:
Sistem veritabanlarının özellikleri sekmesinde, her veritabanı için kullanılan disk alanı, dosya yolunu ve boyutu görüntülenebilir. Bununla beraber kapatılması gereken bir çok konu olduğunu biliyoruz ve sonraki postlarımızda bunları anlatmaya çalışacağız. [/vc_column_text][/vc_column][/vc_row]

Size ve Veritabanlarınıza Yardımcı Olmak İçin Bekliyoruz!

İletişime geçerek hemen destek alabilirsiniz.

İletişim

SQL Server Instance konfigürasyonu hakkında best practice’lerine uygun bir şekilde nasıl yapılması gerektiği konusunda kapsamlı bir çalışma yapmak ve hizmet verdiğimiz ortamları her zaman daha iyi hale getirmek mümkün. İşte bu konuda birkaç önemli nokta:

  1. Disk konfigürasyonu: Disk konfigürasyonu, SQL Server’ın performansını önemli ölçüde etkileyebilir. SQL Server Instance’ı, ayrı disk sürücülerinde yüksek yoğunluklu I/O işlemlerini gerçekleştirerek daha iyi performans sağlanabilir.
  2. Bellek konfigürasyonu: Bellek, SQL Server’ın performansında önemli bir rol oynar. SQL Server Instance’ın yüksek miktarda bellek kullanmasını sağlayarak performansını artırabilirsiniz.
  3. CPU konfigürasyonu: CPU konfigürasyonu, SQL Server’ın performansını doğrudan etkiler. Birden fazla işlemci çekirdeği olan bir sistem kullanarak, SQL Server’ın CPU kullanımını optimize edebilirsiniz.
  4. Tempdb konfigürasyonu: Tempdb, SQL Server’ın geçici verileri sakladığı özel bir veritabanıdır. Tempdb’yi ayrı bir disk sürücüsüne taşıyarak performansı artırabilirsiniz.
  5. Güvenlik konfigürasyonu: SQL Server’ı güvenli bir şekilde yapılandırmak, verilerinizi korumanıza ve istenmeyen erişimlere karşı korunmasına yardımcı olur. Örneğin, parola politikaları belirlemek ve sıkı erişim kontrolleri sağlamak iyi bir güvenlik konfigürasyonu için önemlidir.
  6. Yedekleme konfigürasyonu: SQL Server’ı düzenli olarak yedeklemek, verilerinizi kaybetmenize karşı korur. Yedekleme konfigürasyonu, yedekleme işlemlerinin otomatik olarak yapılmasını ve yedek dosyalarının saklanması için uygun bir disk alanı ayrılmasını içermelidir.
  7. İzleme konfigürasyonu: SQL Server’ı izlemek, performans sorunlarını tespit etmek ve sorunları gidermek için önemlidir. SQL Server Instance’ı izlemek için, uygun izleme araçları ve yöntemleri kullanarak bir izleme planı oluşturmalısınız.

Bu konular hakkında daha fazla ayrıntı ve best practice örnekleri için hazırladığımız videoyu izleyebilirsiniz.

Aşağıdaki linkten sp_WhoIsActive sorgusuna ulaşabilirsiniz.

https://github.com/CopyZenx/sp_WhoIsActive/blob/main/sp_WhoIsActive.sql