Partition Oluşturmak
Partition, kabaca tabloların ve indexlerin parçalara bölünmesi işlemidir. Örneğin 1 TB boyuta sahip bir tablonuz var. Ve bu tabloda datetime tipinde bir kolonunuz var. Tablonuzu bu datetime kolonuna göre günlük, aylık ya da yıllık olarak bölümlere ayırabilirsiniz. Daha önce gördüğüm bir örnekte bir uygulamacı tablonun çok büyümemesi için her ay için farklı bir tablo oluşturmuştu. Bu şekilde veritabanında aynı iş için yüzlerce tablo oluşuyor. SQL Server partition yöntemi ile bu özelliği sağlayabiliyor. Fark olarak, sorgularınız için yüzlerce tablo yerine tek tablo kullanmış oluyorsunuz. SQL Server arka planda bu tablodaki değerleri bölümlere ayırıyor.
Peki partition’ın faydaları nelerdir?
- Örneğimizden yola çıkarak, tabloyu ay ay partition yaptığımızı düşünelim. Üçüncü aydaki bir veriye ulaşmaya çalıştığımızda sadece üçüncü aydaki partition’a erişeceğimiz için veriye daha hızlı erişebileceğiz.
- Tabloda index rebuild,index reorganize gibi bakım işlemlerini yapmak istediğimizde bütün tabloda yapmak yerine partition partition yapabiliriz. Bu şekilde daha hızlı bir şekilde bu işlemi gerçekleştirmiş oluruz.
- Eğer iki tablo aynı kolona göre partition yapılmışsa ve bu iki tablo bu kolon üzerinden join işlemine girerse ciddi bir performans elde edersiniz. Çünkü partition bazında join de yapılabilir.
- Lock Escalation’ı tüm tablo yerine partition bazında aktif hale getirerek performans artışı sağlayabilirsiniz. Lock Escalation çok sayıda küçük seviye lock’ın daha az sayıda bir üst seviye lock’a dönüştürülmesi işlemidir. Örneğin çok sayıda row lock’ın page lock’a dönüştürülmesi işlemi gibi. SQL Server bu işlemi arka planda otomatik olarak yapar. SQL Server lock çeşitleri ile ilgili “SQL Server Lock(Kilit) Çeşitleri” isimli makalemi okumak isteyebilirsiniz. Aşağıdaki sorgu yardımıyla partition yapılmış tablolarda lock escalation’ı partition bazlı hale getirebiliriz. Eğer tablo partition yapılmamışsa lock escalation tablo bazlı olacaktır.
ALTER TABLE T1 SET (LOCK_ESCALATION = AUTO)
Partition’ı oluşturuken her partition’ı farklı filegroup’lara koyabiliyorsunuz. Filegroup’ları da farklı disklere koyarak I/O performans artışı sağlayabiliyorsunuz. Filegroup ile ilgili detaylı bilgi almak için “Veritabanı Oluşturmak Deyip Geçmeyin!” isimli makalemi okumak isteyebilirsiniz.
Partition yapacağımız tablonun partition’larını farklı file group’lara koymak için aşağıdaki script yardımıyla iki tane file group oluşturalım. Filegroup’ların içinde birer tane de file oluşturalım.
USE Test ALTER DATABASE Test ADD FILEGROUP FileGroup1 ALTER DATABASE Test ADD FILEGROUP FileGroup2 ALTER DATABASE Test ADD FILEGROUP FileGroup3 ALTER DATABASE Test ADD FILE ( NAME = DataFile1, FILENAME = 'C:\MSSQL\TestDataFile1.ndf') TO FILEGROUP FileGroup1 ALTER DATABASE Test ADD FILE ( NAME = DataFile2, FILENAME = 'C:\MSSQL\TestDataFile2.ndf') TO FILEGROUP FileGroup2 ALTER DATABASE Test ADD FILE ( NAME = DataFile3, FILENAME = 'C:\MSSQL\TestDataFile3.ndf') TO FILEGROUP FileGroup3
Aşağıdaki script yardımıyla da partition function ve partition schema ‘yı oluşturalım. Partition function’da 1 Ocak 2007 ve öncesine ait tarihlerin bir partition’da 1 Ocak 2007 ile 1 Ocak 2008 arasındaki verilerin başka bir partition’da, sonrasının da başka bir partition’da olacağını belirtiyoruz.
Partition Schema’da ise KayitZamaniPartition isimli partition function’da belirttiğimiz üç partition’ın hangi filegroup’lar da olacağını belirtiyoruz.
CREATE PARTITION FUNCTION KayitZamaniPartition (DATETIME) AS RANGE RIGHT FOR VALUES ('20070101','20080101') CREATE PARTITION SCHEME KayitZamaniScheme AS PARTITION KayitZamaniPartition TO (FileGroup1, FileGroup2,FileGroup3)
Aşağıdaki script yardımıyla da bu partition alt yapısını kullanan tablomuzu oluşturalım. Aynı partition yapısını birden fazla tablo kullanabilir.
CREATE TABLE [dbo].[PartitionOrnek]( [ID] [int] IDENTITY(1,1) NOT NULL, [AdSoyad] [varchar](250) NULL, [KayitZamani] [datetime] NULL ) ON KayitZamaniScheme (KayitZamani) ALTER TABLE dbo.PartitionOrnek SET (LOCK_ESCALATION = TABLE)
Tablomuza aşağıdaki script yardımıyla dört insert işlemi gerçekleştirelim.
INSERT INTO dbo.PartitionOrnek(AdSoyad,KayitZamani) VALUES ('Nurullah ÇAKIR','20080201') INSERT INTO dbo.PartitionOrnek(AdSoyad,KayitZamani) VALUES ('Faruk ERDEM', '20070101') INSERT INTO dbo.PartitionOrnek(AdSoyad,KayitZamani) VALUES ('Hakan GÜRBAŞLAR','20090101') INSERT INTO dbo.PartitionOrnek(AdSoyad,KayitZamani) VALUES ('DİLARA AYDIN','20040401')
Hangi kaydın hangi partition’da olduğunu aşağıdaki script yardımıyla sorgulayabiliriz.
SELECT AdSoyad,KayitZamani, $PARTITION.KayitZamaniPartition(KayitZamani) PARTITION FROM dbo.PartitionOrnek ORDER BY KayitZamani
Mevcut bir tabloyu nasıl partititon yaparız?
1.Yöntem:
Partition yapıda yeni bir tablo oluşturup mevcut tablo içindeki verileri bu yeni tabloya aktarabiliriz.
2.Yöntem:
Öncelikle örneğimizde oluşturduğumuz tablomuzu silelim ve partition yapıdan olmadan yeniden oluşturalım.
USE [Test] GO CREATE TABLE [dbo].[PartitionOrnek]( [ID] [int] IDENTITY(1,1) NOT NULL, [AdSoyad] [varchar](250) NULL, [KayitZamani] [datetime] NULL ) ON [PRIMARY]
Daha sonra bu tabloya aşağıdaki gibi bir kaç kayıt insert edelim.
INSERT INTO dbo.PartitionOrnek(AdSoyad,KayitZamani) VALUES ('Nurullah ÇAKIR','20080201') INSERT INTO dbo.PartitionOrnek(AdSoyad,KayitZamani) VALUES ('Faruk ERDEM', '20070101') INSERT INTO dbo.PartitionOrnek(AdSoyad,KayitZamani) VALUES ('Hakan GÜRBAŞLAR','20090101') INSERT INTO dbo.PartitionOrnek(AdSoyad,KayitZamani) VALUES ('DİLARA AYDIN','20040401')
Aşağıdaki script ile hangi partition’ da kaç kayıt olduğunu sorgulayabiliriz.
SELECT partition_id, object_id, partition_number, rows FROM sys.partitions WHERE object_id = OBJECT_ID('PartitionOrnek')
Daha sonra aşağıdaki script ile tabloda clustered index oluşturarak tabloyu partition yapıya geçirebiliriz.
USE [Test] GO CREATE CLUSTERED INDEX [CIX] ON [dbo].[PartitionOrnek] ( [ID] ASC )WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, SORT_IN_TEMPDB = OFF, DROP_EXISTING = OFF, ONLINE = ON, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON KayitZamaniScheme (KayitZamani)
Eğer clustered index varsa da aşağıdaki gibi create script’ini almalıyız.
Script’teki drop existing kısmını on yapmalıyız ve sonuna da “KayitZamaniScheme (KayitZamani)” değerini yazmalıyız.
“KayitZamaniScheme” bizim partition scheme ‘ mızın ismi.
“KayitZamani” bizim partition yaptığımız kolon’un ismi.
Script’in son halinin aşağıdaki yapıda olması gerekir.
USE [Test] GO CREATE CLUSTERED INDEX [CIX] ON [dbo].[PartitionOrnek] ( [ID] ASC )WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, SORT_IN_TEMPDB = OFF, DROP_EXISTING = ON, ONLINE = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON KayitZamaniScheme (KayitZamani)
Partition ile ilgili sliding window senaryosu(yani tablodaki en eski partition’ın düzenli olarak arşive alınarak tablodaki partition sayısını sabit tutmak) ve switch partition konularını “Sliding Window-Switch Partition-Split Range-Merge Range” isimli makalemde bulabilirsiniz.
Partition ile switch yapma işleminde sıkıntı yaşamamak için partition yapılmış tablodaki tüm index’lerin partition schema’ya göre align edilmiş olması gerekiyor.
Align işleminin ne olduğunu ve nasıl yapıldığını anlamak için “Partition Switch Yapılamıyor” isimli makaleme göz atmak isteyebilirsiniz.
Partition yapılmış tabloları ve detaylarını görmek için aşağıdaki makalelerden de faydalanabilirsiniz.
“Veritabanında Partition Yapılmış Tabloları Bulmak“,
“Partition Yapılmış Tablodaki Partition Detaylarını Görmek“