Recent comments

None


İçerik Ara











Yasal Uyarı
Bu sitede sunulan tüm bilgi ve dökümanlar Turgay Sahtiyan tarafından yazılmaktadır. Yazıların kaynak göstermek şartıyla kullanılması serbesttir.

© Copyright 2009-2013
Takvim
<<  Ağustos 2017  >>
PaSaÇaPeCuCuPa
31123456
78910111213
14151617181920
21222324252627
28293031123
45678910
Keywords

Concat_Null_Yields_Null özelliği ile string birleştirmelerinde NULL ifadenin boş string olarak algılanması dolayısıyla da sonucun NULL gelmemesi için kullanılır.

[more]

Defualt olarak Concat_Null_Yields_Null özelliği ON durumdadır. Bu durumda string bir ifade ile NULL bir ifade birleştirildiğinde sonuç NULL olarak dönecektir. Örneğin Select ‘abc’+NULL ifadesinin sonucu NULL olacaktır.

Eğer Concat_Null_Yields_Null özelliği OFF yapılırsa yukarıdaki aynı örnek ‘abc’ sonucunu döndürecektir.

Şimdi bu 2 örneği SSMS’te gerçekleştirelim.

--CONCAT_NULL_YIELDS_NULL özelliği ON iken
--sonuç NULL olacaktır
SET CONCAT_NULL_YIELDS_NULL ON;
GO
SELECT 'abc' + NULL ;
GO

--CONCAT_NULL_YIELDS_NULL özelliği OFF iken
--sonuç 'abc' olacaktır
SET CONCAT_NULL_YIELDS_NULL OFF;
GO
SELECT 'abc' + NULL; 
GO

 

Son olarak önemli bir not düşerek yazıyı noktalayalım. SQL Server’ın ileriki versiyonlarında Concat_Null_Yields_Null özelliğinin sürekli ON yapılması gündemde. Ve yukarıdaki örneklerde olduğu gibi dışarıdan SET edildiği takdirde hata alıyor olacaktır. Bu yüzden geliştirme ortamlarında artık kullanılması tavsiye edilmemektedir.

 

İyi Çalışmalar

Turgay Sahtiyan

Not : Blog haricinde, faydali gördügüm yazilari ve linkleri twitter adresimden paylasiyorum. Beni twitter'da takip etmek için : twitter.com/turgaysahtiyan


turgay sahtiyan , 27. Ekim 2011, 08:00

Filtered Index, SQL Server 2008 ile gelen, optimize edilmiş bir nonclustered index’tir. Oluşturulurken kullanılan where anahtar kelimesi sayesinde index key’in bütün verilerini değil sadece alt kümesini içerir. İyi tanımlanmış bir Filtered Index performansı arttırabilir, bakım maliyetini düşürür, aynı zamanda filtered olduğu için diskte daha az yer kaplar.

Filtered Index’in sağladığı avantajları detaylı olarak analiz etmek gerekirse;

  • Filtered Index Sorgu Performansını Arttırır : Filtered Index normal Index’e oranla daha az data içerdiği için bu Index üzerinden yapılacak seek/scan işlemleri normal Index üzerinden yapılacak seek/scan işlemlerine oranla daha performanslı çalışacaktır. Ayrıca Filtered Index için otomatik olarak oluşacak olan istatistik te veriyi daha iyi temsil edeceğinden estimated rows daha iyi tahmin edilecek, dolayısıyla da Index’e erişim metodu daha iyi belirlenebilecektir.
  • Index Bakım Maliyetlerini Düşürür : Index fragmante olduğu zaman bakım yapılarak bu fragmantasyonun giderilmesi gerekir. (Detaylı bilgi için şu makaleyi inceleyebilirsiniz.) Index fragmantasyonu tabloda DML işlemleri olduğu zaman oluşur. Filtered Index normal NonClustered Index’e oranla daha az veri içerdiği için fragmante olma ihtimali daha azdır. Ayrıca fragmante olsa dahi bakım işlemi sırasında daha az data ile uğraşılacağı için bakım maliyeti her halukarda normal index’e oranla daha az olacaktır.
  • Disk Maliyetini Düşürür : Daha önceki maddelerde de belirttiğim gibi Filtered Index datanın tamamını içermediği için normal Index’e oranla daha az yer kaplar.

Teorik kısmı burada kesip Filtered Index’i kafamızda daha iyi canlandırmak amacıyla canlı bir örnek verelim. Örneğin tbl1 isimli tablonuzda bulunan col1 adlı kolona index tanımlaması yapıyorsunuz. Tablo toplamda 1000 kayıttan oluşuyor. Fakat bu 1000 kaydın 700’ü için col1 kolonunda NULL bilgisi bulunuyor. Siz Col1 üzerinden yaptığınız bütün aramalarda null olmayan bir değer ile arama yapıyorsunuz. Böyle bir senaryoda col1’in tüm değerleri için Index tanımlamak yerine NULL olmayan satırlar için Index tanımlamanız daha anlamlı olacaktır. Bu şekilde 1000 değerden oluşan bir Index yerine 300 değerden oluşan bir Index olacak, bunun neticesinde B-Tree küçülecek ve Index üzerinden yapılan aramalar daha performanslı olacaktır. Ayrıca Index bütün kayıtlar için değil sadece 300 kayıt için oluştulduğu için diskte daha az yer kaplayacak ve Index maliyeti de otomatikman düşecektir.

Şimdi yukarıda bahsettiğim örneği SQL Server’da gerçekleştirelim ve 2 Index arasındaki farklara bakalım.

Bunun için ilk olarak 1.000.000 satırdan oluşan bir tablo oluşturacağım ve 700.000 kaydın col1 kolonuna null değer atacağım. Kalan 300.000 kaydın col1 kolonunu NewID() fonksiyonundan gelen GUID değeri ile dolduracağım.

--Bir çalışma DB'si oluşturuyoruz.
create database DBFilterIndex
GO
use DBFilterIndex
GO
--Bir çalışma tablosu oluşturuyoruz.
create table tbl_FilterIndex (ID int Identity(1,1), col1 varchar(37))
GO
--col1 bilgisi NULL olan 700.000 kayıt insert ediyoruz.
insert tbl_FilterIndex
  select null
go 700000  
--col1 bilgisi NULL olmayan 300.000 kayıt insert ediyoruz.
insert tbl_FilterIndex
  select cast(NEWID() as varchar(37))
go 300000  

 

1.000.000 kayıttan oluşan çalışma tablomuz hazır. Şimdi Index’leri oluşturalım.

--ID kolonu üzerine Clustered Index oluşturuyoruz
create clustered index CIX on tbl_FilterIndex (ID)
GO
--col1 için normal bir NonClustered Index oluşturuyoruz
create nonclustered index IX_RegularIndex on tbl_FilterIndex (col1)
GO
--col1 için Filtered NonClustered Index oluşturuyoruz
create nonclustered index IX_FilterIndex on tbl_FilterIndex (col1)
	where col1 is not null
GO

 

Şimdi 2 Index’i birbiri ile karşılaştırabiliriz.

İlk olarak 2 index’in kayıt sayılarını ve boyutlarını karşılaştıralım.

SELECT i.index_id, i.name, i.type_desc, ps.reserved_page_count, ps.used_page_count, 
	ps.reserved_page_count*8 as Size_KB,
	ps.row_count, i.filter_definition 
FROM sys.dm_db_partition_stats ps
INNER JOIN sys.indexes i ON ps.object_id = i.object_id AND ps.index_id = i.index_id
WHERE ps.object_id = OBJECT_ID('tbl_FilterIndex')

 

1

Resimde de gördüğünüz üzere normal NonClustered Index 1.000.000 kayıttan oluşurken Filtered Index’te null olan kayıtlar bulundurulmadığı için 300.000 kayıttan oluşmakta. Bu yüzden normal index 22 MB iken Filtered Index 15 MB boyutunda. Disk açısından maliyetin nasıl düşürüldüğünü görmüş olduk.

Şimdi bir de performans karşılaştırması yapalım. Bu karşılaştırma için aynı sorguyu 2 farklı index’i force ederek yapacağım. Aynı zamanda farkı daha net görebilmnek adına Index’i scan edecek bir kriter gireceğim.

SET STATISTICS IO ON
--Normal NonClustered Index'i force ederek
select * from tbl_FilterIndex WITH (INDEX=IX_RegularIndex)
where col1=NEWID()
--Filtered Index'i force ederek
select * from tbl_FilterIndex WITH (INDEX=IX_FilterIndex)
where col1=NEWID()

 

IO karşılaştırmasına baktığımızda normal Index sorguyu tamamlamak için 2749 IO yaparken Filtered Index aynı sorguyu 1879 IO yaparak getirebilmekte.

2

Query Plan’ları karşılaştırarak maliyetlere bakacak olursak;

3

Resimde de görüldüğü üzere normal Index’in maliyeti 4 kat daha fazla. Bu örneklerle de Filtered Index’in performansa olan etkisini görmüş olduk.

Filtered Index’te desteklenen özelliklere bakacak olursak;

  • Filtered Index’in kriteri değiştirilebilir.
  • Missing Index DMV’leri Filtered Index önerisi toplamaz.
  • Database Engine Tuning Advisor “not null” Filtered Index önerisi sunabilir.
  • Filtered Index, online Index operasyonunu destekler. Yani Filtered Index’ler online olarak Rebuild edilebilirler.
  • Table Hint’ler Filtered Index tarafından desteklenir.

SQL Server 2008 ile beraber gelen Filtered Index özelliği Performance Tuning çalışmaları yapılırken göz önünde bulundurulması gereken güzel özelliklerden biri. Filtered Index sayesinde verinin alt kümesi için Index tanımlaması yapılarak performans artışı sağlanabilir.

Not : Blog haricinde, faydali gördügüm yazilari ve linkleri twitter adresimden paylasiyorum. Beni twitter'da takip etmek için : twitter.com/turgaysahtiyan


Daha önce duyurusunu yaptığım SQL Server Öncülülüğü topluluğunun tanıtım toplantısını 21.10.2011 tarihinde Microsoft İstanbul ofisinde gerçekleştirdik.

[more]

120 den fazla BT çalışanının katıldığı etkinlik, öğleden önce tek oturum öğleden sonra paralel oturumlar şeklinde devam etti.

Microsoft Ürün Grup Müdürü Necip Özyücel’in açılış konuşmasını yaptığı etkinlikte community liderleri katılımcılardan beklentilerini kısa cümleler ile aktardılar.

image

Ben öğleden sonra gerçekleştirilen paralel oturumlardan 14:00-15:00 aralığında “Index ve İstatistik : Performansınızı Arttırın” başlıklı sunumu gerçekleştirdim.

image

Yoğun bir katılımın olduğu bu oturumda Index ve İstatistik kavramlarını gerçek demolar yaparak detaylı olarak inceleme fırsatı bulduk.

image

image

Etkinlik bitiminde katılımcılar ile birebir görüşme fırsatım oldu. Bu görüşmelerde oldukça güzel feedback’ler aldım. Bunun için sunum yapan tüm arkadaşlara tekrar teşekkür etmek istiyorum. Aşağıda sunum yapan arkadaşlardan bazılarını görebilirsiniz. (Osman Çokakoğlu – Emrah Uslu – Mustafa Acungil – Turgay Sahtiyan – Serkan Bark)

image

Umarım ilk etkinliğimizde yakaladığımız bu sinerji daha sonraki etkinliklerimizde de gerçekleşir.

Katılan herkese tekrar teşekkürler.

Not : Blog haricinde, faydali gördügüm yazilari ve linkleri twitter adresimden paylasiyorum. Beni twitter'da takip etmek için : twitter.com/turgaysahtiyan


SQL Server’da yetkilendirmeler sunucu, veritabanı, nesne ve kolon seviyesinde yapılabilmektedir. Bu makalede kolon seviyesinde yetkilendirmenin nasıl yapıldığına bakıyor olacağız.

[more]

Şöyle bir ihtiyacımız olduğunu düşünelim. Veritabanında maaş bilgilerinin tutulduğu bir tablo olsun. Bu tabloyu görmeye yetkisi olan kişilerin tüm kolonları görmesini ama maaş bilgilerinin tutulduğu kolonları görmesini istemiyoruz. Böyle bir durumda kolon bazında yetkilendirme özelliğini kullanabiliriz.

Örnekleri AdventureWorks veritabanında bulunan Person.Contact tablosu üzerinde yapacağız. Yeni bir kullanıcı oluşturup bu kullanıcıya Person.Contact tablosu için select hakkı tanımlayıp daha sonra EMailAddress kolonunu görememesi için bu kolon için deny tanımlaması yapacağız.

Yeni bir kullanıcı tanımlıyoruz.

USE [master]
GO
CREATE LOGIN [UserPermission] WITH PASSWORD=N'u'
GO
USE [AdventureWorks]
GO
CREATE USER [UserPermission] FOR LOGIN [UserPermission]
GO

 

Bu kullanıcıyı Person.Contact tablosunu select çekecek şekilde yetkilendiriyoruz.

use [AdventureWorks]
GO
GRANT SELECT ON [Person].[Contact] TO [UserPermission]
GO

 

Ve son olarak EMailAddress kolonunu sorgulayamaması için bu kolona deny veriyoruz.

use [AdventureWorks]
GO
DENY SELECT ON [Person].[Contact] ([EmailAddress]) TO [UserPermission]
GO

 

Şimdi oluşturduğumuz bu kullanıcı ile bağlantı kurup EMailAddress kolonunu sorgulamaya çalışalım.

select EmailAddress from Person.Contact

 

Msg 230, Level 14, State 1, Line 1
The SELECT permission was denied on the column 'EmailAddress' of the object 'Contact", database 'AdventureWorks', schema 'Person'.

Aynı tablodan deny verilmemiş kolonları sorgulamak istersek herhangi bir hata mesajı almayacağız.

select FirstName,LastName from Person.Contact

 

Herhangi bir kolona deny verildiğinda artık select * şeklinde de sorgulamaya izin verilmemektedir.

select * from Person.Contact

 

Msg 230, Level 14, State 1, Line 1
The SELECT permission was denied on the column 'EmailAddress' of the object 'Contact", database 'AdventureWorks', schema 'Person'.

Yukarıda TSQL ile yaptığımız bu yetkilendirme işlemini SSMS kullanarak ta yapabiliriz. Bunun için yetkilendirme ekranında bulunan Object Permission butonunu kullanabiliriz.

ss3

Object Permission butonuna bastığımızda gelen ekranda deny vermek istediğimiz kolonları belirleyebiliriz.

ss4

 

İyi Çalışmalar

Turgay Sahtiyan

Not : Blog haricinde, faydali gördügüm yazilari ve linkleri twitter adresimden paylasiyorum. Beni twitter'da takip etmek için : twitter.com/turgaysahtiyan


2009 yılında yazmaya başladığım blog’um, içeriğin artması ile beraber her geçen gün daha fazla ziyaretçi almaya başladı. İlk günlerde günde maksimum 20-30 ziyaretçi giriş yaparken şu an çoğu community’den daha fazla ziyaretçi almaktayım :)

Aşağıda son ayın ziyaretçi sayısı bilgisini görebilirsiniz.

image

Ziyaret detaylarına baktığımda toplam sayfa gösterimi 19.000’e ulaşmış durumda.

image

Kişisel bir blog için hiç fena değil, değil mi? :)

Bundan sonraki hedefim ayda 20.000 ziyaret. Hep beraber bu değere en kısa sürede ulaşmak üzere :)

 

İyi çalışmalar

Turgay Sahtiyan

Not : Blog haricinde, faydali gördügüm yazilari ve linkleri twitter adresimden paylasiyorum. Beni twitter'da takip etmek için : twitter.com/turgaysahtiyan


2 hafta önce düzenlenen SQLPass etkinliğinde daha önce Denali kod adı ile bilinen SQL Server’ın bir sonraki versiyonu, SQL Server 2012 olarak lanse edildi.

Aşağıdaki link ile SQL Server 2012 Developer Training Kit’i kullanabilir, virtual lab’lar vasıtasıyla teknik içerikler üzerinde denemeler yapabilirsiniz.

http://www.microsoft.com/download/en/details.aspx?id=27721

Eğer Developer Training Kit’i download ederken bir problem ile karşılaşırsanız Web Platform Installer 3.0 uygulamasını kurup tekrar download etmeyi deneyebilirsiniz.

http://www.microsoft.com/web/downloads/platform.aspx

 

İyi çalışmalar

Turgay Sahtiyan

Not : Blog haricinde, faydali gördügüm yazilari ve linkleri twitter adresimden paylasiyorum. Beni twitter'da takip etmek için : twitter.com/turgaysahtiyan


Geçen hafta USA’de düzenlenen SQLPass etkinliğinde,Microsoft tarafından,daha önce Denali kod adı ile bilinen SQL Server’ın yeni versiyonun adının SQL Server 2012 olacağı açıklandı.

[more]

Açıklama geçen hafta olmasına rağmen şu sıralar zamanınımın çoğunu yarın düzenleyeceğimiz SQL Server Öncüleri lansmanına ayırdığım için bu konu hakkında yazma şansı ancak bulabildim.

SQL Server 2012’nin 2012 yılının ilk çeyreğinde release olması bekleniyor. En azından şu anda planlanan bu Smile Umarım gecikme olmaz ve AlwaysOn,Contained Database,Crescent ve şimdi sayamadığım onlarca yeni özelliğe en kısa zamanda kavuşuruz Smile

 

Son olarak SQL Server 2012 hakkında müşteri yorumlarının yer aldığı aşağıdaki videoyu sizinle paylaşarak yazıma son veriyorum.

 

 

SQL Server 2012 ile hedefi 12’den vurmak için görüşmek üzere Smile

 

İyi Çalışmalar

Turgay Sahtiyan

Not : Blog haricinde, faydali gördügüm yazilari ve linkleri twitter adresimden paylasiyorum. Beni twitter'da takip etmek için : twitter.com/turgaysahtiyan


21 Ekimde İstanbul Microsoft ofisinde düzenleyeceğimiz SQL Server Öncüleri Lansmanından geçen hafta duyurduğumuz Database Consolidation appliance için de bir oturum ayırdık.

Sabah oturumları boyunca SQL Server 2012, SQL Azure ve Database Consolidation Appliance gibi son gelişmeler ve vizyonumuz hakkında konuşacağız.

Ardından da İş Kritik Uygulamalar ve İş Zekası hakkında paralel oturumlarımızda derin teknik içerikli bilgileri paylaşacağız.

Sizleri de bekliyoruz. Kaydınızı hemen yaptırın : http://kayit.sqlserveronculeri.com/

image

Not : Blog haricinde, faydali gördügüm yazilari ve linkleri twitter adresimden paylasiyorum. Beni twitter'da takip etmek için : twitter.com/turgaysahtiyan


Bir önceki makalemde Estimated ve Actual Query Plan’ları nasıl görebileceğimiz üzerine konuşmuştuk. Bugünkü makalemde ise bu Query Plan’ları SQL Server Profiler ile otomatik olarak nasıl toplayabileceğimizi görüyor olacağız.

[more]

Daha önceki makalelerimde de değindiğim gibi Query Plan’lar sistem performansını analiz etmede ve çözüm bulmada kullanılan en önemli kaynaklardan biri. Bazı durumlarda gerçek sunucu üzerine gelen tüm Query Plan’ları analiz etmek gerekebilir. Böyle bir durumda SQL Server Profiler aracını kullanabiliriz.

Ayrıca SQL Server Profiler aracının bize sunduğu read ve cpu değerleri ilk aşamada hangi Query Plan’ların daha çok maliyetli olduğunu anlamamızda faydalı olmaktadır.

Bu makalemde SQL Server Profiler ile Query Plan’ların nasıl toplanacağına bakıyor olacağız.

Hemen SQL Server Profiler’ı açalım ve işlemlerimize başlayalım.

İlk olarak Event Selection  kısmında Query Plan’ları toplamak için Performance node’unun altında bulunan ShowPlan XML event’ini seçiyorum.

Ayrıca hangi Query’nin Query Plan’ı oluşturduğunu görmek adına aşağıdaki event’leri de seçmem de fayda var.

  • RPC: Completed
  • SQL: BatchCompleted
  • SQL: BatchStarting

Sonuç itibarıyla seçtiğim tüm event’ler aşağıdaki gibi.

1

ShowPlan XML event’ini seçtiğimiz anda üstteki resimde de göreceğiniz üzere Events Extraction Settings adında yeni bir tab açılacaktır. Bu tab vasıtasıyla toplanan Query Plan’larını tek bir dosyanın içine mi yoksa ayrı ayrı dosyalar içine mi atılacağını belirleyebiliriz. Ben bu örneğimde Query Plan’ları tek bir dosyanın içinde toplayacağım. Ayrıca gene bu ekranda bahsi geçen dosya ya da dosyaların nerede olacağını da belirleyebiliriz.

2

Tanımlamalar tamam. Run’a basıp trace işlemini başlatabiliriz.

Şimdi örnek bir sorgu çalıştıralım ve bu sorgunun SQL Server Profiler’a olan yansımasına bakalım.

select COUNT(*) from Person.Address where AddressID=15

 

3

SQL Server Profiler’dan ilgili sorgunun direk olarak Query Plan’ına bakabiliriz. Ayrıca Showplan XML satırında sağ tık yaptıktan sonra ilgili Query Plan’ı diske kaydedebiliriz.

4

 

İyi Çalışmalar

Turgay Sahtiyan

Not : Blog haricinde, faydali gördügüm yazilari ve linkleri twitter adresimden paylasiyorum. Beni twitter'da takip etmek için : twitter.com/turgaysahtiyan


Bugünkü yazımda Actual ve Estimated Query Planlarını Grafik,text ve XML olarak nasıl görüntüleyebileceğimizi görüyor olacağız.

[more]

Query Plan’ları Estimated(Tahmini) ve Actual (Gerçekleşen) olarak ikiye ayırabiliriz. Estimated Query Plan, sorguyu çalıştırmadan Query Optimizier tarafından hesaplanan en olası (cost-based) Query Plan’dır. Actual Query Plan ise sorgu çalıştırıldığında kullanılan gerçek Query Plan’dır.

Çoğu durumda Estimated ile Actual Query Plan birbirinin aynısı olur. Bazı istisnai durumlarda (istatistik değişimi gibi) Actual ile Estimated Query Plan farklılık gösterebilir.

Şimdi Query Plan’ları görmek için hangi seçeneklerimiz olduğuna bakalım.

Grafik Query Plan

Estimated Query Plan’ı CTRL+L tuş kombinasyonu ile görebiliriz. Ya da toolbox’tan “Display Estimated Execution Plan” butonuna basabiliriz.

Actual Query Plan için ise gene toolbox’tan “Include Actual Execution Plan” butonunu ya da CTRL+M tuş kombinasyonunu kullanabiliriz.

Her 2 Query Plan’ın da örnek görüntüsü aşağıdaki gibi olacaktır.

image

Text Query Plan

Actual ve Estimated Query Plan’ları text formatında görüntülemek mümkün. Her ne kadar kompleks Query Plan’ların bu şekliyle okunması zor olsa da “Acaba tüm Plan’da hangi tablolar Table Scan yapılıyor?” tarzında bir soruya çok hızlı bir şekilde cevap alınabilir.

Estimated Query Plan’ı text formatında almak için aşağıdaki komut kullanılabilir.

SET SHOWPLAN_ALL ON;

 

Actual Query Plan için ise şu komutu kullanabiliriz.

SET STATISTICS PROFILE ON;

 

Her 2 Query Plan’ın text formatı da aşağıdaki gibi bir görüntü olacaktır.

image

XML Query Plan

Actual ve Estimated Query Plan’ları XML formatında da görüntülemek mümkün. XML Formatı düğüm yapısının getirdiği avantajla Text formatına oranla daha kolay bir okunabilirlik sağlamakta.

Estimated Query Plan’ı XML formatında almak için aşağıdaki komut kullanılabilir.

SET SHOWPLAN_XML ON;

 

Actual Query Plan için ise şu komutu kullanabiliriz.

SET STATISTICS XML ON;

 

Oluşan XML dosya açılıp .sqlplan uzantısı ile kaydedilirse Grafik Plan’a erişilmiş olacaktır.

 

Query Plan’lar sorguları optimize etmek için kullanılan en önemli kaynaklardan biridir. Değişik Query Plan görüntüleme özellikleri değişik amaçlar için kullanılabilir.

 

İyi Çalışmalar

Turgay Sahtiyan

Not : Blog haricinde, faydali gördügüm yazilari ve linkleri twitter adresimden paylasiyorum. Beni twitter'da takip etmek için : twitter.com/turgaysahtiyan


Bu makalemde SQL Server 2005 ile gelen Dump Device’ların backup-restore operasyonlarında ne şekilde kullanılabileceklerini görüyor olacağız.

[more]

Eğer hazırladığınız scriptlerin birden fazla yerinde backup restore kodları kullanıyorsanız Dump Device’lar işinizi kolaylaştıracaktır. Çünkü herhangi bir backup folder’ı değişikliğinde tüm backup restore komutlarında değişiklik yapılmaktansa Dump Device’da yapılacak değişiklik işi çözecektir.

Dump Device T-SQL ile şu şekilde create edilebilir;

USE master;
GO
EXEC sp_addumpdevice 'disk', 'myDumpDevice', 'D:\Backup\DenemeXBackup.bak';

 

Tanımlı Dump Device’ları sys.backup_devices catalog view’den sorgulanabilir.

image

Ayrıca SSMS üzerinden de tanımlı Dump Device’lara bakılabilir.

image

Şimdi tanımladığımız bu Dump Device’ı kullanarak backup alalım.

backup database Denemex to myDumpDevice With INIT

 

Bir de restore denemesi yapalım.

Restore database DenemeX from myDumpDevice With Replace

 

İyi Çalışmalar

Turgay Sahtiyan

Not : Blog haricinde, faydali gördügüm yazilari ve linkleri twitter adresimden paylasiyorum. Beni twitter'da takip etmek için : twitter.com/turgaysahtiyan


Bildiğiniz gibi NewID() fonksiyonu 16 byte büyüklüğünde rasgele unique değer oluşturmak için kullanılır. NewID’nin customize edilmiş hali olan NewSequentialID() fonksiyonu ise her defasında daha önce oluşturulan GUID’lerden daha büyük bir GUID oluşturmak için kullanılmakta.

[more]

SQL Server 2008 sürümüyle gelen NewSequentialID() fonksiyonu her çalıştırıldığında son windows restart’ından sonra oluşturulmuş GUID’lerden daha büyük bir GUID oluşturmayı taahhüt eder. Bir sonraki restart’dan sonra ise daha küçük bir GUID’den başlanma ihtimali vardır. Ama her halukarda NewID() gibi global olarak unique bir değer oluşturur.

Kullanılma yeri olarak Clustered Index key örneğini verebiliriz. Bazı geliştirici ya da DBA arkadaşlar clustered key olarak GUID kullanırlar. Eğer oluşturulan GUID rasgele olarak yani sıralı olarak oluşturulmaz ise tabloda Page Split ve Fragmantation oluşur.

NewSequentialID() sıralı GUID oluşturma özelliği ile bu sıkıntıları ortadan kaldırır. Tabi unutmamak gerekir ki, Windows restartından sonra bu sıranın kaybolma ve baştan başlanma ihtimali vardır.

NewSequentialID() sadece Default constraint olarak kullanılabilir.

CREATE TABLE myTable (Col1 uniqueidentifier DEFAULT NEWSEQUENTIALID()) 

 

NewId() gibi select çekilmek istendiğinde ise şu şekilde bir hata alınacaktır.

image

Son olarak şunu belirtmek istiyorum. NewSequentialID() sıralı olmasından dolayı bir sonraki create edilecek ID tahmin edilebilir. Bu yüzden güvenlik kaygısı olunan durumlarda kullanılmaması gerekir.

 

İyi Çalışmalar

Turgay Sahtiyan

Not : Blog haricinde, faydali gördügüm yazilari ve linkleri twitter adresimden paylasiyorum. Beni twitter'da takip etmek için : twitter.com/turgaysahtiyan


Liderleri arasında bulunduğum SQL Server Öncüleri topluluğunun 21 Ekim 2011’de lansmanını yapacağız. Öğleden önce tek öğleden sonra paralel session’lar halinde düzenleyeceğimiz etkinlikte benim de 14:00-15:00 saatleri arasında “Index ve İstatistik – Performansınızı Arttırın” başlıklı bir sunumum olacak.

Güzel bir başlangıç etkinliği olacak. Katılmanızı tavsiye ederim. Ayrıca ilgisi olacağını düşündüğünüz kişilere de bu linki forwardlayabilirsiniz.

Konuyla ilgili duyuruyu aşağıda bulabilirsiniz.

image

Tarih
21 Ekim 2011 Cuma
Saat
09.00 - 16.15
Yer
Microsoft İstanbul Ofisi Jüpiter Toplantı Salonu Bellevue Residance Aydın Sok No:7 Levent

image

Küresel çapta faaliyet gösteren, en büyük SQL Server topluluğu SQL Pass’ın (Professional Association for SQL Server) Türkiye Şubesi olarak çalışmaya başlayan SQL Server Öncüleri, tanıtım toplantısına sizleri de davet ediyor.

SQL Server ve etrafındaki teknolojilere odaklanan, Türkiye’de BT sektöründe konu hakkında çalışanlar arası etkileşimi arttırma hedefinde olan SQL Server Öncüleri ilk etkinliğini 21 Ekimde gerçekleştiriyor.

SQL Server konusunda çalışan BT çalışanlarının ve yazılım geliştiricilerinin hedeflendiği teknik içerikli SQL Server Öncüleri etkinliğinde sizleri de aramızda görmekten mutluluk duyarız.

Saygılarımızla,
SQL Server Öncüleri

image

Not : Blog haricinde, faydali gördügüm yazilari ve linkleri twitter adresimden paylasiyorum. Beni twitter'da takip etmek için : twitter.com/turgaysahtiyan


Microsoft, SP2’yi çıkarmasının üzerinden 11 ay geçmeden Service Pack 3(SP3)’ü yayınladı.

[more]

SP3 ile gelen önemli geliştirmelerden bazıları şu şekilde;

  • Enhanced upgrade experience from previous versions of SQL Server to SQL Server 2008 SP3. In addition, we have increased the performance & reliability of the setup experience.
  • In SQL Server Integration Services logs will now show the total number of rows sent in Data Flows.
  • Enhanced warning messages when creating the maintenance plan if the Shrink Database option is enabled.
  • Resolving database issue with transparent data encryption enabled and making it available even if certificate is dropped.
  • Optimized query outcomes when indexed Spatial Data Type column is referenced by DTA (Database Tuning Advisor).
  • Superior user experience with Sequence Functions (e.g Row_Numbers()) in a Parallel execution plan.

SP3, SP2 ve SP2’den sonra çıkan 4 adet cumulative update’i içermekte. Ayrıca gene SP3’ün içeriğinde müşteriler tarafından bildirilen hataların fixleri de bulunmakta.

SP3’ü aşağıdaki adreslerden download edebilirsiniz.

SQL Server 2008 SP3

SQL Server 2008 SP3 Express

Not : Blog haricinde, faydali gördügüm yazilari ve linkleri twitter adresimden paylasiyorum. Beni twitter'da takip etmek için : twitter.com/turgaysahtiyan


Daha önce SQL Server’da Index Kavramı adlı makalemde ve web seminerimde üzerinde durduğum konuyu bu makalede biraz daha detaylandırmak istiyorum.

[more]

SQL Server’da oluşturulan Clustered Index’te eğer Index’in key’i unique değil ise key’i unique’leştirmek için 4 byte’lık UNIQUIFIER bilgisi konulur.

UNIQUIFIER konulup konulmaması Index oluşturulurken yazılan UNIQUE anahtar kelimesine bağlıdır. Yani sizin Clustered Index key’inizi Identity gibi Unique bir ifade olsa dahi eğer Index’i oluştururken UNIQUE anahtar kelimesi kullanılmaz ise SQL Server gene bu key için 4 byte’lık UNIQUFIER bilgisi kullanacaktır. Bu da gereksiz yere her index satırı için 4 byte’lık yer kaybı anlamına gelmektedir.

Şimdi bu durumu bir örnekle görelim. 2 table oluşturacağız. Bu tablolardan ilkine Integer ID kolonu için Unique olmayan bir Clustered Index, ikincisine ise Unique bir Clustered Index oluşturacağız. Daha sonra bu 2 tablonun boyutlarını karşılaştıracağız.

Örneğimiz aşağıdaki gibi;

--1.Tablo
--Unique Clustered Index
if object_id('dbo.tblIndexDeneme1') is not null drop table tblIndexDeneme1
GO
create table tblIndexDeneme1 (ID int, Ad varchar(20), SoyAd varchar(20), Telefon varchar(10))
GO
declare @i int=0
while @i<100000
begin
  insert tblIndexDeneme1
    select @i,'Turgay'+cast(@i as varchar(10)),'Sahtiyan' + cast(@i as varchar(10)),'555 55 55'
  set @i=@i+1
end
GO
--ID kolonu üzerine clustered index
create clustered index IX_1 on tblIndexDeneme1 ( ID )
GO

--2.Tablo
--NonUnique Clustered Index
if object_id('dbo.tblIndexDeneme2') is not null drop table tblIndexDeneme2
GO
create table tblIndexDeneme2 (ID int, Ad varchar(20), SoyAd varchar(20), Telefon varchar(10))
GO
declare @i int=0
while @i<100000
begin
  insert tblIndexDeneme2
    select @i,'Turgay'+cast(@i as varchar(10)),'Sahtiyan' + cast(@i as varchar(10)),'555 55 55'
  set @i=@i+1
end
GO
--ID kolonu üzerine clustered index
create unique clustered index IX_1 on tblIndexDeneme2 ( ID )
GO

--Tablo ve Index'lerin boyutlarý
sp_spaceused 'tblIndexDeneme1'
GO
sp_spaceused 'tblIndexDeneme2'
GO

 

Tabloların boyut karşılaştırması sonucu aşağıdaki gibi olacaktır.

1

Gördüğünüz gibi Unique olmayan Clustered Index’e sahip tablonun boyutu Unique Clustered Index içeren tabloya oranla daha fazla. Bunun da nedeni Unique olmayan Clustered Index’te kaydı Unique’leştirmek için 4 byte’lık UNIQUIFIER kolonunun kullanılıyor olması.

Boyut farkının hem data hem de index_size’da olduğu gözükmekte. Çünkü UNIQUIFIER kolonu hem Leaf hem de NonLeaf Page’lerde bulunmakta. Şimdi bu durumu görelim.

NonUnique Clustered Index Leaf ve NonLeaf Level Page’ler (UNIQUIFIER kolonu hem NonLeaf hem Leaf Level Page’lerde bulunmakta)

2

3

Unique Clustered Index Leaf ve NonLeaf Level Page’ler (UNIQUIFIER kolonu Page’lerde bulunmamakta.)

4

5

Son söz olarak şunu söyleyelim. Eğer Index’iniz Unique bir kolon için oluşturuluyorsa Index’i oluştururken kesinlikle Unique ifadesini kullanın. Bu şekilde 4 byte’lık UNIQUIFIER kolonundan kurtulmuş olursunuz.

Not : Blog haricinde, faydali gördügüm yazilari ve linkleri twitter adresimden paylasiyorum. Beni twitter'da takip etmek için : twitter.com/turgaysahtiyan


29.09.2011 tarihinde gerçekleştirmiş olduğum SQL Server’da Index Kavramı - Performance Tuning ve Query Optimization başlıklı webcast’imin videosu aşağıdadır.

[more]

 

 

Webcast’te kullandığım sunum dosyasına şu linkten erişebilirsiniz.

Kullandığım scriptler ise aşağıdadır.

--table scan-index kullanımı arasındaki farkın 
--diskten yapılan okuma açısından değerlendirilmesi
drop table tblIndexDeneme1
GO
create table tblIndexDeneme1 (ID int, Ad varchar(20), SoyAd varchar(20), Telefon varchar(10))
GO
declare @i int=1
while @i<100000
begin
  insert tblIndexDeneme1
    select @i,'Turgay'+cast(@i as varchar(10)),'Sahtiyan' + cast(@i as varchar(10)),'555 55 55'
  set @i=@i+1
end
GO

--Table scan yaparak kayıt sorgulama-Query Plan
select * from tblIndexDeneme1 where ID=55000

--Table scan yaparak kayıt sorgulama-IO Consume
SET STATISTICS IO ON
SET STATISTICS TIME ON
GO
select * from tblIndexDeneme1 where ID=55000

--ID kolonu üzerine clustered index
create clustered index IX_1 on tblIndexDeneme1 ( ID )
GO

--clustered index kullanılarak kayıt sorgulama-IO Consume
SET STATISTICS IO ON
SET STATISTICS TIME ON
GO
select * from tblIndexDeneme1 where ID=55000
--230 kat daha az kayıt okundu.

SET STATISTICS IO OFF
SET STATISTICS TIME OFF

-----------------------------------------------------------------
------------- Index Page'leri Görüntüleme -----------------------
-----------------------------------------------------------------
--
select * from tblIndexDeneme1 where ID=55000

--Index Page'leri
DBCC IND('AdventureWorks2008','tblIndexDeneme1',1)

--Data Page için Trace Flag
DBCC TRACEON (3604);

--Page içeriği
DBCC PAGE('AdventureWorks2008',1,39362,3)


-----------------------------------------------------------------
-------------Index Page'lere ilk Bakış---------------------------
-----------------------------------------------------------------
--Clustered Index NonLeaf Level Page Örneği
DBCC IND('AdventureWorks2008','tblIndexDeneme1',1)

DBCC TRACEON (3604);
DBCC PAGE('AdventureWorks2008',1,24080,3)

--NonClustered Index NonLeaf Level Page Örneği
--İlk olarak Ad kolonu üzerinde bir NonClustered Index tanımlaması yapalım.
--Soyad kolonunuda included olarak belirleyelim.
create nonclustered index IX_2 on tblIndexDeneme1 ( Ad ) INCLUDE(Soyad)
GO

DBCC IND('AdventureWorks2008','tblIndexDeneme1',3)

DBCC PAGE('AdventureWorks2008',1,40603,3)



------------------------------------------------------
-------Örneklerle Index Page’lerin İncelenmesi--------
------------------------------------------------------

----------------------------------------
--Clustered Index’te Page’lerin Yapısı--
----------------------------------------

--Unique Clustered Index
drop table tblIndexDeneme2
GO
create table tblIndexDeneme2 (ID int, Ad varchar(20), SoyAd varchar(20), Telefon varchar(10))
GO
declare @i int=1
while @i<10000
begin
  insert tblIndexDeneme2
    select @i,'Turgay'+cast(@i as varchar(10)),'Sahtiyan' + cast(@i as varchar(10)),'555 55 55'
  set @i=@i+1
end
GO
create unique clustered index IX_1 on tblIndexDeneme2 ( ID )
GO

DBCC IND('AdventureWorks2008','tblIndexDeneme2',1)

DBCC TRACEON (3604);
DBCC PAGE('AdventureWorks2008',1,40482,3)

--Unique Olmayan Clustered Index
drop table tblIndexDeneme2
GO
create table tblIndexDeneme2 (ID int, Ad varchar(20), SoyAd varchar(20), Telefon varchar(10))
GO
declare @i int=1
while @i<10000
begin
  insert tblIndexDeneme2
    select cast(@i/10 as int),'Turgay'+cast(@i as varchar(10)),'Sahtiyan' + cast(@i as varchar(10)),'555 55 55'
  set @i=@i+1
end
GO
create clustered index IX_1 on tblIndexDeneme2 ( ID )
GO

DBCC IND('AdventureWorks2008','tblIndexDeneme2',1)

DBCC TRACEON (3604);
DBCC PAGE('AdventureWorks2008',1,40625,3)


-------------------------------------------
--NonClustered Index’te Page’lerin Yapısı--
-------------------------------------------

--Heap Tablo + Unique NonClustered Index
drop table tblIndexDeneme2
GO
create table tblIndexDeneme2 (ID int, Ad varchar(20), SoyAd varchar(20), Telefon varchar(10))
GO
declare @i int=1
while @i<10000
begin
  insert tblIndexDeneme2
    select cast(@i/10 as int),'Turgay'+cast(@i as varchar(10)),'Sahtiyan' + cast(@i as varchar(10)),'555 55 55'
  set @i=@i+1
end
GO
create unique nonclustered index IX_2 on tblIndexDeneme2 ( Ad )
GO

DBCC IND('AdventureWorks2008','tblIndexDeneme2',2)

DBCC TRACEON (3604);
DBCC PAGE('AdventureWorks2008',1,40786,3)

--Unique Clustered Index + Unique NonClustered Index
drop table tblIndexDeneme2
GO
create table tblIndexDeneme2 (ID int, Ad varchar(20), SoyAd varchar(20), Telefon varchar(10))
GO
declare @i int=1
while @i<10000
begin
  insert tblIndexDeneme2
    select @i,'Turgay'+cast(@i as varchar(10)),'Sahtiyan' + cast(@i as varchar(10)),'555 55 55'
  set @i=@i+1
end
GO
create unique clustered index IX_1 on tblIndexDeneme2 ( ID )
GO
create unique nonclustered index IX_2 on tblIndexDeneme2 ( Ad )
GO

DBCC IND('AdventureWorks2008','tblIndexDeneme2',2)

DBCC TRACEON (3604);
DBCC PAGE('AdventureWorks2008',1,23099,3)

--Unique Olmayan Clustered Index + Unique NonClustered Index
drop table tblIndexDeneme2
GO
create table tblIndexDeneme2 (ID int, Ad varchar(20), SoyAd varchar(20), Telefon varchar(10))
GO
declare @i int=1
while @i<10000
begin
  insert tblIndexDeneme2
    select cast(@i/10 as int),'Turgay'+cast(@i as varchar(10)),'Sahtiyan' + cast(@i as varchar(10)),'555 55 55'
  set @i=@i+1
end
GO
create clustered index IX_1 on tblIndexDeneme2 ( ID )
GO
create unique nonclustered index IX_2 on tblIndexDeneme2 ( Ad )
GO

DBCC IND('AdventureWorks2008','tblIndexDeneme2',2)

DBCC TRACEON (3604);
DBCC PAGE('AdventureWorks2008',1,41236,3)

--Unique Olmayan Clustered Index + Unique Olmayan NonClustered Index
drop table tblIndexDeneme2
GO
create table tblIndexDeneme2 (ID int, Ad varchar(20), SoyAd varchar(20), Telefon varchar(10))
GO
declare @i int=1
while @i<10000
begin
  insert tblIndexDeneme2
    select cast(@i/10 as int),'Turgay'+cast(@i as varchar(10)),'Sahtiyan' + cast(@i as varchar(10)),'555 55 55'
  set @i=@i+1
end
GO
create clustered index IX_1 on tblIndexDeneme2 ( ID )
GO
create nonclustered index IX_2 on tblIndexDeneme2 ( Ad )
GO

DBCC IND('AdventureWorks2008','tblIndexDeneme2',2)

DBCC TRACEON (3604);
DBCC PAGE('AdventureWorks2008',1,41504,3)


------------------------------------------------------
----NonClustered Index’te Included Kolon Kullanımı----
------------------------------------------------------

--AdventureWorks Person.Address tablosunun kayıt sayısını arttırmak.
declare @i int=1
while @i<5 begin
  insert Person.Address (AddressLine1, AddressLine2,City,StateProvinceID,PostalCode)
    select AddressLine1 + CHAR(@i), isnull(AddressLine2,'') + CHAR(@i)
		,City,StateProvinceID,PostalCode
    from Person.Address
  set @i=@i+1
end

drop index IX_City on Person.Address
create nonclustered index IX_City on Person.Address
	(City)

--Çekmek istediğimiz sorgu. Query Plan'a bakalım.
--City üzerinde NonClustered Index tanımlı
select AddressLine1, PostalCode
from Person.Address
where City='Bothell'

--Hızlandırmak için 1.seçenek 
--City, AddressLine1, PostalCode üzerine composite index tanımlamak
drop index IX_1 on Person.Address

create nonclustered index IX_1 on Person.Address
	(City,AddressLine1,PostalCode) 

--Index tanımladıktan sonra Query Plan'a tekrar bakalım.
select AddressLine1, PostalCode
from Person.Address
where City='Bothell'

--Composite index'in boyutu
--25.210 MB
select b.name,b.index_id,SUM(a.reserved_page_count)*8/1024. as Size_MB
from sys.dm_db_partition_stats a inner join sys.indexes b
on a.object_id=b.object_id and a.index_id=b.index_id
where OBJECT_ID('Person.Address')=a.object_id
	and b.name = 'IX_1'
group by b.name,b.index_id	

--Şimdi composite index yerine included index oluşturalım.
drop index IX_1 on Person.Address
GO
create nonclustered index IX_1 on Person.Address
	(City) INCLUDE (AddressLine1,PostalCode)

--Query Plan
select AddressLine1, PostalCode
from Person.Address
where City='Bothell'

--Bu composite index'in boyutu
--25.02 MB
select b.name,b.index_id,SUM(a.reserved_page_count)*8/1024. as Size_MB
from sys.dm_db_partition_stats a inner join sys.indexes b
on a.object_id=b.object_id and a.index_id=b.index_id
where OBJECT_ID('Person.Address')=a.object_id
	and b.name = 'IX_1'
group by b.name,b.index_id	

--Aradaki boyut farkının sebebi included kolonların 
--non-leaf page'lerde bulunmamasıdır.

DBCC IND('AdventureWorks2008','person.address',7)

DBCC TRACEON (3604);
DBCC PAGE('AdventureWorks2008',1,45274,3)
Not : Blog haricinde, faydali gördügüm yazilari ve linkleri twitter adresimden paylasiyorum. Beni twitter'da takip etmek için : twitter.com/turgaysahtiyan


Merhaba Arkadaşlar,

Bugün aldığım güzel bir haberi sizin ile paylaşmak istiyorum.

2011 yılında yaptığım çalışmalar sonucunda Microsoft tarafından SQL Server dalında MVP (Most Valuable Proffessional) ödülü ile ödüllendirildim.

Bu süreçte beni destekleyen Microsoft Ürün Müdürü Gökben Utkun’a, Türkiye MVP Liderimiz Sinem Eylem Arslan’a, yaptığım çalışmalarımda desteğini hiç esirgemeyen iş arkadaşım Kadir Evciler’e, sorularıma bıkmadan usanmadan cevap veren MS SQL Server PFE Batuhan Yıldız’a, içerik üretmeye başladığım ilk yer olan Çözümpark portalının kurucusu Hakan Uzuner’e bu post aracılığı ile bir kez daha teşekkür etmek istiyorum.

Umarım aldığım bu ödül bana daha çok itici güç olur ve paylaşımlarım katlanarak artmaya devam eder.

Turgay Sahtiyan

Not : Blog haricinde, faydali gördügüm yazilari ve linkleri twitter adresimden paylasiyorum. Beni twitter'da takip etmek için : twitter.com/turgaysahtiyan