Memory-Optimized Tablolardaki Dizinler
Şunlar için geçerlidir:SQL ServerAzure SQL VeritabanıAzure SQL Yönetilen Örneği
Satırları birbirine bağlayan dizinler olduğundan, bellek için iyileştirilmiş tüm tabloların en az bir dizini olmalıdır. Bellek için iyileştirilmiş bir tabloda, her dizin de bellek için iyileştirilmiştir. Bellek için iyileştirilmiş bir tablodaki bir dizinin disk tabanlı tablodaki geleneksel bir dizinden farklı olması için çeşitli yollar vardır:
- Veri satırları sayfalarda depolanmaz, bu nedenle bir tablonun tüm sayfalarını almak için başvurulabilecek sayfa veya kapsam koleksiyonu, bölüm veya ayırma birimi yoktur. Kullanılabilir dizin türlerinden biri için dizin sayfaları kavramı vardır, ancak bunlar disk tabanlı tablolar için dizinlerden farklı şekilde depolanır. Bir sayfada geleneksel parçalanma türünü biriktirmezler, bu nedenle doldurma faktörleri yoktur.
- Veri işleme sırasında bellek için iyileştirilmiş tablolardaki dizinlerde yapılan değişiklikler hiçbir zaman diske yazılır. Yalnızca veri satırları ve verilerde yapılan değişiklikler işlem günlüğüne yazılır.
- Veritabanı yeniden çevrimiçi duruma getirildiğinde bellek için iyileştirilmiş dizinler yeniden oluşturulur.
Bellek için iyileştirilmiş tablolardaki tüm dizinler, veritabanı kurtarma sırasındaki dizin tanımlarına göre oluşturulur.
Dizin aşağıdakilerden biri olmalıdır:
- Hash dizini
- Bellek için iyileştirilmiş Kümelenmemiş dizin (B ağacının varsayılan iç yapısı anlamına gelir)
Columnstore dizinleri başka bir makaleele alınmaktadır.
Bellek için iyileştirilmiş dizinlerin söz dizimi
Bellek için iyileştirilmiş bir tabloya ait her CREATE TABLE deyimi, açıkça bir İNDİS aracılığıyla veya örtülü olarak bir BİRİNCİL ANAHTAR veya BENZERSİZ kısıtlaması aracılığıyla bir dizin içermelidir.
Varsayılan DAYANIKLILIK = SCHEMA_AND_DATA olarak ilan edilmesi için, bellek için optimize edilmiş tablonun birincil anahtarı olmalıdır. Aşağıdaki CREATE TABLE deyimindeki PRIMARY KEY NONCLUSTERED yan tümcesi iki gereksinimi karşılar:
CREATE TABLE deyiminde bir dizinin en düşük gereksinimini karşılayacak bir dizin sağlar.
SCHEMA_AND_DATA yan tümcesi için gereken birincil anahtarı sağlar.
CREATE TABLE SupportEvent ( SupportEventId int NOT NULL PRIMARY KEY NONCLUSTERED, ... ) WITH ( MEMORY_OPTIMIZED = ON, DURABILITY = SCHEMA_AND_DATA);
Not
SQL Server 2014 (12.x) ve SQL Server 2016 (13.x) bellek için iyileştirilmiş tablo veya tablo türü başına 8 dizin sınırına sahiptir. SQL Server 2017 'den (14.x) başlayarak ve Azure SQL Veritabanı'nda bellek için iyileştirilmiş tablolara ve tablo türlerine özgü dizin sayısı sınırı yoktur.
Söz dizimi için kod örneği
Bu alt bölüm, bellek için optimize edilmiş bir tabloda çeşitli dizinler oluşturmaya yönelik söz dizimini gösteren bir Transact-SQL kod bloğu içerir. Kod aşağıdakileri gösterir:
Bellek için iyileştirilmiş bir tablo oluşturun.
İki dizin eklemek için ALTER TABLE deyimlerini kullanın.
Birkaç veri satırı ekleyin.
DROP TABLE IF EXISTS SupportEvent; go CREATE TABLE SupportEvent ( SupportEventId int not null identity(1,1) PRIMARY KEY NONCLUSTERED, StartDateTime datetime2 not null, CustomerName nvarchar(16) not null, SupportEngineerName nvarchar(16) null, Priority int null, Description nvarchar(64) null ) WITH ( MEMORY_OPTIMIZED = ON, DURABILITY = SCHEMA_AND_DATA); go -------------------- ALTER TABLE SupportEvent ADD CONSTRAINT constraintUnique_SDT_CN UNIQUE NONCLUSTERED (StartDateTime DESC, CustomerName); go ALTER TABLE SupportEvent ADD INDEX idx_hash_SupportEngineerName HASH (SupportEngineerName) WITH (BUCKET_COUNT = 64); -- Nonunique. go -------------------- INSERT INTO SupportEvent (StartDateTime, CustomerName, SupportEngineerName, Priority, Description) VALUES ('2016-02-23 13:40:41:123', 'Abby', 'Zeke', 2, 'Display problem.' ), ('2016-02-24 13:40:41:323', 'Ben' , null , 1, 'Cannot find help.' ), ('2016-02-25 13:40:41:523', 'Carl', 'Liz' , 2, 'Button is gray.' ), ('2016-02-26 13:40:41:723', 'Dave', 'Zeke', 2, 'Cannot unhide column.'); go
Yinelenen dizin anahtarı değerleri
Dizin anahtarı için yinelenen değerler bellek için iyileştirilmiş tabloların performansını düşürebilir. Çoğu dizin okuma ve yazma işlemi için giriş zincirlerinden geçiş yapmak için sistemin yinelemeleri. Yinelenen girişler zinciri 100 girdiyi aştığında performans düşüşü ölçülebilir hale gelebilir.
Yinelenen karma değerler
Hash dizinler söz konusu olduğunda bu sorun daha görünür. Karma dizinler, aşağıdaki etmenlerden dolayı daha fazla etkilenir:
- Karma dizinler için işlem başına daha düşük maliyet.
- Büyük yinelenen zincirlerin karma çakışmalar zinciri ile etkileşimi.
Dizinde yinelemeyi azaltmak için aşağıdaki ayarlamaları deneyin:
- Kümelenmemiş bir dizin kullanın.
- Yinelenenlerin sayısını azaltmak için dizin anahtarının sonuna ek sütunlar ekleyin.
- Örneğin, birincil anahtarda da bulunan sütunları ekleyebilirsiniz.
Karma çakışmaları hakkında daha fazla bilgi için bkz. Memory-Optimized Tablolar için Karma Dizinler
Örnek iyileştirme
Dizininizdeki performans verimsizliği önlemeye yönelik bir örnek aşağıda verilmiştir.
CustomerId
üzerinde birincil anahtarı olan ve CustomerCategoryID
sütununda dizini olan bir Customers
tablosu düşünün. Genellikle belirli bir kategoride çok sayıda müşteri olacaktır. Bu nedenle, dizinin belirli bir anahtarının içinde CustomerCategoryID için birçok yinelenen değer olacaktır.
Bu senaryoda, en iyi yöntem (CustomerCategoryID, CustomerId)
üzerinde bir kümelenmemiş dizin kullanmaktır. Bu dizin, CustomerCategoryID
içeren bir koşul kullanan sorgular için kullanılabilir, ancak dizin anahtarı yineleme içermez. Bu nedenle, dizin bakımındaki verimsizliklerin nedeni yinelenen CustomerCategoryID değerleri veya dizindeki ek sütun değildir.
Aşağıdaki sorgu,WideWorldImporters
SELECT AVG(row_count) FROM
(SELECT COUNT(*) AS row_count
FROM Sales.Customers
GROUP BY CustomerCategoryID) a
Kendi tablonuz ve dizininiz için dizin anahtarı yinelemelerinin ortalama sayısını değerlendirmek için, Sales.Customers
tablonuzun adıyla değiştirin ve CustomerCategoryID
dizin anahtarı sütunlarının listesiyle değiştirin.
Her dizin türünün ne zaman kullanılacağını karşılaştırma
Hangi dizin türünün en iyi seçenek olduğunu belirli sorgularınızın doğası belirler.
Mevcut bir uygulamada bellek için iyileştirilmiş tablolar uygulanırken genel öneri, disk tabanlı tablolardaki geleneksel kümelenmiş ve kümelenmemiş dizinlerin özelliklerine daha yakın olduğundan, kümelenmemiş dizinlerle başlamaktır.
Kümelenmemiş dizin kullanımına yönelik öneriler
Kümelenmemiş dizinler, şu durumlarda karma dizine göre tercih edilir:
- Sorguların indeksli sütunda bir
ORDER BY
yan tümcesi vardır. - Çok sütunlu dizinin yalnızca önde gelen sütunlarının test edildiği sorgular.
- Sorgular, dizine alınan sütunu bir
WHERE
koşul ifadesi kullanarak test etmektedir:- Eşitsizlik:
WHERE StatusCode != 'Done'
- Değer aralığı taraması:
WHERE Quantity >= 100
- Eşitsizlik:
Aşağıdaki tüm SELECT'lerde, karma dizin yerine kümelenmemiş dizin tercih edilir:
SELECT CustomerName, Priority, Description
FROM SupportEvent
WHERE StartDateTime > DateAdd(day, -7, GetUtcDate());
SELECT StartDateTime, CustomerName
FROM SupportEvent
ORDER BY StartDateTime DESC; -- ASC would cause a scan.
SELECT CustomerName
FROM SupportEvent
WHERE StartDateTime = '2016-02-26';
Karma dizin kullanımına yönelik öneriler
Karma dizinleri öncelikle aralık taramaları için değil nokta aramalarında kullanılır.
Aşağıdaki örnekte olduğu gibi sorgular eşitlik koşullarını kullandığında ve WHERE
yan tümcesi tüm dizin anahtarı sütunlarıyla eşlendiğinde karma dizin, kümelenmemiş bir dizine göre tercih edilir:
SELECT CustomerName
FROM SupportEvent
WHERE SupportEngineerName = 'Liz';
Çok sütunlu dizin
Çok sütunlu dizin, kümelenmemiş bir dizin veya karma dizin olabilir. Dizin sütunlarının sütun1 ve sütun2 olduğunu varsayalım. Aşağıdaki SELECT
deyimi göz önüne alındığında, sorgu iyileştiricisi için yalnızca kümelenmemiş dizin yararlı olabilir:
SELECT col1, col3
FROM MyTable_memop
WHERE col1 = 'dn';
Karma dizin, anahtarındaki sütunların her biri için bir eşitlik testi belirtmek için WHERE
yan tümcesine ihtiyaç duyar. Aksi halde karma dizin sorgu iyileştiricisi için kullanışlı değildir.
WHERE
yan tümcesi dizin anahtarında yalnızca ikinci sütunu belirtiyorsa, dizin türü de yararlı olmaz.
Dizin kullanım senaryolarını karşılaştırmak için özet tablosu
Aşağıdaki tabloda, farklı dizin türleri tarafından desteklenen tüm işlemler listelenmektedir. Evet, dizinin isteği verimli bir şekilde karşılayabileceği anlamına gelir ve Hayır, dizinin isteği verimli bir şekilde karşılayamayacağı anlamına gelir.
İşlem | Bellek açısından optimize edilmiş Hash |
Bellek iyileştirilmiş kümelenmemiş |
Disk tabanlı, (kümelenmemiş) |
---|---|---|---|
Dizin Taraması, tüm tablo satırlarını alın. | Evet | Evet | Evet |
Eşitlik koşullarına (=) göre dizin araması. | Evet (Tam anahtar gereklidir.) |
Evet | Evet |
Eşitsizlik ve aralık koşullarında indeks araması (>, <, <=, >=, BETWEEN ). |
Hayır (Dizin taramasına neden olur.) |
Evet 1 | Evet |
Satırları dizin tanımıyla eşleşen bir sıralama düzeninde alın. | Hayır | Evet | Evet |
Dizin tanımının tersiyle eşleşen bir sıralama düzeninde satırları alın. | Hayır | Hayır | Evet |
1 Bellek için optimize edilmiş bir kümelenmemiş dizin için dizin araması gerçekleştirirken tam anahtar gerekli değildir.
Otomatik dizin ve istatistik yönetimi
Bir veya daha fazla veritabanının dizin birleştirme ve istatistik güncelleştirmelerini otomatik olarak yönetmek için Uyarlamalı Dizin Birleştirme gibi çözümlerden yararlanın. Bu yordam, diğer parametreler arasında bir dizini parçalanma düzeyine göre yeniden derlemeyi veya yeniden düzenlemeyi ve istatistikleri doğrusal bir eşikle güncelleştirmeyi otomatik olarak seçer.
Ayrıca Bkz.
sql server dizin tasarım kılavuzu
Memory-Optimized Tablolar
Kümelenmemiş Dizinler Memory-Optimized Tablolar İçin
Uyarlamalı Dizin Birleştirme