Bu yazımda sizlere
SQL Server 2014 ile birlikte hayatımıza girmiş olan In Memory OLTP'den
bahsetmek istiyorum. SQL Server 2016'nın hayatımıza gireceği bu günlerde SQL
Server 2014 ile birlikte Gelen yeniklikler adında uzun zaman önce yazdığım
ancak yayınlama fırsatı bulamadığım bu yazı dizimi yayınlama fırsatını ancak
bulabildim.
SQL Server 2014
versiyonunu uzun zamandan bu yana kullanmaktayız. Ancak çoğumuz yeni gelen
özellikleri ve hayatımıza kattığı kolaylık gözden kaçırabiliyoruz. Aynı şeyler
eski versiyonlar içinde geçerli. Bu nedenle yeni bir ürün çıktığında o ürünle
birlikte gelen yeni özellikleri çok önemsiyorum.
Yenilikler konusunda
ilk yazım SQL Server 2014 ile birlikte gelen In-Memory OLTP adlı yazım olacak.
SQL Server ilk
dizayn edildiği yıllarda RAM maliyetleri çok yüksekti. Bu nedenler verilerin
diskte tutulup process görmesi gerekiyordu. Teknoloji ilerledikçe bu yapının
değiştirilmesi kaçınılmaz bir hal aldı. Ram fiyatları ve işlemci fiyatları
inanılmaz derecede düştü. Bu nedenle SQL Server engine modeli üzerinde yeniden
yapılandırmaya gidildi ve SQL Server In-Memory OLTP teknolojisi geldi.
SQL
Server 2014'teki In-Memory teknolojiyle, işlem
uygulamalarını 30 kata kadar hızlandırabilir, 100 kattan daha yüksek hızdaki
sorgular ve raporlar sayesinde işletmenizle ilgili bilgileri daha hızlı elde
edebilir ve hızlı çözümleme için milyonlarca satırı işleyebilirsiniz.
Memory Optimized
Tables and Indexes
İlk önce In-Memory
tabloları tutacağımız veritabanında Memory
Optimized Data File Group ve içerisinde File oluşturmanız gerekiyor.
ALTER DATABASE
[HekatonDB]
ADD FILEGROUP
[InMemFileGroup] CONTAINS MEMORY_OPTIMIZED_DATA
GO
ALTER
DATABASE[HekatonDB]
ADD FILE(
NAME=N'InMemFile',
FILENAME=N'C:\SQLData\InMemFile'
) TO FILEGROUP
[InMemFileGroup]
Daha sonra
Memory-Optimized Tabloyu aşağıdaki gibi oluşturabiliriz.
CREATE TABLE dbo.sample_memoryoptimizedtable
(
s1 int NOT NULL
PRIMARY KEY
NONCLUSTERED HASH (s1) WITH (BUCKET_COUNT =1024),
s2 decimal(10,2) NOT
NULL
INDEX IDX_s2 HASH (s2) WITH (BUCKET_COUNT =1024)
) WITH
(MEMORY_OPTIMIZED=ON,DURABILITY=SCHEMA_AND_DATA)
Buradaki
keywordlerden MEMORY_OPTIMIZED tablonunun memory optimized olup olmadığını
belirtmek için kullanılır. DURABILITY
Keywordu ise opsiyenel bir Keyworddur. Belirtilmezse default olarak
SCHEMA_AND_DATA olarak belirtilir. Serverın crash olması durumunda hem schema
hemde data geri getirilebilir.
NONCLUSTERED HASH
Index yeni bir Index türüdür. İleriki makalelerde ayrıntılı olarak bahsetmeyi
planlıyorum. NONCLUSTERED HASH Index Memory Optimized tablolara özgü bir index
türüdür. Mutlaka eklenmelidir. Tablo DLL olarak compile edildiği için sonradan eklenemez.
Memory Optimized
Tablolarda kullanmadıklarımız
*Lob Typelerı Memory
Optimized Tablolarda kullanamayız.
*Identity
Kullanmayız.
*Tabloyu ALTER TABLE
edemeyiz.
*DML Trigger
kullanamıyız.
*XML kullanamayız.
*CLR Kullanamayız.
*Foreing Key
Kullanamayız.
HASH INDEX
Memory Optimized
tablolarda 8 adet Hash Index tanımlanabilir. Index tanımlanırken tabloyu
oluştururken bucket_count ile belirttiğimiz hücrelere veriler hash
algoritmasından geçerek yerleşir.
RANGE INDEX
Bucket_Count
belirtilmek istenmediği durumlarda ve aralık sorgulamalarının sıkça yapılacağı
durumlarda bu index türü tercih edilmelidir. Çünkü daha performanslı çalışır.
MEMORY OPTIMIZED
TABLOLARA NASIL ERİŞEBİLİRİZ.
1-T-SQL kullanarak
erişebiliriz.
2-Native Compiled
Stored Procedures kullanarak erişebiliriz.
Erişimi T-SQL ile
kullandığımızda performans artışı sağlayabiliriz ancak Native Compiled Stored
Procedures kullandığımızda gerçek performansı elde etmiş oluruz.
Native Compiled
Stored Procedures normal bir stored procedure yazım şeklindedir.
CREATE PROCEDURE
usp_Insert500000Rows
WITH
NATIVE_COMPILATION, EXECUTE AS OWNER, SCHEMABINDING
AS
BEGIN ATOMIC WITH
(TRANSACTION ISOLATION LEVEL = SNAPSHOT, LANGUAGE = N'English')
DECLARE @i INT = 0
WHILE @i < 500000
BEGIN
INSERT INTO dbo.T1_inmem VALUES (@i, @i/2,
GETDATE(), N'my string')
SET @i += 1
END
END
DEMO(Yiğit AKTAN'ın
Demosunda Alınmıştır.)
-----Memory Optimized Data File Group içeren Bir
Database oluşturuyoruz------
CREATE DATABASE
[HekatonDB1]
CONTAINMENT = NONE
ON
PRIMARY
( NAME =
N'HekatonDB1', FILENAME = N'D:\Workload\Databases\SQL2014\HekatonDB1.mdf' ,
SIZE = 5120KB , FILEGROWTH = 1024KB )
LOG ON
( NAME =
N'HekatonDB1_log', FILENAME =
N'D:\Workload\Databases\SQL2014\HekatonDB1_log.ldf' , SIZE = 2048KB ,
FILEGROWTH = 10%)
GO
ALTER DATABASE
[HekatonDB1] ADD FILEGROUP [HekatonDB1_MOD] CONTAINS MEMORY_OPTIMIZED_DATA
GO
ALTER DATABASE
[HekatonDB1] SET COMPATIBILITY_LEVEL = 120
GO
USE [HekatonDB1]
GO
IF NOT EXISTS
(SELECT name FROM sys.filegroups WHERE is_default=1 AND name = N'PRIMARY')
ALTER DATABASE [HekatonDB1] MODIFY FILEGROUP
[PRIMARY] DEFAULT
GO
------FileGroup'a Bir Tane File
Ekliyoruz-----------------------------
USE [master]
GO
ALTER DATABASE
[HekatonDB1]
ADD FILE (NAME =
N'HekatonDB1_MOD', FILENAME = N'D:\Workload\Databases\SQL2014\HekatonDB1_MOD')
TO FILEGROUP
[HekatonDB1_MOD]
GO
-----Disk Bazlı Tablomuzu
Oluşturuyoruz.--------------------------------------------------
USE [HekatonDB1]
GO
CREATE TABLE
dbo.T1_ondisk
(
c1
int NOT NULL PRIMARY KEY,
c2
int NOT NULL INDEX IDX_C2 NONCLUSTERED,
c3
DATETIME2 NOT NULL,
c4
NCHAR(400)
)
GO
-----Memory Optimized Table
oluşturuyoruz--------------------------------------------
USE HekatonDB1
GO
CREATE TABLE
dbo.T1_inmem
(
c1
int NOT NULL PRIMARY KEY NONCLUSTERED HASH WITH (BUCKET_COUNT = 20000000),
c2
int NOT NULL INDEX IDX2 NONCLUSTERED HASH WITH (BUCKET_COUNT = 20000000),
c3
DATETIME2 NOT NULL,
c4
NCHAR(400)
) WITH
(MEMORY_OPTIMIZED = ON)
GO
-----İkinci Memory Optimized Table
Oluşturuyoruz--------------------------------------
USE HekatonDB1
GO
CREATE TABLE
dbo.T2_inmem
(
c1
int NOT NULL PRIMARY KEY NONCLUSTERED HASH WITH (BUCKET_COUNT = 20000000),
c2
int NOT NULL INDEX IDX3 NONCLUSTERED HASH WITH (BUCKET_COUNT = 20000000),
c3
DATETIME2 NOT NULL,
c4
NCHAR(400)
) WITH
(MEMORY_OPTIMIZED = ON)
GO
-----Diskte Tutulan Tableımıza 500000 kayıt
ekliyoruz----------------------------------------
USE [HekatonDB1]
GO
DECLARE @i INT = 0
WHILE @i < 500000
BEGIN
INSERT INTO dbo.T1_ondisk VALUES (@i, @i/2,
GETDATE(), N'my string')
SET @i += 1
END
-----Memory Optimized Table Native SP Kullanmadan
500000 kayıt ekliyoruz---
USE [HekatonDB1]
GO
DECLARE @i INT = 0
WHILE @i < 500000
BEGIN
INSERT INTO dbo.T2_inmem VALUES (@i, @i/2,
GETDATE(), N'my string')
SET @i += 1
END
-----Natively Compiled Stored Procedure
Oluşturuyoruz----------------------------------
USE [HekatonDB1]
GO
CREATE PROCEDURE
usp_Insert500000Rows
WITH
NATIVE_COMPILATION, EXECUTE AS OWNER, SCHEMABINDING
AS
BEGIN ATOMIC WITH
(TRANSACTION ISOLATION LEVEL = SNAPSHOT, LANGUAGE = N'English')
DECLARE @i INT = 0
WHILE @i < 500000
BEGIN
INSERT INTO dbo.T1_inmem VALUES (@i, @i/2,
GETDATE(), N'my string')
SET @i += 1
END
END
GO
----Natively Compiled Stored Procedure Çalıştırarak
500000 kayıt ekliyoruz---
EXEC
[HekatonDB1].[dbo].[usp_Insert500000Rows]
INSERT, UPDATE, DELETE performansını 30 kat arttırmak konusunda iddialı olan bu
teknolojiyi SQL Server 2014 versiyonu ile sizde kullanmaya başlayabilirsiniz.