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.
Ö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.
Sonraki adımda oluşturulan wizard ile oluşturulan script’i çalıştırdıktan sonra Product tablosu bölümlenmiş oldu.
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;
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.