Not
Bu sayfaya erişim yetkilendirme gerektiriyor. Oturum açmayı veya dizinleri değiştirmeyi deneyebilirsiniz.
Bu sayfaya erişim yetkilendirme gerektiriyor. Dizinleri değiştirmeyi deneyebilirsiniz.
Şunlar için geçerlidir:SQL Server
Azure SQL Veritabanı
Azure SQL Yönetilen Örneği
Geçici tablolar, tablo değişkenleri veya tablo değerli parametreler kullanıyorsanız, performansı artırmak için bellek için iyileştirilmiş tabloları ve tablo değişkenlerini kullanmak için bunların dönüşümlerini göz önünde bulundurun. Kod değişiklikleri genellikle çok azdır.
Bu makalede şunlar açıklanmaktadır:
- Bellek İçi dönüşümü lehine argüman sunan senaryolar.
- Bellek içi dönüşümleri uygulamaya yönelik teknik adımlar.
- Bellek İçi dönüştürme öncesi önkoşullar.
- Bellek iyileştirmenin performans avantajlarını vurgulayan kod örneği
A. Bellek için iyileştirilmiş tablo değişkenlerinin temelleri
Bellek için iyileştirilmiş tablo değişkeni, bellek için iyileştirilmiş tablolar tarafından kullanılan aynı bellek için iyileştirilmiş algoritmayı ve veri yapılarını kullanarak büyük verimlilik sağlar. Tablo değişkenine yerel olarak derlenmiş bir modülün içinden erişildiğinde verimlilik en üst düzeye çıkar.
Bellek için iyileştirilmiş bir tablo değişkeni:
- Yalnızca bellekte depolanır ve diskte bileşen yoktur.
- Herhangi bir G/Ç etkinliği yoktur.
- Kullanım veya çekişme içermez
tempdb. - Depolanan bir proc'a tablo değerli bir parametre (TVP) olarak geçirilebilir.
- En az bir dizine, ya hash ya da küme olmayan dizine sahip olmalıdır.
- Karma indeks için, demet sayısı ideal olarak beklenen benzersiz dizin anahtarlarının sayısının 1-2 katı olmalıdır, ancak demet sayısını fazla tahmin etmek (10 kata kadar) genellikle sorun yaratmaz. Daha fazla bilgi için bkz. Memory-Optimized Tablolarındaki Dizinler.
Nesne türleri
In-Memory OLTP, geçici tabloları ve tablo değişkenlerini bellek iyileştirme için kullanılabilecek aşağıdaki nesneleri sağlar:
- Bellek için iyileştirilmiş tablolar
- Dayanıklılık = SCHEMA_ONLY
- Bellek için iyileştirilmiş tablo değişkenleri
- İki adımda bildirilmelidir (satır içi değil):
-
CREATE TYPE my_type AS TABLE ...;sonra -
DECLARE @mytablevariable my_type;.
-
- İki adımda bildirilmelidir (satır içi değil):
B. Senaryo: Genel geçici tabloyu değiştirme
Genel geçici tabloyu bellek için iyileştirilmiş bir SCHEMA_ONLY tablosuyla değiştirmek oldukça basittir. En büyük değişiklik, tabloyu çalışma zamanında değil dağıtım zamanında oluşturmaktır. Derleme zamanı iyileştirmeleri nedeniyle bellek için iyileştirilmiş tabloların oluşturulması geleneksel tabloların oluşturulmasından daha uzun sürer. Çevrimiçi iş yükünün bir parçası olarak bellek-iyileştirilmiş tabloların oluşturulması ve silinmesi, hem iş yükünün performansını hem de Always On Kullanılabilirlik Grubu ikincil kopyalarındaki ve veritabanı kurtarmadaki tekrar işleme performansını etkiler.
Aşağıdaki genel geçici tabloya sahip olduğunuzu varsayalım.
CREATE TABLE ##tempGlobalB
(
Column1 INT NOT NULL,
Column2 NVARCHAR (4000)
);
Genel geçici tabloyu, DAYANIKLILIK = SCHEMA_ONLY olan aşağıdaki bellek için iyileştirilmiş tabloyla değiştirmeyi göz önünde bulundurun.
CREATE TABLE dbo.soGlobalB
(
Column1 INT NOT NULL INDEX ix1 NONCLUSTERED,
Column2 NVARCHAR (4000)
)
WITH (MEMORY_OPTIMIZED = ON, DURABILITY = SCHEMA_ONLY);
Adımlar
Genel geçiciden SCHEMA_ONLY dönüştürme aşağıdaki adımlardır:
-
dbo.soGlobalBTabloyu, tıpkı geleneksel disk içi tablolarda olduğu gibi bir kez oluşturun. - Transact-SQL (T-SQL) içinden
##tempGlobalBtablo oluşturmayı kaldırın. Tablo oluşturma ile gelen derleme ek yükünü önlemek için çalışma zamanı yerine, dağıtım sırasında bellek optimize edilmiş tablo oluşturmak önemlidir. - T-SQL'inizdeki
##tempGlobalBiledbo.soGlobalBgeçen tüm yerleri değiştirin.
C. Senaryo: Oturum geçici tablosunu değiştirme
Oturum geçici tablosunu değiştirme hazırlıkları, önceki genel geçici tablo senaryosuna göre daha fazla T-SQL içerir. Ne mutlu ki fazladan T-SQL, dönüştürmeyi gerçekleştirmek için daha fazla çaba gerektiği anlamına gelmez.
Genel geçici tablo senaryosunda olduğu gibi en büyük değişiklik, derleme ek yükünü önlemek için tabloyu çalışma zamanında değil dağıtım zamanında oluşturmaktır.
Aşağıdaki oturum geçici tablosuna sahip olduğunuzu varsayalım.
CREATE TABLE #tempSessionC
(
Column1 INT NOT NULL,
Column2 NVARCHAR (4000)
);
Önce, filtrelemek için @@spid aşağıdaki tablo-değer işlevini oluşturun. İşlev, oturum geçici tablolarından dönüştürdüğünüz tüm SCHEMA_ONLY tabloları tarafından kullanılabilir.
CREATE FUNCTION dbo.fn_SpidFilter
(@SpidFilter SMALLINT)
RETURNS TABLE
WITH SCHEMABINDING, NATIVE_COMPILATION
AS
RETURN
SELECT 1 AS fn_SpidFilter
WHERE @SpidFilter = @@spid
İkincisi, SCHEMA_ONLY tablosunu ve tabloda bir güvenlik ilkesi oluşturun.
Bellek için iyileştirilmiş her tablonun en az bir dizini olmalıdır.
- Uygun BUCKET_COUNT hesaplanırsa, dbo.soSessionC tablosu için bir HASH indeksi daha iyi olabilir. Ancak bu örnek için NONCLUSTERED dizinini basitleştiririz.
CREATE TABLE dbo.soSessionC
(
Column1 INT NOT NULL,
Column2 NVARCHAR (4000) NULL,
SpidFilter SMALLINT DEFAULT (@@spid) NOT NULL,
CONSTRAINT CHK_soSessionC_SpidFilter CHECK (SpidFilter = @@spid),
INDEX ix_SpidFiler NONCLUSTERED (SpidFilter)
-- INDEX ix_SpidFilter HASH
-- (SpidFilter) WITH (BUCKET_COUNT = 64),
)
WITH (MEMORY_OPTIMIZED = ON, DURABILITY = SCHEMA_ONLY);
GO
CREATE SECURITY POLICY dbo.soSessionC_SpidFilter_Policy
ADD FILTER PREDICATE dbo.fn_SpidFilter(SpidFilter) ON dbo.soSessionC
WITH (STATE = ON);
GO
Üçüncüsü, genel T-SQL kodunuzda:
- Transact-SQL ifadelerinizdeki geçici tabloya yapılan tüm başvuruları yeni bellekle iyileştirilmiş tabloyla değiştirin:
-
Eski:
#tempSessionC -
Yeni:
dbo.soSessionC
-
Eski:
- Kodunuzdaki
CREATE TABLE #tempSessionCdeyimlerini, aynı session_id'ye sahip önceki bir oturum tarafından eklenmiş tablo içeriğini görmediğinizden emin olmak içinDELETE FROM dbo.soSessionCile değiştirin. Tablo oluşturma ile gelen derleme ek yükünü önlemek için çalışma zamanı yerine, dağıtım sırasında bellek optimize edilmiş tablo oluşturmak önemlidir. -
DROP TABLE #tempSessionCDeyimleri kodunuzdan kaldırın. İsteğe bağlı olarak, bellek boyutunun olası bir sorun olması durumunda birDELETE FROM dbo.soSessionCdeyim ekleyebilirsiniz.
D. Senaryo: Tablo değişkeni MEMORY_OPTIMIZED=ON olabilir
Geleneksel tablo değişkeni, veritabanındaki tempdb bir tabloyu temsil eder. Çok daha hızlı performans için tablo değişkeninizi bellekte iyileştirebilirsiniz.
Geleneksel tablo değişkeninin T-SQL'i aşağıdadır. Toplu işlem veya oturum sona erdiğinde kapsamı biter.
DECLARE @tvTableD TABLE (
Column1 INT NOT NULL,
Column2 CHAR (10));
Satır içinden açık biçime dönüştürme
Yukarıdaki söz diziminin satır içi tablo değişkenini oluşturacağı söylenir. Satır içi söz dizimi bellek iyileştirmeyi desteklemez. Bu nedenle, satır içi söz dizimini TÜR için açık söz dizimine dönüştürelim.
Kapsam: İlk go-delimited toplu işlemi tarafından oluşturulan TÜR tanımı, sunucu kapatılıp yeniden başlatıldıktan sonra bile devam eder. Ancak ilk go komutundan sonra, bildirilen tablo @tvTableC, yalnızca bir sonraki go komutu gerçekleşip komut grubu sona erene kadar mevcut kalır.
CREATE TYPE dbo.typeTableD AS TABLE (
Column1 INT NOT NULL,
Column2 CHAR (10));
GO
SET NOCOUNT ON;
DECLARE @tvTableD AS dbo.typeTableD;
INSERT INTO @tvTableD (Column1) VALUES (1), (2);
SELECT * FROM @tvTableD;
GO
D.2 Açık disk üzerindeki verileri bellek için iyileştirilmiş duruma dönüştürme
Bellek için iyileştirilmiş tablo değişkeni içinde tempdbyer almaz. Bellek iyileştirmesi, genellikle 10 kat veya daha hızlı olan hız artışları ile sonuçlanır.
Bellek-optimize edilmiş dönüşüm yalnızca bir adımda gerçekleştirilir. Açık TÜR oluşturma işlemini aşağıdaki gibi geliştirin; bu da şunları ekler:
- Dizin. Yine, bellek için iyileştirilmiş her tablonun en az bir dizini olmalıdır.
- MEMORY_OPTIMIZED = ON.
CREATE TYPE dbo.typeTableD AS TABLE (
Column1 INT NOT NULL INDEX ix1,
Column2 CHAR (10))
WITH (MEMORY_OPTIMIZED = ON);
Tamam.
E. SQL Server için Önkoşul FILEGROUP
Microsoft SQL Server'da, bellek ile iyileştirilmiş özellikleri kullanmak için, veritabanınızın MEMORY_OPTIMIZED_DATA ile bildirilen bir FILEGROUP'u olmalıdır.
- Azure SQL Veritabanı bu FILEGROUP'un oluşturulmasını gerektirmez.
Önkoşul: FileGROUP için aşağıdaki Transact-SQL kodu, bu makalenin sonraki bölümlerinde yer alan uzun T-SQL kod örnekleri için önkoşuldur.
- T-SQL gönderebilen SSMS.exe veya başka bir araç kullanmanız gerekir.
- Örnek FILEGROUP T-SQL kodunu SSMS'ye yapıştırın.
- T-SQL'i düzenleyerek belirli adlarını ve dizin yollarını istediğiniz gibi değiştirin.
- FILENAME değerindeki tüm dizinlerin önceden var olması gerekir, ancak son dizin önceden var olmamalıdır.
- Düzenlenen T-SQL'inizi çalıştırın.
- Sonraki alt bölümde T-SQL hız karşılaştırmasını tekrar tekrar ayarlayıp yeniden çalıştırsanız bile FILEGROUP T-SQL'i birden fazla çalıştırmanız gerekmez.
ALTER DATABASE InMemTest2
ADD FILEGROUP FgMemOptim3 CONTAINS MEMORY_OPTIMIZED_DATA;
GO
ALTER DATABASE InMemTest2
ADD FILE (NAME = N'FileMemOptim3a', FILENAME = N'C:\DATA\FileMemOptim3a'
-- C:\DATA\ preexisted.
) TO FILEGROUP FgMemOptim3;
GO
Aşağıdaki betik sizin için dosya grubunu oluşturur ve önerilen veritabanı ayarlarını yapılandırmaktadır: enable-in-memory-oltp.sql
FILE ve FILEGROUP hakkında ALTER DATABASE ... ADD daha fazla bilgi için bkz:
- ALTER DATABASE (Transact-SQL) Dosya ve Dosya Grubu Seçenekleri
- Bellek için iyileştirilmiş dosya grubu
F. Hız geliştirmeyi kanıtlamak için hızlı test
Bu bölüm, bellek için iyileştirilmiş bir tablo değişkeni kullanarak INSERT-DELETE'e ilişkin hız kazancını test etmek ve karşılaştırmak üzere çalıştırabileceğiniz Transact-SQL kodunu sağlar. Kod, tablo türünün bellek için optimize edilmiş olduğu ilk yarı dışında neredeyse aynı olan iki yarıdan oluşur.
Karşılaştırma testi yaklaşık 7 saniye sürer. Örneği çalıştırmak için:
- Önkoşul: Önceki bölümden FILEGROUP T-SQL'i zaten çalıştırmış olmanız gerekir.
- Aşağıdaki T-SQL INSERT-DELETE betiğini çalıştırın.
- T-SQL'i
GO 50015.001 kez yeniden gönderen deyimine dikkat edin. Sayıyı ayarlayabilir ve yeniden çalıştırabilirsiniz.
Betiği bir Azure SQL Veritabanında çalıştırırken aynı bölgedeki bir VM'den çalıştırdığınızdan emin olun.
PRINT ' ';
PRINT '---- Next, memory-optimized, faster. ----';
DROP TYPE IF EXISTS dbo.typeTableC_mem;
GO
CREATE TYPE dbo.typeTableC_mem -- !! Memory-optimized.
AS TABLE (
Column1 INT NOT NULL INDEX ix1,
Column2 CHAR(10)
)
WITH (MEMORY_OPTIMIZED = ON);
GO
DECLARE @dateString_Begin NVARCHAR(64) =
CONVERT(NVARCHAR(64), GETUTCDATE(), 121);
PRINT CONCAT (
@dateString_Begin,
' = Begin time, _mem.'
);
GO
SET NOCOUNT ON;
DECLARE @tvTableC dbo.typeTableC_mem;-- !!
INSERT INTO @tvTableC (Column1) VALUES (1), (2);
INSERT INTO @tvTableC (Column1) VALUES (3), (4);
DELETE @tvTableC;GO 5001
DECLARE @dateString_End NVARCHAR(64) =
CONVERT(NVARCHAR(64), GETUTCDATE(), 121);
PRINT CONCAT (
@dateString_End,
' = End time, _mem.'
);
GO
DROP TYPE IF EXISTS dbo.typeTableC_mem;
GO
---- End memory-optimized.
-------------------------------------------------
---- Start traditional on-disk.
PRINT ' ';
PRINT '---- Next, tempdb based, slower. ----';
DROP TYPE IF EXISTS dbo.typeTableC_tempdb;
GO
CREATE TYPE dbo.typeTableC_tempdb -- !! Traditional tempdb.
AS TABLE (
Column1 INT NOT NULL,
Column2 CHAR(10)
);
GO
DECLARE @dateString_Begin NVARCHAR(64) =
CONVERT(NVARCHAR(64), GETUTCDATE(), 121);
PRINT CONCAT (
@dateString_Begin,
' = Begin time, _tempdb.'
);
GO
SET NOCOUNT ON;
DECLARE @tvTableC dbo.typeTableC_tempdb;-- !!
INSERT INTO @tvTableC (Column1) VALUES (1), (2);
INSERT INTO @tvTableC (Column1) VALUES (3), (4);
DELETE @tvTableC;
GO 5001
DECLARE @dateString_End NVARCHAR(64) =
CONVERT(NVARCHAR(64), GETUTCDATE(), 121);
PRINT CONCAT (
@dateString_End,
' = End time, _tempdb.'
);
GO
DROP TYPE IF EXISTS dbo.typeTableC_tempdb;
GO
PRINT '---- Tests done. ----';
GO
Sonuç kümesi aşağıdadır.
---- Next, memory-optimized, faster. ----
2016-04-20 00:26:58.033 = Begin time, _mem.
Beginning execution loop
Batch execution completed 5001 times.
2016-04-20 00:26:58.733 = End time, _mem.
---- Next, tempdb based, slower. ----
2016-04-20 00:26:58.750 = Begin time, _tempdb.
Beginning execution loop
Batch execution completed 5001 times.
2016-04-20 00:27:05.440 = End time, _tempdb.
---- Tests done. ----
G. Etkin bellek tüketimini tahmin et
Aşağıdaki kaynaklarla bellek için iyileştirilmiş tablolarınızın etkin bellek gereksinimlerini tahmin etmeyi öğrenebilirsiniz:
- Memory-Optimized Tablo için Bellek Gereksinimlerini Tahmin Etme
- Bellek için iyileştirilmiş tablolarda tablo ve satır boyutu
Daha büyük tablo değişkenleri için, kümelenmemiş dizinler bellek için iyileştirilmiş tablolardan daha fazla bellek kullanır. Satır sayısı ve dizin anahtarı ne kadar büyük olursa, fark o kadar artar.
Bellek için iyileştirilmiş tablo değişkenine erişim başına yalnızca bir tam anahtar değeriyle erişiliyorsa, karma dizin, kümelenmemiş dizinden daha iyi bir seçim olabilir. Ancak, uygun BUCKET_COUNT tahmin edemiyorsanız, KÜMELENMİYEN dizin iyi bir ikinci seçenektir.