Sepetiniz

SQL Server Tüm Veritabanlarında Otomatik Audit Oluşturmak

SQL Server’da bir Instance üzerinde tüm veritabanlarında, tüm kullanıcıların yapmış olduğu belli işlemleri kaydetmek isteyebilirsiniz. Bunun için Audit özelliğini kullanmanız gerekir. Audit hakkında detaylı bilgi almak için SQL Server Audit Oluşturmak isimli makaleyi okuyabilirsiniz. Bir instance üzerinde çok sayıda veritabanı olduğunda bunları manuel biçimde oluşturmak oldukça zaman alacaktır. Ayrıca bazı şeyleri gözden kaçırma ihtimali de oluşturacaktır. Bu nedenle TSQL ile tüm veritabanlarında bunları oluşturmak daha efektif olacaktır. Bununla ilgili olarak yazdığım Script aşağıdadır. Ben örnek olarak Audit adlarını veritabanı adlarıyla birebir aynı aldım. Filepath olarak Data dosyalarının default path’ini belirledim. Maximum dosya boyutu olarak 10 MB ve Maximum dosya sayısı olarak 1 belirledim. Siz kendi ihtiyaçlarınıza göre bu değerleri şekillendirebilirsiniz.

DECLARE @DatabaseName NVARCHAR(1000)
DECLARE @sqltext NVARCHAR(MAX)
DECLARE AuditCursor CURSOR FOR
SELECT name FROM sys.databases WHERE name NOT IN (SELECT name FROM sys.server_audits ) AND database_id > 4
OPEN AuditCursor
FETCH NEXT FROM AuditCursor INTO @DatabaseName
WHILE @@FETCH_STATUS=0
BEGIN
SET @sqltext=
'CREATE SERVER AUDIT '+ @DatabaseName +'
TO FILE 
(	FILEPATH = N''C:\Program Files\Microsoft SQL Server\MSSQL12.MSSQLSERVER\MSSQL\DATA''
	,MAXSIZE = 10 MB
	,MAX_FILES = 1
	,RESERVE_DISK_SPACE = OFF
)
WITH
(	QUEUE_DELAY = 1000
	,ON_FAILURE = CONTINUE
)'

EXEC sp_executesql @sqltext

SET @sqltext=
'USE [' + @DatabaseName +'] 
CREATE DATABASE AUDIT SPECIFICATION ['+ @DatabaseName +'] FOR SERVER AUDIT [' + @DatabaseName + ']'

EXEC sp_executesql @sqltext

SET @sqltext=

'USE [' + @DatabaseName +'] 
DECLARE @AuditScript TABLE (ID INT IDENTITY,AuditScript NVARCHAR(MAX))
DECLARE @ID INT=1
DECLARE @sqltext NVARCHAR(MAX)
INSERT @AuditScript
 
SELECT ''ALTER DATABASE AUDIT SPECIFICATION ['' + DB_NAME() + ''] ADD (UPDATE ON DATABASE::['' + DB_NAME() + ''] BY [''+ name + ''])'' 
FROM sys.database_principals 
WHERE type=''S'' AND name NOT IN (''guest'',''INFORMATION_SCHEMA'',''sys'')

UNION ALL

SELECT ''ALTER DATABASE AUDIT SPECIFICATION ['' + DB_NAME() + ''] ADD (DELETE ON DATABASE::['' + DB_NAME() + ''] BY [''+ name +''])'' 
FROM sys.database_principals 
WHERE type=''S'' AND name NOT IN (''guest'',''INFORMATION_SCHEMA'',''sys'')

WHILE @ID<=(SELECT COUNT(*) FROM @AuditScript)
BEGIN
SET @sqltext=(SELECT AuditScript FROM @AuditScript WHERE ID=@ID)
EXEC sp_executesql @sqltext
SET @ID=@ID +1
END

SET @sqltext=N''ALTER DATABASE AUDIT SPECIFICATION ''  + DB_NAME() + '' WITH (STATE=ON) ''
EXEC sp_executesql @sqltext
'

EXEC sp_executesql @sqltext

SET @sqltext='ALTER SERVER AUDIT [' + @DatabaseName + ']  WITH (STATE=ON)'
EXEC sp_executesql @sqltext

FETCH NEXT FROM AuditCursor INTO @DatabaseName
END
CLOSE AuditCursor
DEALLOCATE AuditCursor

 

SQL Server Nedir?

SQL Server Microsoft’un çıkarmış olduğu ilişkisel bir veritabanı yönetim sistemidir(RDBMS).  “http://www.veritabani.gen.tr/” adresinde MSSQL sekmesinde SQL Server ile ilgili geniş bir makale serisini bulabilirsiniz.

 

1988 yılında Microsoft, Ashton-Tate ve Sybase’e katılarak 1 yıl sonra SQL Server’ın ilk sürümünü IBM OS/2 için çıkardı.

 

SQL Server, ilk olarak 4.21 versiyonu ile NT sistemleri desteklese de, NT sistemler için dizayn edilen ilk SQL Server versiyonu ise 6.0

 

Microsoft’un 1993 yılında Windows NT ‘yi çıkarmasıyla Sybase ve SQL Server yollarını ayırdı.

 

SQL Server 7.0 sürümünde Sybase engine’inde büyük değişiklikler yapıldı.

 

SQL Server 2000’de de engine’de büyük değişimler oldu. SQL Server 2005’te ise SQL Server engine’in Sybase’den kalan kodu tamamen yeniden yazılmış oldu.

 

SQL Server Sürümleri ve bu sürümlerde gelen yeni özellikler için “SQL Server Sürümleri ve Her Sürümde Gelen Yenilikler” isimli makaleyi kesinlikle okumanızı tavsiye ederim. Bu makalede her sürümde gelen yenilikleri çok detaylı bir şekilde bulabilirsiniz. Bu makale şu ana kadar yazdığım en güzel ve detaylı makale olabilir.

 

 

Aşağıdaki tabloda sql server sürümlerinin geçmişini bulabilirsiniz.

SQL Server Geçmişi

Versiyon

Yıl

SQL Server Sürümü

Kod İsmi

1.0 (OS/2)

1989

SQL Server 1.0 (16-bit)

Filipi

1.1 (OS/2)

1991

SQL Server 1.1 (16-bit)

Pietro

4.2A (OS/2)

1992

SQL Server 4.2A (16-bit)

 

4.2B (OS/2)

1993

SQL Server 4.2B (16-bit)

 

4.21a (WinNT)

1993

SQL Server 4.21a

SQLNT

6.0

1995

SQL Server 6.0

SQL95

42861

1996

SQL Server 6.5

Hydra

7.0

1998

SQL Server 7.0

Sphinx

8.0

2000

SQL Server 2000

Shiloh

8.0

2003

SQL Server 2000 64-bit Edition

Liberty

9.0

2005

SQL Server 2005

Yukon

10.0

2008

SQL Server 2008

Katmai

10.50

2010

SQL Server 2008 R2

Kilimanjaro (aka KJ)

11.0

2012

SQL Server 2012

Denali

12.0

2014

SQL Server 2014

Hekaton

13.0

2016

SQL Server 2016

 

14.0

2017

SQL Server 2017

Helsinki

 

Benim ilk kullandığım SQL Server sürümü SQL Server 2000. Onun öncesinde SQL Server’ın emekleme döneminde olduğunu söyleyebilirim. Hatta Microsoft ilk olarak SQL Server 2005 sürümü ile beraber ciddi anlamda diğer ilişkisel veritabanlarıyla rekabet etmeye başladı. Ama benim gördüğüm kadarıyla IT sektöründeki genel kanıya göre 2005 öncesindeki sürümlerde güçlü bir ilişkisel veritabanı olarak sayılmıyordu.

 

SQL Server kötü imajını 2005 ile beraber düzeltmeye başlasa da tam olarak bu yıllar içersinde bu kötü imajı yıktığını söyleyemeyiz. Benim fikrime göre SQL Server 2008 ile beraber artık gerçekten ciddi anlamda diğer ilişkisel veritabanı sistemleri ile rekabet etmeye başladı.

 

SQL Server 2012 ile de Always On’u bize tanıtmasıyla artık küçük ve orta ölçekli sistemlerin vazgeçilmezi ve büyük sistemlerde de güzel bir alternatif olduğunu düşünüyorum. Tabi SQL Server 2008 ile de büyük sistemlerde kullanılıyordu fakat bence SQL tam anlamıyla kendini 2012’de buldu.

 

SQL Server ve Diğer İlişkisel Veritabanı Yönetim Sistemleri

Makalenin bundan sonraki kısmında kendi tecrübelerimle ilişkisel veritabanının ne olduğundan ve SQL Server’ın diğer ilişkisel veritabanlarına göre nerede durduğundan bahsedeceğim.

 

İlişkisel veritabanı, verilerin tablo yapısında tutulduğu ve bu tabloların bazı anahtarlar ile birbiri ile bağlantılı yapıda olduğu bir veritabanı modelidir. Bu anahtarlar yardımı ile birbirinden farklı tabloları birbirleri ile ilişkilendirerek büyük verileri parçalara bölebiliriz. Bu konunun detaylarını “Normalizasyon Kavramı” isimli makalede bulabilirsiniz.

 

 

İlişkisel veritabanı sistemleri genel olarak kurumsal uygulamalarda, web uygulamalarında, masa üstü uygulamalarda kullanılırlar. Bilinen en popüler ilişkisel veritabanı sistemlerini(RDBMS) aşağıdaki gibi sıralayabiliriz.

 

  1. Oracle
  2. SQL Server
  3. PostgreSQL
  4. DB2
  5. MySQL

 

 

 

Makalenin bu kısmından sonra söyleyeceklerim tamamen kendi fikirlerimdir. Objektif olduğuna inanan 10 yıl tecrübeye sahip bir SQL Server veritabanı yöneticisinin özgür düşüncüleri diyebilirsiniz. 🙂

 

 

Çalıştığım kurumlarda genellikle Oracle ve SQL Server bulunuyordu. Bir çok kurumda da genellikle sistemler gördüğüm kadarıyla bu şekilde.

 

  1. Oracle muhtemelen veritabanı yönetim sistemlerinin en iyisi. Benim en beğendiğim özellikleri ASM Teknolojisi, RAC yapısı, FlashBack Teknolojisi, Online Resize işlemleri. Bu konularla ilgili makalelere sitemizdeki ORACLE bölümünden ulaşabilirsiniz. Spesifik arama yapmak için de Arama kısmını kullanabilirsiniz.

  2. SQL Server: Türkiye’de var olan mevcut veritabanı ihtiyacının en az %99’unu performanslı bir şekilde çalıştırabilecek çok güçlü bir veritabanı yönetim sistemidir. Bunu söylememin sebebi SQL Server’ın lisans maliyetinin Oracle’a göre bir hayli uygun olması. Daha ucuz, ihtiyacınızı karşılayabilecek kadar iyi ve güçlü bir support’u olan bir veritabanı yönetim sistemi olsun diyorsanız SQL Server’ı tercih edebilirsiniz.

    Oracle’daki gibi bir ASM teknolojisi, RAC yapısı ya da FlashBack teknolojisine sahip olmasada bir çok özelliğine sahiptir. Ve veritabanı ve altyapısı düzgün dizayn edilirse bankacılık sistemleri gibi yoğun işlem gören sistemlerde yüksek performans elde edilebilir. Bir çok bankacılık sistemi veritabanı sistemi olarak şu anda SQL Server kullanmaktadır.

  3. PostgreSQL: Çoğu PostgreSQL uzmanı fanatiktir. Genellikle PostgreSQL’i ORACLE ile kıyaslarlar ve PostgreSQL’in Oracle’dan çok daha iyi olduğunu düşünürler. Hatta bir süre bu insanlarla konuşursanız sizde öyle düşünebilirsiniz.

    Ben büyük sistemlerde PostgreSQL’i kullanmadım ama kullanan sistemleri araştırdım ve bu sistemin yöneticileri ile bir çok kez konuşup bilgi alış verişinde bulundum. Benim fikrime göre PostgreSQL’de SQL Server gibi Türkiyedeki ihtiyacın büyük bir bölümünü karşılayabilecek güçte bir veritabanı yönetim sistemi.

    En büyük avantajı lisans maliyetinin olmaması. En büyük dezavantajı ise Oracle ve SQL Server’ın sahip olduğu gibi bir support mekanizmasının ve yeterli sayıda veritabanı uzmanının olmaması.

    Sitemizin PostgreSQL kısmında ilgili makaleleri bulabilirsiniz.

  4. DB2: Bu veritabanı yönetim sistemi ile de hiç çalışmadım. Sadece bir bankacılık sisteminde yapılan POC çalışmasında çok performanslı bir şekilde çalıştığına şahit oldum. Ayrıca dünya çapında bir çok kurum da büyük sistemlerin DB2 ile çalıştığını size söyleyebilirim.

  5. MySQL: En çok kullanılan veritabanı yönetim sistemleri arasında dünya çapında ilk sıralarda yer alıyor. Ama genellikle küçük sistemlerde yoğun olarak kullanıldığını gördüm.

 

Aşağıdaki site ilişkisel veritabanların kullanım oranları hakkında belki bir fikir verebilir.

 

https://db-engines.com/en/ranking

SQL Server Veritabanı Yöneticisinin Yol Haritası

Bu makalede sql server veritabanı yöneticisinin yapması gereken işlemleri madde madde belirterek her maddenin nasıl yapıldığıyla ilgili makalelere link vereceğim. Bu şekilde yeni veritabanı yöneticisi adayları için bir rehber olmasını hedefliyorum.

  1. İşletim Sistemi Logları ve SQL Server logları her gün kontrol edilmeli ve sıradışı bir hata varsa müdahale edilmelidir. “İşletim Sistemi ve SQL Server Log’larını Kontrol Etmek” isimli makalede detayları bulabilirsiniz.
     
  2. Schedule edilmiş jobların doğru çalışıp çalışmadığı kontrol edilmelidir. Job’lar hata alırsa veritabanı yöneticilerine mail atacak şekilde konfigüre edilmelidir. “Hatalı Biten Job’ları Mail Attırmak” isimli makaleyi okumak isteyebilirsiniz.
     
  3. Backuplar sorunsuz bir şekilde alınmış mı kontrol edilmelidir. Backup’ların doğru alınıp alınmadığını kontrol edip veritabanı yöneticilerine mail atacak script job olarak tanımlanmalıdır. “Yedeği Alınmamış Veritabanlarının Mail ile Bildirilmesi” isimli makaleden faydalanabilirsiniz.
     
  4. Backuplar mutlaka farklı bir lokasyona alınmalı ya da alındıktan sonra taşınmalıdır. Çünkü sunucu erişilemez bir hale gelirse backup’larınıza farklı bir kaynak üzerinden ulaşıp yeni bir ortama restore işlemi yapabilmeniz gerekir. 
     
  5. Acil durumlarda hızlıca backuptan dönebilmek için mutlaka bir geri dönüş planı hazırlanmalıdır ve mutlaka ay da en az 1 kere geri dönüş testi yapılmalıdır. Backup ve Restore hakkında detaylı bilgi için sitemizdeki arama kısmında Backup ya da Restore ifadeleriyle ilgili makaleleri aratabilirsiniz.
     
  6. Veritabanının yer sıkıntısı yaşamaması için diskler düzenli olarak kontrol edilmelidir. Hatta disklerin doluluk oranını kontrol eden bir script’i düzenli olarak dba’lere mail atacak bir job schedule edilmelidir. İlgili script’e “Disklerdeki Boş Alanların Veritabanı Yöneticilerine Mail ile Bildirilmesi” isimli makaleden ulaşabilirsiniz.
     
  7. Gün boyunca sistem monitör edilerek performans kontrol edilmelidir. Birbirini lock’layan sorgular  ya da uzun süren sorgular var mı incelenmelidir. Anlık sorguları izleyebilmek için “SQL Server’a gelen anlık sorguları çeşitli filtrelerle listelemek” isimli makaleyi, veritabanında yavaşlık talebiyle size gelindiğinde sadece ilgili veritabanı için uzun süren sorguları izlemek için de “SQL Server Profiler Kullanarak Uzun Süren Sorguları Bulmak ve Tablo Olarak Kaydetmek”  ya da “Extended Events Kullanarak Performans Monitoring Yapmak” isimli makalelerden okuyabilirsiniz.
     
  8. Potansiyel problemler için alert oluşturulmalı ve gerektiğinde soruna anında müdahale edilebilmesi için veritabanı yöneticilerine mail gidecek şekilde sistem konfigüre edilmelidir. Gerekli alertleri oluşturabilmek için “Yeni Kurulumda Yapılması Gereken Konfigürasyonlar” isimli makalemde belirttiğim script’i çalıştırabilirsiniz. Sitemizin Arama kısmına alert yazarsanız alert’ler ile ilgili diğer makalelere de erişebilirsiniz.
     
  9. Veritabanı kullanım amacına ve ihtiyaçlara uygun özelliklerde yaratılmalıdır. Veritabanı oluşturmak sağ tık değildir. Doğru veritabanı dizayn’ı için “Veritabanı Oluşturmak Deyip Geçmeyin!” isimli makaleyi okumanızı tavsiye ederim.
     
  10. Üretim ortamını upgrade etmeden önce, test ortamında bu işlem gerçekleştirilmelidir. Upgrade sonrası mutlaka uygulamaların doğru çalıştığından emin olunmalıdır. Ben upgrade işlemlerini genelde yeni bir instance kurarak yaparım. Kurduğum yeni instance’a veritabanlarını teker teker aktararak önce testlerini gerçekleştiririm. Bu şekilde, testler’de bir problem meydana gelirse hızlı bir şekilde eski instance üzerindeki veritabanını ayağa kaldırarak riskleri minimum’a indirgerim. Herkesin böyle bir  şansı olmayabilir. Eğer böyle bir şansınız yoksa mutlaka kendinize bir geri dönüş senaryosu hazırlamalı ve bu senaryoyu test etmelisiniz. Yeni kurulumla ilgili detaylı bilgi almak için “SQL Server Kurulumu” isimli makaleden faydalanabilirsiniz.
     
  11. Veritabanı sunucuları fiziksel olarak güvenli bir ortamda tutulmalıdır. Sunucuların rack server olmasını tavsiye ederim. Çünkü blade sunucularda bir problem olduğunda(ki birkaç kez problem olduğunu gördüm) high availability(yüksek erişilebilirlik) bir işe yaramıyor.
     
  12. Veritabanı sistemlerinizde mutlaka HA(High Availaiblity/Yüksek Erişilebilirlik) çözümlerinden birini kullanın. Bu şekilde beklenmedik sunucu hatalarının, disk hatalarının önüne geçebilirsiniz. Ayrıca sistemlerinizde yapacağınız upgrade yada sunucu bakım işlemlerini kesinti olmadan yapabilirsiniz. Ben always on’u tercih ve tavsiye ederim. HA(High Availaiblity/Yüksek Erişilebilirlik) çözümleri hakkında detaylı bilgi almak için sitemizde MSSQL menüsünden HA(YÜKSEK ERİŞİLEBİLİRLİK) & DR(FELAKET KURTARMA) sekmesine tıklayarak ilgili makalelere erişebilirsiniz. Özellikle ilk defa bu çözümleri öğreneceksiniz ilk etapta karşılaştırma makalesi olan “SQL Server Failover Cluster, Database Mirroring, Always ON,Replication ve Log Shipping Farkları” isimli makaleyi okumanızı tavsiye ederim.
     
  13. Veritabanı sunucuları ve uygulama sunucuları aynı vlan’da olmamalıdır! Aynı Vlan’da olursa uygulama sunucuları ile arasında port kısıtlaması yapılamaz. Bu yüzden güvenli olmayacaktır.
     
  14. Veritabanı sunucuları ve uygulama sunucuları arasında mutlaka firewall olmalıdır. Bu firewall üzerinden sadece gerekli portlar’a izin verilmelidir. Bütün network trafiği açık olmamalıdır. Örneğin veritabanı sunucusu 1433 portun’dan hizmet veriyorsa, uygulama sunucusu veritabanı sunucusuna sadece 1433 portundan erişebilmelidir.
     
  15. Veritabanına ulaşan sysadmin sayısı minimize edilmelidir. Yetkilerle ilgili detaylı sonuçları veren script’e “SQL Server’da Tüm Yetkilendirmeleri Listelemek” isimli makaleden ulaşabilirsiniz.
     
  16. Kullanıcılara sadece ihtiyaçları kadar yetki verilmelidir. Eğer uygulama sadece read,write ve execute yapacaksa db_owner hakkı verilmemelidir. Çünkü db_owner olan biri aynı zamanda backup’ta alabilir. Backup’ı alan uygulamacı hangi diskte ne kadar yer olmadığını bilmediği için sisteminizi çökertebilir. Bu konuyla ilgili “Loginlerin Owner Oldukları Veritabanında Backup Almasını Engellemek” isimli makaleyi okuyabilirsiniz.
     
  17. Kullanıcıların veriye direk ulaşmasına izin vermek yerine, mümkünse stored procedure veya view gibi nesneler üzerinden yetkilendirmek daha sağlıklı olacaktır. Stored Procedure ve view’ler ile ilgili sitemizde detaylı bilgiler bulabilirsiniz. Arama kısmına anahtar kelimeleri(Stored Procedure, View, Indexed View vb.) yazarak erişebilirsiniz.
     
  18. Tüm veritabanı kullanıcıları için güçlü şifre kullanma kriterleri oluşturulmalıdır. Windows üzerindeki policy’lerle güçlü şifre kullanımı garanti altına alınmalıdır. “secpol.msc(Security Policy SQL Server Ayarları)“, “SQL Server Parola Politikası” ve “SQL Server Kullanıcı Locklama Politikası” isimli makalelerimde detaylı bilgiye ulaşabilirsiniz.
     
  19. Uzun süredir login olmayan kullanıcılar sahibiyle irtibatlı bir şekilde silinmelidir. Logon Trigger kullanarak sql server’a bağlanan kullanıcıları bir tabloya aktaracak bir job oluşturabilirsiniz. “SQL Server Trigger Çeşitleri” isimli makalemde bu işlemin nasıl yapılacağını detaylı olarak açıkladım.
     
  20. Veritabanı sunucusu kesinlikle internete açık olmamalıdır! Bu en temel güvenlik prensibidir ve olmazsa olmazdır.
     
  21. Veritabanı sunucusuna lisanslı bir virüs programı yüklenmelidir. Virüs programına veritabanı dosyalarının olduğu path’ler için exception(virüs programı veritabanı file’larını izlememeli, diğer klasörleri izlemeli) tanımlanmalıdır. Eğer exception tanımlamazsanız veritabanınızın performansı yavaşlayacaktır.
     
  22. Periyodik olarak bakım işlemleri gerçekleştirilmelidir. Bakım işlemleri ile ilgili “SQL Server Maintenance(OLA HALLENGREN)” isimli makaleyi okuyabilirsiniz. Ayrıca sitemizin arama kısmına ve Maintenance Plan yazarak bakım işlemleri ile ilgili diğer makalelere erişebilirsiniz.
     
  23. Belirli aralıklarla instance üzerinde cpu’yu ve disk’i en çok kullanan sorgular tespit edilmeli ve gerekli iyileştirmeler yapılmalıdır. “CPU’yu En Çok Kullanan Sorgular” ve “Disk’i En Çok Kullanan Sorgular” isimli makalelerimden ilgili sorgulara erişebilirsiniz.
     
  24. Sistemdeki eksik indexler belirli aralıklarla sorgulanmalı ve gerekirse oluşturulmalıdır. “Eksik Index’leri Tespit Etmek” isimli makaleden faydalanabilirsiniz.
     
  25. Kullanılmayan indexler ve tablolar uygulamacı ile irtibatlı bir şekilde kaldırılmalıdır. “Kullanılmayan Index’leri Tespit Etmek” ve “Kullanılmayan Tabloları Tespit Etmek” isimli makalelerden faydalanabilirsiniz.
     
  26. İhtiyaç fazlası indexler create edilmemelidir. Örneğin tabloda 4 kolon var ve 3 kolon için index oluşturulması isteniyor. Bu zaten tabloyu yeniden oluşturmakla aynı şey sayılır. Böyle bir index oluşturulmamalıdır. Ayrıca fazla sayıda index tanımlanmamalıdır. Fazla index tanımlanırsa tabloya gelen insert, update ve delete’ler yavaşlayabilir. Index tanımlamadan önce indexler hakkında detaylı bilgi almak için “SQL Server’da Index Kavramı ve Performansa Etkisi” ve “SQL Server’da İstatistik Kavramı ve Performansa Etkisi” isimli makaleleri okumanızı tavsiye ederim.
     
  27. Her tabloda mutlaka bir primary key tanımlanmalı ve bu primary key en çok kullanılan integer ve unique bir kolon üzerinde olmalıdır. Bu şekilde tanımlanmayan tablolar tespit edilip uygulamacıya bildirilmelidir. “Primary Key ve Foreign Key” ve “Primary Key ve Unique Constaint’in farkları” isimli makalelerden faydalanabilirsiniz.
     
  28. Kendini sürekli tekrar eden sorgular için Select’teki, where’deki, joinde’ki bütün kolonlar index üzerinde tanımlanabilir. Bu şekilde sorgu tablo üzerindeki gerçek dataya hiç erişmeden index üzerinden ihtiyacını karşılayarak I/O’yu azaltacak ve performansı artıracaktır. Bu tip index’lere covering index denir. Ayrıca ORDER BY, GROUP BY ifadelerine de bakmak gerekir.  Detaylar için aşağıdaki makaleleri okumanızı tavsiye ederim.

    SQL Server’da Index Kavramı ve Performansa Etkisi” isimli makaleden faydalanabilirsiniz.

    Index Oluştururken Sorgudaki Order By Yönüne Bakmak(ASC,DESC)

    Index Oluştururken JOIN Yapılan Kolonlara Dikkat Etmek

    Index Oluşturuken GROUP BY İfadesindeki Kolona Dikkat Etmek

  29. Tablolarda kolonların boyutlarını belirlerken büyüklüğüne dikkat edilmelidir. Gereğinden büyük boyutlar gereksiz I/O ‘ya sebep olacaktır. Doğru veri tipleri tablonun gereksiz büyümesini engelleyecektir. “SQL Server Veri Tipleri” isimli makaleden faydalanabilirsiniz.
     
  30. Query Hint’i uygulamadan önce yaptığınız işlemin istediğiniz sonucu verdiğinden emin olmanız gerekir. Çünkü query hint kullanarak SQL Server’ı normal davranışından uzaklaştırarak istediğiniz şekilde hareket etmeye zorlamış oluyorsunuz. Kullanılan query hint performansı artırabilir fakat azaltabilirde. Bu yüzden tam olarak sonuçlarını test etmeden query hint kullanılmamalıdır.

    Microsoft query hint’leri için şöyle bir uyarı veriyor:

    SQL Server genellikle en iyi execution plan’ı seçtiği için sadece son çare olarak query hint’leri kullanın.

    Query Hint’ler hakkında bilgi almak için “SQL Server Query Hint Kavramı ve Bazı Query Hint’ler” isimli makaleyi okumak isteyebilirsiniz.


  31. Uygulama, veritabanına transaction gönderme ihtiyacı hissettiğinde bu sql ‘i stored procedure içine yerleştirmek daha faydalıdır. “Sp(Stored Procedure) Nedir” isimli makaleyi okuyabilirsiniz. Bazen stored procedure’lerde parameter sniffing meydana gelir. Çözümü için “Parameter Sniffing” isimli makaleyi okuyabilirsiniz.
     
  32. UNION ifadesini kullanırken tekrar eden kayıt olup olmadığına bakılmalıdır. Çünkü UNION tekrar eden satırları tek satıra düşürür. Eğer sonuç kümesinde tekrar eden kayıtlar varsa ve uygulamanın tekrar eden kayıtlara ihtiyacı yoksa UNION kullanılabilir, aksi takdirde UNION ALL kullanmak gerekecektir. UNION ve UNION ALL ifadelerinin kullanımı ve detayları için “UNION ve UNION ALL” isimli makaleyi okumak isteyebilirsiniz.
     
  33. Select ifadesini kullanırken sadece ihtiyaç duyulan kolonlar çekilmelidir. Bazı uygulamacılar select * from tablo şeklinde bütün kolonları çekiyorlar ve bu gereksiz I/O ve performans kaybına yol açıyor.
     
  34. Select ifadesine ihtiyaca göre mutlaka where filtresi eklenmeli. Filtre eklendiğinde sadece ihtiyaç duyulan satırlar gelecek ve gereksiz I/O yapılmayacaktır. Ayrıca filtreli sorgulara index ekleyerek sorgunun gelme süresini minimuma indirebilirsiniz.
     
  35. Sorgularınızda Where ifadesini kullanırken “<>”, “!=”, “!>”, “!<“, “NOT IN”, “NOT LIKE” gibi olumsuz ifadeler mümkünse kullanılmamalıdır. Çünkü bu ifadelerle yazılmış bir sorgu index’i kullanmak yerine table scan’a sebep olabilir. Örneğin NOT IN yerine LEFT JOIN  yaparak, where koşulunda ikinci tablodan null olanlar gelsin diyebilirsiniz ya da !> yerine <= kullanabilirsiniz.
     
  36. SQL Server kurulumu sonrasında doğru konfigürasyonun yapılması gerekir. “Yeni Kurulumda Yapılması Gereken Konfigürasyonlar” isimli makaleyi okumak isteyebilirsiniz.
     
  37. Uygulama içersinde şifre girilmemesi ve uygulama kullanıcısı dışındaki kullanıcıları audit ile izleyebilmek için uygulama sunucularını login olarak tanımlayabilirsiniz. “Login olarak Server Tanımlamak” isimli makalede detayları bulabilirsiniz.
     
  38. Mutlaka uygulama kullanıcısı dışındaki kullanıcıları audit ile izlemelisiniz.”SQL Server Audit Oluşturmak” isimli makalede detayları bulabilirsiniz.
     
  39. Her veritabanı yöneticisi SSMS’e ya da veritabanı sunucusuna bağlanamadığında DAC ile veritabanına bağlanma yöntemini bilmelidir. “DAC(Dedicated Admin Connections)” isimli makalede detayları bulabilirsiniz.
     
  40. Her veritabanı yöneticisi zor durumlarda mutlaka cmd komut satırından sql server’a bağlanmayı bilmelidir. “SQL Server’a cmd komut satırını kullanarak bağlanmak” isimli makale ilginizi çekebilir.
     
  41. Always On kullanıyorsanız mutlaka alert sisteminiz olmalı. Always On ile ilgili alert kurulumu için “Always On Alert Sistemi” isimli makaleden faydalanabilirsiniz.
     
  42. Veritabanı oluştururken herhangi bir değişiklik yapmazsanız, veritabanınız kurulumda yaptığınız path’ler de oluşur. “Veritabanı oluşurken data ve log file’ın oluşacağı default path’leri değiştirmek” isimli makale ilginizi çekebilir.
     
  43. Veritabanının Recovery Model’i veritabanı yönetiminde kritik bir rol oynar. “Veritabanı Recovery Modelleri” ve “Veritabanı Recovery Model’ini Değiştirmek” isimli makaleleri okumak isteyebilirsiniz.
     

Aslında buradaki maddeler tabiki veritabanı yöneticisi olmak için yeterli değil. Ama başlangıç için iyi bir yol haritası olacağını düşündüm. Buradaki makaleleri okuduktan sonra sitemizdeki makaleleri sırayla takip etmenizi öneririm. Sitemizdeki tüm makaleler büyük sistemlerde karşınıza çıkan ya  da çıkabilecek senaryolardan oluşmaktadır.

Veritabanında Aradığınız Kolonu ve İçeriği Bulmak

Bazen bir kolon adının veritabanındaki hangi tabloda olduğunu öğrenmek isteyebilirsiniz. Tek tek tabloların kolonlarına bakmak yerine aşağıdaki script’lerden birini kullanabilirsiniz.

select table_name AS [Tablo Adı], Column_name AS [Kolon İsmi] from Information_Schema.Columns 
where Column_Name like '%Aradığınız Kolon İsmi%'

 

Select distinct object_name(object_id) AS [Tablo Adı], name AS [Kolon İsmi] from sys.columns 
where name like '%Aradığınız Kolon İsmi%'

 

Yada veritabanında şu ifade hangi tabloda geçiyor sorusunun cevabını almak isteyebilirsiniz. Bunun için de aşağıdaki stored procedure’ü kullanabilirsiniz. “SizinVeritabanıİsminiz” yazan yere kendi veritabanı adınız yazmalısınız.

USE [SizinVeritabanıİsminiz]
GO
CREATE PROC [dbo].[TumTablolardaAra]
(
@Aranacak nvarchar(100)
)
AS
BEGIN
CREATE TABLE #Sonuc (ColumnName nvarchar(370), ColumnValue nvarchar(3630))
SET NOCOUNT ON
DECLARE @TabloIsmi nvarchar(256), @KolonIsmi nvarchar(128), @Aranacak2 nvarchar(110)
SET @TabloIsmi =''
SET @Aranacak2 = QUOTENAME('%' + @Aranacak + '%','''')
WHILE @TabloIsmi IS NOT NULL
BEGIN
SET @KolonIsmi = ''
SET @TabloIsmi = ( SELECT MIN(QUOTENAME(TABLE_SCHEMA) + '.' + QUOTENAME(TABLE_NAME))
FROM INFORMATION_SCHEMA.TABLES
WHERE TABLE_TYPE = 'BASE TABLE'
AND QUOTENAME(TABLE_SCHEMA) + '.' + QUOTENAME(TABLE_NAME) > @TabloIsmi
AND OBJECTPROPERTY(
OBJECT_ID(
QUOTENAME(TABLE_SCHEMA) + '.' + QUOTENAME(TABLE_NAME)
), 'IsMSShipped' )
= 0
)
WHILE (@TabloIsmi IS NOT NULL) AND (@KolonIsmi IS NOT NULL)
BEGIN SET @KolonIsmi = ( SELECT MIN(QUOTENAME(COLUMN_NAME))
FROM INFORMATION_SCHEMA.COLUMNS
WHERE TABLE_SCHEMA = PARSENAME(@TabloIsmi, 2)
AND TABLE_NAME = PARSENAME(@TabloIsmi, 1)
AND DATA_TYPE IN ('char', 'varchar', 'nchar', 'nvarchar')
AND QUOTENAME(COLUMN_NAME) > @KolonIsmi )
IF @KolonIsmi IS NOT NULL
BEGIN
INSERT INTO #Sonuc EXEC ( 'SELECT ''' + @TabloIsmi + '.' + @KolonIsmi + ''', LEFT(' + @KolonIsmi + ', 3630)
FROM ' + @TabloIsmi + ' (NOLOCK) ' +
' WHERE ' + @KolonIsmi + ' LIKE ' + @Aranacak2 )
END
END
END
SELECT ColumnName AS [Tablo ve Kolon İsmi], ColumnValue AS [Kolon İçeriği] FROM #Sonuc
END

 

 

 

Stored procedure’ü oluşturduktan sonra aşağıdaki gibi sorgulamalısınız.  “SizinVeritabanıİsminiz” yazan yere kendi veritabanı adınız yazmalısınız. Büyük veritabanlarında bu sorguyu çalıştırırken kontrollü olmalısınız.

USE [SizinVeritabanıİsminiz]
GO
[dbo].[TumTablolardaAra] 'Burayaaracağınızkelimeyiyazmalısınız'

 

UNION ve UNION ALL

SQL Server’da birden fazla sonuç kümesini birleştirmemiz gerektiğinde UNION veya UNION ALL işlemleri kullanılır. Mesela internet satışları ile mağaza satışları farklı tablolarda olan bir veritabanı düşünelim. Toplam satışları listelemek için bu iki tablonun birleşimi gerekir. UNION ve UNION ALL operatörlerini kullanırken dikkat etmemiz gereken hususlar şu şekildedir.

 

  1. Bütün sonuç kümelerindeki sütun sayısı aynı olmalıdır.
  2. Sıra olarak birbirine karşılık gelen sütunların veri tipleri birbirleriyle uyumlu olmalıdır.

 

UNION ile UNION ALL arasındaki tek fark UNION ALL ifadesi iki sonuç kümelerini direk alt alta eklerken, UNION ifadesi aynı olan kayıtlardan sadece bir tanesini getirir. Eğer birleşim için kullanacağımız sonuç kümelerinde ortak kayıtlar yoksa UNION ile UNION ALL aynı sonucu getirir. Aralarındaki performans farkını makalenin sonunda açıklayacağız.

 

UNION ve UNION ALL ile ilgili örneklere geçelim.

 

Öncelikle 2 adet örnek tablo oluşturalım.

CREATE TABLE Deneme 
(ID INT IDENTITY,
 Ad NVARCHAR(20),
 Soyad NVARCHAR(50),
 Tarih DATE)

INSERT Deneme
VALUES ('Hakan','Gürbaşlar','2017-01-01'),('Nurullah','Çakır','2017-01-01'),('Faruk','Erdem','2017-01-01')

CREATE TABLE Deneme2 
(ID INT IDENTITY,
 Ad NVARCHAR(20),
 Soyad NVARCHAR(50),
 Tarih DATE)

INSERT Deneme2
VALUES ('Hakan','Gürbaşlar','2015-01-01'),('Nurullah','Çakır','2016-01-01'),('Faruk','Erdem','2017-01-01')

 

İlk olarak UNION ile UNION ALL arasındaki sonuç farkını görelim.

SELECT Ad,Soyad
FROM Deneme

UNION ALL

SELECT Ad,Soyad
FROM Deneme2

 

SELECT Ad,Soyad
FROM Deneme

UNION

SELECT Ad,Soyad
FROM Deneme2

 

 

Bu örnekte görüldüğü gibi UNION kullanımıyla tekrarlayan kayıtlar birer kez getirildi.

Farklı sayıda kolona sahip iki sonuç kümesini birbirine bağlamayı denediğimizde ise aşağıdaki gibi bir hata alırız.

 

SELECT Ad,Soyad,ID
FROM Deneme

UNION ALL

SELECT Ad,Soyad
FROM Deneme2

 

Sorguyu biraz değiştirelim. İlk sorguda Ad,Soyad ; ikinci sorguda Soyad,Ad sırasıyla getirelim. Veri tipleri aynı olduğu için UNION işleminde hata ile karşılaşmayacağız.

 

SELECT Ad,Soyad
FROM Deneme

UNION ALL

SELECT Soyad,Ad
FROM Deneme2

 

İlk sorguda Ad,Soyad,ID ; ikinci sorguda Ad,Soyad,Tarih alanlarını kullanarak UNION işlemini yaptığımızda ise veri tipi uyuşmazlığından kaynaklı bir hata alırız.

 

SELECT Ad,Soyad,ID
FROM Deneme

UNION ALL

SELECT Ad,Soyad,Tarih
FROM Deneme2

 

 

Tarih alanlarının sadece yıl kısımlarını alarak UNION işlemini yapalım.

 

SELECT Ad,Soyad,YEAR(Tarih)
FROM Deneme

UNION ALL

SELECT Ad,Soyad,YEAR(Tarih)
FROM Deneme2

 

İki sorguda ortak kayıt yoksa UNION ile UNION ALL aynı sonucu getirir demiştik. Peki bu iki sorgunun performans değerleri nasıl?

 

SELECT Ad,Soyad
FROM Deneme
WHERE Ad='Hakan'

UNION ALL

SELECT Ad,Soyad
FROM Deneme2
WHERE Ad='Nurullah'

---------------------------

SELECT Ad,Soyad
FROM Deneme
WHERE Ad='Hakan'

UNION 

SELECT Ad,Soyad
FROM Deneme2
WHERE Ad='Nurullah'

 

 

Yukarıdaki iki sorguda da ortak kayıt olmadığı için sonuç aynı olacaktır. Çalışma planlarını incelediğimizde UNION işleminde Distinct Sort işlemi yani tekrarlayan kayıtları temizleme işlemi yapıldığı için Sorgu maliyeti neredeyse 3 katına çıkıyor. Bu nedenle de ortak kayıtların olmadığına emin olduğumuz durumlarda mutlaka UNION ALL kullanmalıyız.