SQL Server Tablo Bölümleme

Veritabanı içerisindeki büyük boyuttaki tablo ve indexler daha küçük bölümlemelere ayrılabilir ve farklı filegroup’lara dağıtılabilir. Böylelikle bölümleme ile hem select atıldığında sadece istenilen verinin bulunduğu bölüme giderek veri alınır hem de filegroup’lar farklı disklere taşınarak diskte yer açılır. Bu ise disk IO işlemlerinde performans kazanılması demektir. Örneğin bir tabloda bulunan 2020 verileri üzerinde DML işlemleri yapılırken aynı anda 2019 ve 2018 senesindeki veriler arşivlenebilir ve istediğimiz zaman arşivli verilere sorgu atabiliriz.

Bu makalede, var olan bir tablonun primary filegroup üzerinde bölümleme işlemini anlatacağım. Bu işlem adımları şu şekilde özetlenebilir:

  • Partition function oluşturarak tablo bölütlerinin belirlenmesi
  • Partition scheme oluşturularak veriler ile fonksiyonun ilişkilendirilmesi
  • Tablonun tarihlere göre partition’lara ayırılması

Var Olan Tablonun Bölümlenmesi

Var olan bir tabloyu bölümleyeceğimiz için ilk önce bir veritabanı ve bir ürünler tablosu oluşturarak başlayalım.

USE [Master]
GO

/* DemoDatabase veritabanının oluşturulması */

CREATE DATABASE [DemoDatabase]
ON  PRIMARY 
( NAME = N'DemoDatabase', FILENAME = N'C:\Microsoft SQL Server\DATA\DemoDatabase.mdf' )
log ON 
( NAME = N'DemoDatabase_log', FILENAME = N'C:\Microsoft SQL Server\DATA\DemoDatabase_log.ldf' )
GO

USE [DemoDatabase]
GO

/* Product tablosunun oluşturulması */

CREATE TABLE [dbo].[Product](
[ProductID] [Int] IDENTITY(1,1) NOT NULL,
[Quantity] [Int] NOT NULL,
[ModifiedDate] [Datetime] NULL,
CONSTRAINT [PK_Product] PRIMARY KEY CLUSTERED 
( [ProductID] ASC )
) ON [PRIMARY]
GO

Yüz bin kayıt insert ediyorum.

BEGIN TRY
	DECLARE @fromDate DATETIME = '2018-01-01 00:00:00'
	DECLARE @toDate DATETIME = CURRENT_TIMESTAMP
	DECLARE @seconds INT = DATEDIFF(SECOND, @fromDate, @toDate)
	DECLARE @random INT = ROUND(((@seconds-1) * RAND()), 0)
	DECLARE @randomDate DATETIME = DATEADD(SECOND, @random, @fromDate)
	INSERT INTO [Dbo].[Product] ([Quantity], [ModifiedDate]) 
	VALUES ( ROUND(RAND()*10000,0), @randomDate )
END TRY
BEGIN CATCH
	SELECT ERROR_NUMBER() AS ErrNum
		,ERROR_MESSAGE() AS ErrMsg;
	END CATCH;

GO 100000

Veritabanı ve henüz bölümlenmemiş tablomuz hazır. Tabloyu bölümlemeden önce partition function ve partition scheme oluşturmak zorundayız. Partition scheme’in görevi, oluşturulan fonksiyonu kullanarak verileri ilgili bölümlemelerle eşleştirmektir.

-- Partition function 
CREATE PARTITION FUNCTION MyPartitionFunc (DATETIME)
AS RANGE RIGHT
FOR VALUES (
'2018-01-01 00:00:00',
'2019-01-01 00:00:00',
'2020-01-01 00:00:00'
)
GO

-- Partition scheme
CREATE PARTITION SCHEME MyPartitionScheme
AS PARTITION MyPartitionFunc
ALL TO ([PRIMARY]);

Şimdi de tabloyu bölümleme işlemine geçelim. Object Explorer üzerinden tabloyau bulup sağ tıklayarak Storage -> Create Partition seçeneğini seçerek Partition Wizard penceresini açtım. Tabloyu tarihlere göre bölümleyeceğim için sadece ModifiedDate sütununu seçerek ilerledim.

Create Partition...
Resim 1
Create Partition Wizard
Resim 2

Önceden fonksiyon ve scheme’i oluşturduğum için onları seçip sonraki adımlara geçtiğimde işlemler sonucunda oluşan bölümlemeler gösterilmiştir.

Create Partition Wizard
Resim 3

Sonraki adımda oluşturulan wizard ile oluşturulan script’i çalıştırdıktan sonra Product tablosu bölümlenmiş oldu.

Create Partition Wizard Result
Resim 4

Bölümleme sonucuna göz atmak için şu script’in çıktısına bakmak yeterli olacaktır.

SELECT
    t.name AS TableName, i.name AS IndexName, p.partition_number, 
    r.value AS BoundaryValue, p.rows
FROM sys.tables AS t

INNER JOIN sys.indexes AS i 
ON t.object_id = i.object_id

INNER JOIN sys.partitions AS p 
ON i.object_id = p.object_id AND i.index_id = p.index_id

INNER JOIN sys.partition_schemes AS s 
ON i.data_space_id = s.data_space_id

INNER JOIN  sys.partition_functions AS f 
ON s.function_id = f.function_id

LEFT OUTER JOIN sys.partition_range_values AS r 
ON f.function_id = r.function_id AND r.boundary_id = p.partition_number

WHERE  t.name = 'Product' AND i.type <= 1
ORDER BY p.partition_number;
Check partitions
Resim 5

Sonraki partition yazılarında partition ve filegroup’ların ilişkililendirilmesinden bahsedeceğim. Yıllara göre filegroup’lar oluşturacağız ve bunları farklı disklere taşınarak veriyi arşivleyebileceğiz.

Leave a Reply

Your email address will not be published. Required fields are marked *