3 Nisan 2014 Perşembe

Clustered Index Seek (Spatial): "Missing Column Statistics" ?!

Spatial veritiplerini ne kadar kullanıyorsunuz bilemiyorum, ama bizim 1-2 projemizde kullanılıyor ve bu nedenle Spatial Index'ler konusunda yüzeyselden öte biraz çalışma yapmam gerekti.

Aşağıdaki görüntüyü bir Execution Plan'da ilk defa gördüğümde şaşırmıştım, adını aşağıda paylaşacağım kitapta bunu gördüğümde o tecrübem aklıma geldi ve sizlerle de paylaşmak istedim.

Clustered Index Seek (Spatial)
Neden şaşırdığımı, Execution Plan'larla haşır neşir olan arkadaşlarım hemen anlayacaktır. Clustered Index Seek operatörü simgesinin üstünde bir de ünlem işareti vardı. Execution Plan'lardaki ünlem işaretleri, Execution Plan incelemelerinde ilk göze çarpan şeylerdendir. Tabii ki benim de hemen dikkatimi çekmişti ve fare ile bu operatörün üstüne gelip biraz beklediğimde (veya F4'e basıp Properties penceresindeki Warning alanında da görebilirsiniz) "Missing Column Statistics" uyarısını gördüm.

Bunu ilk gördüğümde, bunun gayet normal olduğunu bilmiyordum. Şöyle ki, geleneksel B-Tree Index'lerinin aksine, SQL Server, Spatial Index'lerin istatistiklerini Internal tablolarda tutuyor. Fakat maalesef Execution Plan oluşturulması işlemi sırasında bu dikkate alınmıyor ve biz de ilk gördüğümüzde bizi kaygılandıran bu uyarıyı görüp çırpınıyoruz.

Bu ve benzeri güzel bilgileri Pro Spatial with SQL Server isimli kitapta bulabilirsiniz! Özellikle SQL Server'da Spatial veritipleriyle çalışan arkadaşlarıma tavsiye ederim. En azından referans kaynak olarak elinizin altında bulunmasında fayda var.

Ekrem Önsoy


SQL Server 2012: Target Recovery Time

SQL Server 2014'ü incelerken farkettiğim, fakat aslında ilk defa SQL Server 2012 ile geldiğini öğrendiğim bir özellik, Target Recovery Time'a değinmek istiyorum.

SQL Server 2012'deki yeniliklerden bahsedilirken veya herhangi başka bir makalede hiç rastlamamıştım bu özelliğe. Bu özellik CHECKPOINT ile ilgili. Bu vesileyle SQL Server'daki Checkpoint'lere de değinmiş olayım.

Veritabanı moturunda veri sayfalarında yaptığı işlemleri RAM'de yapar (Data Cache'te) ve yaptığı her değişiklikten sonra hemen diske yazmaz bu değişiklikleri. Zaman zaman, aşağıda çeşitlerini açıkladığım gibi değişik Checkpoint tiplerini kullanarak yapar değişiklikleri diske yazma işlemini. Checkpoint işlemi, hafızadaki o anda bulunan (kirli sayfalar da denilen) veri sayfalarını ve Transaction Log bilgisini hafızadan diske yazma işlemidir. 

SQL Server'da 4 çeşit Checkpoint var, bunlar:
- Automatic: Otomatik Checkpoint'ler "EXEC sp_configure 'recovery interval', 'seconds'" ayarına bağlı olarak tetiklenir. Ayrıca veritabanı motoru yazma işlemlerindeki gecikme 20 milisaniyeyi geçtiğinde de bunu tetikler.
- Indirect: Bu, veritabanı bazında bir ayardır ve "ALTER DATABASE … SET TARGET_RECOVERY_TIME = target_recovery_time { SECONDS | MINUTES }" komutuyla belirlenir. Bu ayar, Instance düzeyinde belirlenen Automatic ayarı ezer. Varsayılan değeri 0'dır ve bu durumda diğer tipler işler.
- Manuel: Transaction SQL komutu olan CHECKPOINT komutu çalıştırılarak tetiklenebilir.
- Internal: Yedek alma veya veritabanı Snapshot'ı oluşturma gibi işlemlerde otomatik olarak veritabanı moturu tarafından tetiklenir. Bu tip için sizin müdahale etme şansınız yok.

Target Recovery Time özelliğini SQL Server Management Studio (SSMS) arayüzünden de değiştirebilirsiniz. Bunun için ilgili veritabanının özelliklerine gidip, Options sayfasındaki Recovery bölümünden aşağıdaki ekran görüntüsünde işaretlediğim ayarı değiştirmelisiniz. Örneğin bu ayarı 30 yaparsanız, her 30 saniyede bir veritabanınız için Checkpoint komutu çalıştırılacaktır ve Dirty Page'ler diske yazılacaktır. 

Bu komutu gerçekten ne yaptığınızı biliyorsanız kullanmanızı tavsiye ederim. Checkpoint işleminin her işlem gerçekleştiğinde tek tek değil de toplu toplu yapılmasının bir nedeni var, performans! Bu nedenle gerçekten ihtiyacınız olduğundan emin değilseniz Checkpoint işlemini bırakın SQL Server varsayılan ayarlarıyla halletsin.

SSMS: Target Recovery Time
Checkpoint'ler hakkında daha fazla bilgi için benim de bu yazıyı yazarken yararlandığım BOL sayfasını kullanabilirsiniz: http://msdn.microsoft.com/en-us/library/ms189573%28v=sql.120%29.aspx

Ekrem Önsoy

SQL Server 2014 - BPE ile ilgili bir BUG

Brent Ozar Buffer Pool Extension (BPE) kullanımıyla ilgili bir BUG tespit etmiş ve bunu dosyalamış. Bu konudaki gelişmeleri aşağıdaki Connect sayfasından takip edebilirsiniz.

https://connect.microsoft.com/SQLServer/feedback/details/844906/buffer-pool-extensions-fail-on-sql-server-restart

Ekrem Önsoy

2 Nisan 2014 Çarşamba

Yeni Cardinality Estimator

Bildiğiniz gibi dün, 1 Nisan'da SQL Server 2014 artık genel olarak kullanılabilir oldu ve Microsoft'un aşağıdaki adresinden indirilebilir:

http://technet.microsoft.com/en-US/evalcenter/dn205290

Yeni Cardinality Estimator hakkında biraz daha fazla yeni bilgi edinme şansım oldu, sizlerle de paylaşmak istedim.

Öncelikle, Cardinality Estimator nedir biraz onu anlatmaya çalışayım. Cardinality Estimation, SQL Server sorgu işlemcisi tarafından, Execution Plan oluşturulma işleminde kullanılır. Cardinality Estimate'ler nihai kayıt sayısı ve Join'ler, filtrelemeler ve SUM, COUNT gibi Aggregate işlemlerindeki kayıt sayılarının tahmininde kullanılır. Bu tahminler de yapılacak olan işlemler için oluşturulacak Execution Plan'ların seçimini belirler.

SQL Server 2014 öncesindeki SQL Server 2000, 2005, 2008, 2008R2 ve 2012 gibi versiyonlarda çoğu  kodu SQL Server 7.0'da yazılmış Cardinality Estimator kullanılıyordu; SQL Server 2014 ile birlikte isteğe bağlı olarak yeni, çağımızın iş yüklerine uygun olarak yazılmış Cardinality Estimator kullanılacak. İsteğe bağlı olarak dedim, çünkü bu yeni Cardinality Estimator'ı eğer veritabanının Compatibility Level'ını 120 yaparsanız veya 2312 numaralı Trace Flag'i kullanırsanız kullanabiliyorsunuz. Eğer veritabanınızın Compatibility Level'ı 120'den düşük ise ve 2312 numaralı Trace Flag'i de kullanmıyorsanız, o zaman yukarıda sıraladığım eski versiyonlarda varolan Cardinality Estimator'ı kullanıyor olacaksınız.

Eğer veritabanınızın Compability Level'ı 120 ise ve siz buna rağmen yine de eski Cardinality Estimator'ı kullanmak istiyorsanız o zaman da 9481 numaralı Trace Flag'i kullanmanız gerekiyor.

Eğer veritabanınızın Compatibility Level'ı 120 ise Execution Plan'ın 1. operatörünün Properties penceresindeki CardinalityEstimationModelVersion alanında 120 değerini göreceksiniz. Eğer ilgili veritabanının Compatibility Level'ı 120'den daha düşükse, o zaman bu alanda 70 değerini göreceksiniz. Bu da bence SQL Server 7.0'ye vurgu.

Bu Trace Flag'lerini sunucu, oturum veya sorgu düzeyinde kullanabilirsiniz. Ben şahsen, isterseniz ayıplayabilirsiniz, sorgu düzeyinde Trace Flag kullanılabildiğini bilmiyordum. Aşağıda bir örneğini veriyorum:

SELECT * FROM FactCurrencyRate WHERE DateKey = 20101201 OPTION (QUERYTRACEON 2312)

Compatibility Level'larını her değiştirdiğinizde ilgili veritabanı için Plan Cache'inizin de tamamen sıfırlanacağını hatırlamalısınız. Bu nedenle bu işlemi sık sık yapmak istemezsiniz.

Cardinality Estimator'un hangi versiyonunu kullanıyor olursanız kullanın, ama sonuç olarak Cardinality Estimator'lar için İstatistikler çok önemlidir. Bu nedenle İstatistiklerinizi olabildiğince güncel tutmanızda fayda büyük var. Auto Update Statistics ve Auto Create Statistics ayarlarının açık olduğundan emin olmalısınız. Index ve İstatistik bakımlarınızı düzenli olarak yapmalısınız. Cardinality Estimator'lar için bunlar çok kritiktir.


Yeni Cardinality Estimator'da, eskisinde olan tablo değişkenleriyle, TVF, TVP ve yerel değişkenlerle ilgili sorunların düzeltilmediği de belirtiliyor.


Bu yazı için yararlandığım kaynak: CSS SQL Server Engineers: SQL Server 2014’s new cardinality estimator (Part 1) 


Ekrem Önsoy

1 Nisan 2014 Salı

A connection was successfully established with the server, but then an error occurred during the login process. (provider: TCP Provider, error: 0 - The specified network name is no longer available.) (Microsoft SQL Server, Error: 64)

HATA:
SSMS'ten bağlanmaya çalıştığımda aldığım hata mesajı:
A connection was successfully established with the server, but then an error occurred during the login process. (provider: TCP Provider, error: 0 - The specified network name is no longer available.) (Microsoft SQL Server, Error: 64)

SQLCMD'den bağlanmaya çalıştığımda aldığım hata mesajı:
HResult 0x40, Level 16, State 1
TCP Provider: The specified network name is no longer available.

Sqlcmd: Error: Microsoft SQL Native Client : Communication link failure.

AÇIKLAMA:
Dün gece bir operatör bana bu hatayı haber verdi. Sorun yaşanan makineye X diyelim. Bu makine ile Y makinesi arasında Transactional Replication kurulu. Hem X'te Y'ye gönderilen bir Publication var, hem de Y'de, X'e gönderilen bir Publication var. Yani çift taraflı replikasyon söz konusu.

Öncelikle şunları kontrol ettim:
- X'ten Y'ye ve tam tersi yönde Ping atılabiliyor mu? Evet!
- X'ten Y'ye ve tam tersi yönde TELNET yapılabiliyor mu? Evet!
- X'e RDP yapmışken Y'ye SSMS ile bağlanabiliyor muyum? Hayır!
- Y'ye RDP yapmışken X'e SSMS ile bağlanabiliyor muyum? Evet!

- X'e RDP yapmışken Y'ye SQLCMD ile bağlanabiliyor muyum? Hayır!
- Y'ye RDP yapmışken X'e SQLCMD ile bağlanabiliyor muyum? Evet!
- X'e RDP yapmışken Y'ye ODBC Administrator'dan bir DSN oluşturup bağlanabiliyor muyum? Hayır!

- Y'ye RDP yapmışken X'e ODBC Administrator'dan bir DSN oluşturup bağlanabiliyor muyum? Evet!
- X'teki Windows Application Event Log'da ve SQL Error Log'da herhangi ilgili bir kayıt var mı? Yok!
- Y'deki Windows Application Event Log'da ve SQL Error Log'da herhangi ilgili bir kayıt var mı? Eğer yanlış kullanıcı bilgileri girersem, var! Eğer doğru kullanıcı bilgileriyle bağlanmaya çalışırsam, yok!
- İki sunucudaki Windows Firewall'ları kontrol ettim, kapalılar.
- Sistem ve Ağ yöneticileriyle konuştuk, bildiğimiz bir değişiklik yok dediler ve onlar da düşündü ve ortaya bir şey çıkmadı.
- X'te de Y'de de antivirüs uygulamaları kurulu, fakat uzun zamandır kuruluydular ve sorun dün akşam 19:00'dan itibaren olmaya başladı ve sistem yöneticilerinin söylediğine göre bu uygulamalarda SQL bağlantısını engelleyebilecek bir ayar da yok.
- Ağdaki diğer sunuculardaki SSMS ve SQLCMD'lerden Y'e bağlanmaya çalışıyorum, sorun yok. 
- Belli ki X'e özel bir durum söz konusu. X sunucusunu yeniden başlattık, fakat sorun çözülmedi.
- Son çare Google'a sordum. Bu sorun, çok genel bir sorun. Yani belli bir sorun değil. Herkes başka bir şey söylemiş ve hiçbiri de benim durumuma uymuyor.



ÇÖZÜM:
Son çare olarak Y sunucusunu yeniden başlatmayı gördük. Böyle garip durumlarda maalesef genelde yeniden başlatmak çözüm oluyor. Bizim durumumuzda da bu bir çözüm oldu. Fakat maalesef sorunun neden çıktığını, neden çözüldüğünü bilmiyor durumdayız. Bunu bu şekilde söylemek ve bu şekilde dokümante etmek canımı sıkıyor, ama olur ya belki bir gün birinin işine yarar...

Ekrem Önsoy