Pazartesi , 20 Kasım 2017

SQL Server 2016 Truncate Table Komutu

SQL Serverda tablomuzda tutulan verileri silmek için iki komut kullanabiliriz. Bunlardan bir tanesi TRUNCATE iken diğeri ise DELETE komutudur. Her iki komut da tablolarımızdaki verileri silmek için kullanılsa da her ikisinin de farklı yönleri vardır. Örneğin TRUNCATE TABLE komutu ile tablolarımızda bulunan verinin tamamını hızlıca silebiliriz. Çünkü TRUNCATE TABLE komutu veriyi silerken satır satır silmek yerine verinin tutulduğu pagelerin referanslarını silmektedir. Bu da bize veri boyutu çok büyük olsa bile milyonlarca satır veriyi birkaç saniyede silmeyi sağlamaktadır. DELETE komutu ise sadece tablomuzdaki verinin tamamını silmek için kullanılabileceği gibi bir koşul verilerek tablomuzdaki verimizin koşula uyan bir kısmını silmemizi sağlamaktadır. Fakat DELETE komutunun en önemli özelliği silinen kayıtları satır satır silip bu kayıtların her birinin Transaction log dosyasına da yazmasıdır ki bu durum silinecek kayıt sayısı fazla olduğunda DELETE komutunun çalışması süresini uzatacaktır. Bu sebeple eğer bir tablomuzdaki kayıtların tamamını silme gibi bir ihtiyacımız olduğunda DELETE yerine TRUNCATE TABLE komutunu kullanmak önerilmektedir.

Daha öncede belirttiğimiz gibi TRUNCATE TABLE komutu en önemli dezavantajı tablomuzdaki verinin tamamını silme zorunluluğudur. İşte SQL Server 2016 CTP 2 versiyonu ile beraber table partition kullandığımız tablolarda TRUNCATE TABLE komutuyla tablomuzdaki tüm veriyi değil, verinin sadece belli kısmını içeren partitionlardan birini veya bir kaçını silebiliriz.

TRUNCATE TABLE komutunun kullanımı SQL Server 2016 CTP 2 versiyonu ile aşağıdaki gibi değişti.

TRUNCATE TABLE 
    [ { database_name .[ schema_name ] . | schema_name . } ]
    table_name
    [ WITH ( PARTITIONS ( { <partition_number_expression> | <range> } 
    [ , ...n ] ) ) ]
[ ; ]

TRUNCATE TABLE komutuna değindikten sonra şimdi SQL Server 2016 CTP 2 versiyonu ile tanıtılan özelliği test edelim. Bunun için öncelikle örnek veritabanımızda beraber tablomuzdaki veriyi farklı partitionlarda tutacak şekilde aşağıdaki gibi örnek veritabanımızı ve tablomuzu adım adım oluşturalım.

USE master
GO
CREATE DATABASE PartitionDb
GO

Yukarıdaki gibi veritabanımızı oluşturduktan sonra şimdi Partitioning işlemi için gerekli olan Partition Function ve Partition Scheme objelerimizi oluşturalım. Bildiğimiz gibi Table Partitioning işleminde kullanılan bu objelerden Partition Function tablomuzdaki verinin bölüneceği değer aralıklarını tanımlarken, tanımlanan bu aralıktaki kayıtların veritabanı seviyesinde hangi Filegroup içinde yer alan dosyaya yazılacağını ise Partition Scheme objesi ile belirtiyoruz. Şimdi bu objelerimizi oluşturalım.

USE PartitionDb
GO
CREATE PARTITION FUNCTION PartitioningByID (int)
AS RANGE LEFT FOR VALUES
(1000, 2000, 3000,4000, 5000, 6000,7000)
 GO

CREATE PARTITION SCHEME PartitionByID
AS PARTITION PartitioningByID
TO ([PRIMARY], [PRIMARY], [PRIMARY], [PRIMARY], [PRIMARY]
, [PRIMARY], [PRIMARY],[PRIMARY]);
 
GO

Yukarıdaki gibi Partition Function ve Partition Scheme objelerimizi oluşturduk. Dikkat ederseniz tablomuza kaydedilecek olan veriyi binerli gruplara ayırarak böleceğimizi Partition Function ile belirlerken, ilgili aralığa denk gelen kaydın fiziksel olarak nerede tutulacağını ise Partition Scheme ile belirtiyoruz. Veritabanımızda hâlihazırda tek Filegroup olduğu için tüm aralıklar için aynı Filegroup kullanılacaktır. Oysa genellikle Partition Function içinde belirtilen her aralık için fiziksel dosyaların yer aldığı farklı Filegrouplar kullanılmaktadır. Şimdi artık tablomuzu aşağıdaki gibi oluşturabiliriz.

CREATE TABLE PartitionedTable(
    ID INT NOT  NULL,
    NAME VARCHAR(100) NULL,
    CREATEDATE DATETIME NOT NULL
) ON PartitionByID(ID)
 
GO

Yukarıdaki gibi tablomuzu oluşturduktan sonra dikkat etmemiz gereken nokta tablomuzdaki verinin Id değerine göre bir fonksiyondan geçirilerek verinin fiziksel olarak hangi Filegroup içinde olacağının belirleneceğini belirtiyoruz. Tablomuzda oluşturduktan sonra artık tablomuza örnek kayıtlarımızı ekleyebiliriz.

INSERT INTO PartitionedTable(ID,NAME,CREATEDATE)
SELECT TOP 7000 ROW_NUMBER() OVER(ORDER BY o1.object_id),'ismail adar',GETDATE()
FROM sys.objects o1 cross join sys.objects o2

Yukarıdaki gibi tablomuza 7000 adet kayıt ekledikten sonra şimdi bu kayıtların hangi partition içinde tutulduğunu kontrol edelim.

SELECT
    $PARTITION.PartitioningByID (ID) AS PartitionID
,   COUNT(*) AS [RowCount]
FROM dbo.PartitionedTable
GROUP BY $PARTITION.PartitioningByID (ID)

truncate_table1

 

Yukarıdaki resimde gördüğümüz gibi her bir partition için 1000 tane kayıt eklediğini görebiliyoruz. Şimdi de Truncate Table komutumuza eklenen seçenek ile bu partitionlardan bulunan verileri silelim. İlk olarak 1. ve 2. Partitionda bulunan verilerimizi silelim.


TRUNCATE TABLE dbo.PartitionedTable

WITH (PARTITIONS(1,2));



SELECT

$PARTITION.PartitioningByID(ID) AS PartitionID

,   COUNT(*) AS [RowCount]

FROM dbo.PartitionedTable

GROUP BY $PARTITION.PartitioningByID(ID)

truncate_table2

Yukarıdaki gibi 1. ve 2. Partitionlarda bulunan verilerimizi sildik. Dikkat ederseniz silmek istediğimiz Partition numaralarını aralarına virgül koyarak belirtebiliyoruz. Ayrıca eğer silmek istediğimiz Partition birden fazla ve ardışık ise aralıkta belirtebiliriz. Şimdi de bunu kullanarak 3 ve 6 numaralı partition aralığında yer alan tüm partitionlarda yer alan verileri silelim ve Partitionların son durumunu kontrol edelim.


TRUNCATE TABLE dbo.PartitionedTable

WITH (PARTITIONS(3 TO 6));


SELECT

$PARTITION.PartitioningByID(ID) AS PartitionID

,   COUNT(*) AS [RowCount]

FROM dbo.PartitionedTable

GROUP BY $PARTITION.PartitioningByID(ID)

truncate_table3

Tablomuzun son durumunu kontrol ettiğimizde sadece silmediğimiz son partitionda yer alan verilerin kaldığını görebiliriz.

 

Hakkında ismailadar

2 yorum

  1. Faydalı çalışma olmuş hocam emeğinize sağlık…

Cevapla

E-posta adresiniz yayınlanmayacak. Required fields are marked *

*


*

Şu HTML etiketlerini ve özelliklerini kullanabilirsiniz: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>