6 Ağustos 2015 Perşembe

SQL Server 2014 Yenilikleri-1 (In-Memory OLTP)

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.


Sql Server DateTime Veri Tipindeki Datayı Türkçe Formatında Göstermek

  SQL'de tarihleri farklı formatlarda göstermek için FORMAT fonksiyonunu kullanabilirsiniz. Türkçe kısa tarih formatı genellikle "...