SQL Server 2016 (CTP2) Query Store – Bölüm 1
Danışmanlık verdiğim hemen hemen bütün müşterilerimde aynı sorular ile karşılaşıyorum; “Query’im neden bu index’i kullandı?“, “Query’lerim neden geç geliyor?“, “Query’lerimin performansını nasıl arttırabilirim?“. Bu gibi sorular sorulduğunda ilk “Query plan’ı inceledinizmi?” diye sorarım. Bu şekilde karşı soru yöneltmemin nedeni execution plan (Query Plan) sonucunun bütün bu sorulara cevap olabileceğidir.
Peki execution plan nasıl çalışır? Execution plan, query optimizer’ın döndüğü matematiksel sonucu hesaplayıp karşınıza anlamlaştırarak çıkartır. Bir query gönderdiğinizde SQL Server, birkaç process’i eş zamanlı olarak çalıştırır ve query’niz ilk olarak relational engine tarafından işleme alınır. T-SQL kodunuzun doğruluğu burada sorgulanır. Eğer doğruysa query parse edilir ve süreç bu şekilde ilerler. Query’nin oluşturulması ile sonuç dönmesi arasında daha çok fazla adım vardır. Bu post’ta hepsine değinmeye gerek yok.
Eminim SQL Server ile çalışan herkes query’nin herhangi bir nedenden dolayı yanlış ve yeni bir plan almasıyla performans problemi yaşamıştır veya SQL Server’ı upgrade/restart ettiğinde query’nin önceki planının ne olduğunu öğrenmek istemiştir. Bu gibi durumlarda ya 3rd party kullanır veya kendi tracking yapımızı oluştururduk. SQL Server 2016’da bu problemlere cevap olacak yeni bir özellik geldi: Query Store! SQL Server 2016’nın CTP1 versionundan beri yeni gelen özellikleri inceliyor, bug bulduğum kısımları Microsoft’a bug report yapıyorum. Geçtiğimiz günlerde CTP2 artık ilk public version olarak indirilebilir olarak duyuruldu. Anlatacaklarımı kendinizde CTP2 üzerinde deneyebilirsiniz. Query Store, CTP1’de mevcut değildi. Fakat CTP2’nin public versionunda dahil edildi.
Query Store nedir? Ne yapar?
Query Store, plan değişikliklerinden dolayı yaşanılan performans problemleri için geliştirilmiştir. Fakat Query Store’da yapabilecekleriniz bununla sınırlı değildir. Query Store ile sistem üzerinde Query plan geçmişini tutabilirsiniz. Zaman içerisinde execution plan’ı değişmiş query’lerin önceki plan’ları ile karşılaştırılmasını sağlayabilirsiniz ve Query plan geçmişinde tutulan eski planları query’lere force ettirebilirsiniz.
Nasıl kullanılır?
Query Store, instance bazlı değildir. Veritabanı spesifik çalışır. Bu yüzden ilk olarak istenilen veritabanı üzerinde Query Store’un açılması gerekir. Default olarak kapalıdır.
|
ALTER DATABASE CURRENT SET QUERY_STORE = ON |
Query Store açıldığında query plan’ların ve query performans verilerinin toplanması başlatılır. Fakat toplama süresi default olarak 1 saattir. Benim için 1 saat uzun bir süre olduğundan ben bu süreyi 1 dakika olarak değiştiriyorum.
|
ALTER DATABASE CURRENT SET QUERY_STORE (INTERVAL_LENGTH_MINUTES = 1) |
Bu ve bunun gibi özellikleri Database Properties altından da ulaşabilirsiniz.
Bu ekranda değinmemiz gereken birkaç önemli parametre var.
Max Size (MB): Bu parametre ile query store büyüklüğünü belirlersiniz. Eğer query store belirlenen MB’ye ulaşırsa otomatik olarak Operational Mode’u Read Write’tan Read Only’ye çekilir.
Stale Query Threshold (Days): Bu parametre ile belirlenen gün kadar capture edilen data’nın query store içerisinde kalması sağlanır. Default’u 367 gündür.
Query Store kullanarak performans problemlerinin saptanması artık gerçektende çok kolay oldu. En basit şekilde bu konuda şu şekilde bir yol izleyebilirsiniz. Veritabanında Query Store’u açıyoruz –> Query Store ile verilerin toplanmasını sağlıyoruz –> Problemli query’yi seçiyoruz –> ve FORCE PLAN. Bu süreç için bir demo hazırladım. Bunu adım adım gerçekleştirelim.
İlk olarak bu çalışma için demo1 isminde bir veritabanı oluşturuyorum ve üzerinde Query Store’u açıp, store boyutunu 200MB olarak belirleyip, plan verisini her 1 dakikada bir toplayacak şekilde ayarlıyorum.
|
CREATE DATABASE [demo1] GO USE [demo1] GO ALTER DATABASE [demo1] SET QUERY_STORE = ON ALTER DATABASE [demo1] SET QUERY_STORE (INTERVAL_LENGTH_MINUTES = 1) ALTER DATABASE [demo1] SET QUERY_STORE (MAX_STORAGE_SIZE_MB = 200) GO |
Oluşturduğum veritabanı içerisine tablo oluşturup, veri yazıyorum ve index’liyorum. Aynı query’nin birden fazla query plan’a sahip olması için mümkün olduğu kadar kötü bir mimaride yapıyı oluşturmaya çalıştım. (CI yerine NCI seçiyorum vb.)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
|
CREATE TABLE [dbo].[OrderTable] ( [ID] INT NULL, [OrderImage] BINARY(2000) NULL ) ON [PRIMARY] GO DECLARE @RowCount INT SET @RowCount = 0 WHILE @RowCount < 10000 BEGIN INSERT INTO [dbo].[OrderTable]([OrderImage]) VALUES(CONVERT(VARBINARY(2000), @RowCount * @RowCount)) SET @RowCount = @RowCount + 1 END GO INSERT INTO [dbo].[OrderTable]([ID]) VALUES(1) GO 100000 CREATE NONCLUSTERED INDEX [IDX_1] ON [dbo].[OrderTable] ([ID]) GO |
Burada önemli olan oluşturduğumuz veriyi kullanıp, Query Store içerisinde plan’ları görmek. Bunun için bir workload yazdım. Bu EXE’yi ilgili linkten indirebilirsiniz. baglanti.xml dosyasını edit’leyip kendi connection string’inizi yazmalısınız.
EXE'yi indir
SSMS üzerinde demo1 altından Query Store’a girip, “Top Resource Consuming Queries” ‘i açıyoruz.
EXE’yi çalıştırıp query’nin birden fazla plan almasını ve bunun Query Store tarafından capture edilmesini sağlıyoruz. EXE’yi .NET Framework 4.5.1 ‘de derledim. Framework hatası alırsanız bundandır.
Workload’u 30-40 saniye kadar çalıştırmak yeterli olacaktır. Daha sonra SSMS’de açtığımız “Top Resource Consumers” ekranını refresh ediyoruz.
Metric olarak “Execution Count” ‘u ve hemen yanındaki bölümden de “num plans” ‘ı seçiyorum. En başta görüntülenen yeşil sütundaki query’min 2 farklı query plan’a sahip olduğu anlaşılıyor. Plan Summary kısmından bu plan’ların ne zaman yaratıldıklarını görmek mümkün. Bu planlar arası farklılıkları görmek için “Compare the plans for the selected query in a separate window.” butonuna tıklıyorum.
Alt kısımda yer alan plan’da table, scan edilirken yukarıdaki plan’da index’in seek edildiği görünüyor. Yukarıdaki plan’ı tercih ediyorum ve “Force Plan” ‘a tıklıyorum. Böylelikle query’min artık yukarıdaki plan’ı kullanmasını sağlıyorum.
Bu makalede Query Store’u basit şekilde inceledik. Bu serinin bir sonraki makalesinde biraz daha derinlemesine inceleyeceğiz.
Post Details