Stored Procedure – Tek Parametreyle Tek veya Tüm Kayıtları Seçme

Dışarıdan parametre alan bir Stored Procedure içerisinde parametreye göre bazen sadece o değere eşit olan kaydı bazen de tüm kayıtları getirmesini isteyebiliriz. Bu tür durumlarda tablodan seçim yapmadan önce parametrenin boş ve dolu olduğuna bakarız. Eğer dolu ise WHERE bölümüne kolon filtresi ekleriz boş ise herhangi bir kısıtlama eklemeyiz ki tüm tablo listelensin. Bu amaçla genellikel prosedür üzerinde seçmeli parametre tanımlanır.

CREATE PROCEDURE GetKategori(@KategoriId int=NULL)
AS
IF @KategoriId IS NULL
	SELECT * FROM Kategori
ELSE
	SELECT * FROM Kategori WHERE KategoriId=@KategoriId

Okumaya devam et

Tablodaki Satır Değişmiş mi ? (CHECKSUM ve timestamp)

SQL Server’da uygulamamız için kritik olan tablodaki bazı veya tüm alanların değişip değişmediğini öğrenmemiz gerektiğinde bunun için ya log, history gibi arşiv tabloları oluşturulur veya o satır değiştiği zaman o satır için tanımlı versiyon numarasını değiştiririz. Tarihçe tablolarını oluşturmamız hem değişiklik olup olmadığını hem de verilerin eski ve yeni değerlerini görmemize imkan tanır. Ancak değişiklik olup olmadığını anlamak için tarihçe tablosu ile ana tabloyu JOIN edip kolon seviyesinde fark olup olmadığına bakmamız gerekir. Bu da uğraştırıcı bir durum olduğu için sadece bu amaç için tarihçe tablosu oluşturmak mantıklı olmayabilir. SQL Server’in sunduğu CHECKSUM() fonksiyonu ve timestamp veri türü bu aşamada kolaylık sağmaktadır. Kontrol sayısı olarak türkçeleştirebileceğimiz CHECKSUM() fonksiyonu parametre olarak aldığı değer için bir hash değeri döndürür. Bu değer normal bir veri olabileceği gibi bir kolon veya kolonlar listesi de olabilir.
Okumaya devam et

SQL Server Single User ve Restricted User Arasındaki Fark

SQL Server’de sistem yöneticisi olarak sistem üzerinde kullanıcıları etkileyecek bir maintenance çalışma yapacağımız zaman o süre zarfında kullanıcıların işlem yapıp yapamayacaklarını dikkate almalıyız. Kullanıcı erişimlerini kısıtlamak için <>Restrict Access özelliği kullanılır.

Bu özellikle 3 seçenek sunar;
Multi User : Default değer olup veritabanına tüm kullanıcıların erişilebileceğini belirtir.
Single User : Aynı anda tek bir kullanıcının erişebileceği anlamına gelir. Bu herhangi bir kullanıcı olabilir. İlk önce kim giriş yaparsa oturumu o almış olur. Bu kullanıcı bağlantısı bitmeden başka kullanıcı o veritabanına erişemez. Bu seçeneği genellikle sistem yöneticisi kendi oturumunda kritik bir işlem yapacağı tercih eder.
Restricted User : Bu seçenek ise Single User’e benzerlik gösterse de tek kullanıcı için değil tüm db_owner, dbcreator ve sysadmin üyeleri için erişimi açık bırakır. Bunların dışındaki kullanıcılara database erişiminde bulunamazlar.
Okumaya devam et

SQL Deyimlerinin Yürütülme Sırası

T-SQL’de temel olarak veri arama, bulma ve işleme işlemleri gerçekleştirilir. En çok kullanılan yantümce hiç şüphesiz “SELECT” deyimidir. Peki SELECT ve onunla birlikte kullandığımız ifadeler hangi sırayla yürütülmektedir. SQLHacks’de denk geldiğim bu küçük bilgiyi paylaşmakta fayda görüyorum. Bir SELECT cümlesi yüzeysel olarak aşağıdaki formata sahiptir.
SELECT DISTINCT TOP (list)
FROM (LeftTable)
(join type) JOIN (RightTable)
ON (condition])
WHERE (condition)
GROUP BY (list)
WITH (CUBE | ROLLUP)
HAVING (condition)
ORDER BY (list)

SQL Server öncelikle FROM alanındaki kaynakları işler. Ardından kaynaklar üzerinde tanımlı koşulları çalıştırır. Varsa gruplama, özetleme işlemlerini uygular ve son olarak hangi alanlar istenmişse onları seçer.
Bu ifadeler için değerlendirilme, yürütülme sırası aşağıdaki gibidir;

  1. FROM (LeftTable – Sol Tablo)
  2. ON (condition – Şart, koşul)
  3. (join type) JOIN (RightTable – JOIN türü, Sağ tablo)
  4. WHERE (condition – Şart, koşul)
  5. GROUP BY (list – özetleme alanları)
  6. WITH (CUBE | ROLLUP)
  7. HAVING (condition – özetlenmiş alan filtreleri)
  8. SELECT
  9. DISTINCT
  10. ORDER BY (list – sıralama alanları)
  11. TOP (list – kayıt adeti)

Common Table Expression (CTE) Nedir, Ne Değildir ?

SQL Server 2005 ile birlikte sunulan CTE (Common Table Expression – Ortak Tablo İfadeleri), bir sorgunun yürütülmesi anında elde edilmiş geçici sonuçlar bir veya daha fazla kere kullanılmasını sağlayan ifadelerdir. CTE bir table veya view olmayıp sadece bir sorgu ifadesidir. Yani geçici ve kalıcı tablolar gibi herhangi bir veri içermezler. Bir CTE’nin basit yazım biçimi aşağıdaki gibidir;

WITH expression_name [ ( column_name [,...n] ) ]
AS
( CTE_query_definition )

CTE’ler WITH sözcüğüyle tanımlanır. CTE’lerin en önemli özelliği kendi kendini çağırabiliyor olması ve aynı sorgu içerisinden birden fazla çalıştırılabiliyor olmasıdır. Bu özelliğiyle CTE’ler daha çok recursive(Öz-yinelemeli) işlemler için geliştirilmiştir diyebiliriz. Örnek olarak hiyerarşik listeler için tercih edilir. Bu tür işlemler için geçici tablolar kullanılabiliyor olsa da CTE’ler daha iyi bir performans sağlar. En azından tablo okuma ve işlemler gibi herhangi bir log izi oluşturmaz.
CTE’ler table ve view yapılarından farklı olarak primary key, unique, not null, default. gibi constraint’ler desteklemez. Aslında olmayan birşeyden daha doğrusu sadece çağrıldıkları anda oluşan bir yapıdan bahsediyoruz.
CTE’ler yalnızca SELECT değil INSERT, UPDATE ve DELETE yapılarında da kullanılabilir.
Okumaya devam et

SQL Server Index Kullanım Bilgileri (sys.dm_db_index_usage_stats)

Veritabanı sistemlerinde index oluşturmak önemli bir performans adımıdır. Ancak her tablo üzerinde mutlaka index oluşturulmalı diye bir kural bulunmamaktadır. Önemli olan doğru tablo üzerinde doğru index’leri oluşturmaktır. Oluşturduğumuz indexler okumada hız kazandırabilir ancak yazmada gecikmeye neden olmaması için belli dönemlerde indexleri gözden geçirmede fayda vardır. İndexlerin kullanım bilgilerine sys.dm_db_index_usage_stats DMV’den erişebiliriz. Bu view, indexlerin ne zaman oluşturulduğunu, güncellendiğini, kaç defa scan veya seek edildiğini, sistemin veya kullanıcının ne zaman başvurduğunu döndürür. MSDN’den alınmış aşağıdaki script’i kullanarak atıl indexleri bulabiliriz.

SELECT  CAST(OBJECT_NAME(idx.OBJECT_ID) AS VARCHAR(30)) AS 'Object',
	CAST(idx.name AS VARCHAR(50)) AS 'Index',
	idx.index_id AS 'Id',
	CAST(idx.type_desc AS VARCHAR(20)) AS 'Type',
	CAST(col.index_columns AS VARCHAR(180)) AS 'Columns'
FROM sys.indexes idx  LEFT outer join sys.dm_db_index_usage_stats usg
					  ON usg.OBJECT_ID=idx.OBJECT_ID and idx.index_id=usg.index_id
					   and usg.database_id = DB_ID()
	  LEFT outer join
			(SELECT DISTINCT OBJECT_ID, index_id,
			STUFF((SELECT   ','+COL_NAME(OBJECT_ID,column_id ) AS 'data()'
				FROM sys.index_columns idx_col2
				WHERE idx_col1.OBJECT_ID = idx_col2.OBJECT_ID
				and idx_col1.index_id = idx_col2.index_id FOR XML PATH ('')),1,1,'')
			AS 'index_columns' FROM  sys.index_columns idx_col1  ) col ON
			col.index_id = idx.index_id and col.OBJECT_ID = idx.OBJECT_ID
WHERE OBJECTPROPERTY(idx.OBJECT_ID, 'IsIndexable') = 1
and usg.index_id IS null and idx.type_desc not in ('heap','clustered')

Örneğin ay sonlarında bu scripti çalıştırarak o dönemde hiç kullanılmamış indexleri bulup DROP etmekte fayda var.
Aynı şekilde bu DMV’yi kullanarak tablo ve onlara bağlı index’lerin kullanım bilgilerini izleyebiliriz. Aşağıdaki script tablo / index lerin kaç defa yazıldığını ve okunduğunu listelemektedir.

SELECT CAST(OBJECT_NAME(usg.OBJECT_ID) AS VARCHAR(30)) AS 'Table',
       CAST(idx.name AS VARCHAR(30)) AS 'Index',
       usg.user_seeks + usg.user_scans + usg.user_lookups AS 'Reads',
       usg.user_updates AS 'Writes'
FROM sys.dm_db_index_usage_stats AS usg
INNER join sys.indexes AS idx
ON usg.OBJECT_ID = idx.OBJECT_ID
and idx.index_id = usg.index_id
WHERE OBJECTPROPERTY(usg.OBJECT_ID,'isusertable') = 1
ORDER BY 'Table';

SQL Server Page Split Nedir ?

SQL Server’de hem performans tarafında hem de index düzenleme tarafında dikkat edilmesi konulardan biri Page Split işlemidir. Sayfa bölümlendirme olarak tanımlanan bu işlem canlı sistemlerde bazen performans sorununa neden olabilmektedir. Peki Page Split nedir ? Bilindiği gibi SQL Server’in dosya tabanında Page denen 8KB’lık alanlar mevcuttur ve bunlardan 8 tanesi (8*8K=64K) bir extenti oluşturur. Data ve Index verileri page’lerde tutulur ve okuma/yazma işlemleri extent bazında gerçekleşir. Her page’de kaç satırın bulunacağı satırın uzunluğuna bağlı olarak değişebilir. Eğer uzun bir row gelecek olursa veya mevcut row çok uzun bir veriyle güncellenecek olursa SQL Server değişikliği yapmak için mevcut satırların yerini değiştirebilir eğer değişiklik sayfaya sığmıyorsa SQL Server yeni bir sayfa (data page) oluşturup satırları buraya taşır. Bu şekilde öndeki veya sonraki sayfada öteleme işlemleri yapmak zorunda kalır. Bu işleme page split denilir. Sayfaların ne kadar sıklıkla dolacağı ve bölüneceği Fill Factor denen değerle doğrudan ilişkilidir. Bu değer, sayfaların ne kadarlık kısmının dolu olacağını belirtir. Örneğin fillfactor değerini %80 olarak set ettiğimizde bu sayfanın %20’lik kısmı sonradan eklenecek veriler için boş bırakılacaktır. Eğer okuma amaçlı yani az ekleme/güncelleme yapılacan bir veritabanı üzerinde çalışıyorsak doluluk oranının %100’e yakın tutmamız performans artıracaktır. Çünkü daha az page taranmış olacaktır. Eğer yazma işlemleri yoğun yapılıyorsa bu değer yüksekse Page Split işlemi sık yapılmak zorunda kalabilir. Bu da yazma esnasında sisteme zaman kaybettirecektir. Aynı şekilde verilerin bölümlenmesi daha fazla disk yüzeyine yayılmaya neden olduğundan okuma esnasında da performans sorunu yaşanabilir. Aşağıdaki gibi tbDeneme tablosu oluşturalım.
Okumaya devam et

SQL Server I/O Performansı ve Darboğazları Gözleme

Yazma, okuma işlemlerinde aygıtlar içerisinde en yavaşı olan disk, veritabanı yönetim sistemlerinde her zaman en önemli konulardan biri olmuştur. Bir VTYS’nin disk seçimi array konfigürasyonunun, nasıl olacağı o veritabanının kullanım amacına bağlıdır. Yani sözkonusu veritabanı daha çok yazma mı yoksa okuma için mi kullanılacak bunun netleştirilmesi gerekir. Veritabanı motorlarının en çok yaptığı işlemlerden biri çalışma esnasında database page’leri taşımasıdır. Bu da önemli bir I/O trafiğine neden olmaktadır. Örneğin en basiyi bir güncelleme yapılacağı zaman ilgili alanlar, veri sayfaları diskten belleğe taşır commit etmeden önce TEMPDB üzerinde ilgili sıralama ve güncellemeleri yapar. Yani hem okuma hem de yazma durumlarında I/O sistemleri kritik önem arzetmektedir. Bu trafikte en önemli sorun oluşacak darboğazlardır (I/O bottlenecks). Sistem üzerinde taleplerimizi gerçekleştirmeden önce execution plan’a bakmak ve ona göre I/O kaynak tüketimini tahim edip ardından takip etmekte fayda var. Performans sorunu olması sonucu kullanıcılara geç yanıt verilecektir. Bu durumda I/O tarafındaki darboğazları gözlemek için SQL Server’den beslenen çeşitli sayaçlar bulunmaktadır (performance counter). Bu yazıda çok kullanılan, bakılması tavsiye edilen sayaçları listeleyeceğiz.
Okumaya devam et

SQL Server Bekleyen İşler – sys.dm_os_waiting_tasks DMV

SQL Server özellikle yoğun ve taleplere yavaş yanıt verdiği durumlarda tam olarak durumu tespit etmek için çeşitli yöntemler bulunmaktadır. Bu yöntemlerden biri de sistem üzerindeki bloke durumları ve bekleme modunda işlemleri görmektir. Bu noktada SQL Server 2005 ile birlikte gelen sys.dm_os_waiting_tasks dynamic view nesnesi sistemde kaynakları bekleyen task’leri listeler. Kuyrukta bekleyen tüm işleri listeleyelim.
Okumaya devam et