Aracılığıyla paylaş


Memory-Optimized Tabloları için Karma Dizin sorunlarını giderme

Şunlar için geçerlidir:SQL ServerAzure SQL VeritabanıAzure SQL Yönetilen Örneği

Önkoşul

Bu makaleyi anlamak için önemli bağlam bilgilerine şu konumdan ulaşabilirsiniz:

  • Memory-Optimized Tabloları için Dizinleri
  • Memory-Optimized Tablolar için Karma Dizinleri

Pratik sayılar

Bellek ile iyileştirilmiş bir tablo için hash dizin oluştururken, oluşturma zamanında kovaların sayısının belirtilmesi gerekir. Çoğu durumda demet sayısı ideal olarak dizin anahtarındaki ayrı değerlerin sayısının 1 ila 2 katı olur.

Ancak, BUCKET_COUNT tercih edilen aralığın orta derecede altında veya üstünde olsa bile karma dizininizin performansı muhtemelen tolere edilebilir veya kabul edilebilir olacaktır. En azından karma dizininize, hafıza için optimize edilmiş tablonuzun sahip olacağını tahmin ettiğiniz satır sayısına yaklaşık eşit bir BUCKET_COUNT vermeyi düşünün.
Büyüyen tablonuzda 2.000.000 satır olduğunu ve tahminen 10 kat artarak 20.000.000 satıra çıkacağını varsayın. Tablodaki satır sayısının 10 katı olan bir kova sayısıyla başlayın. Bu, daha fazla satır için size yer sağlar.

  • İdeal olarak, satır sayısı ilk demet sayısına ulaştığında demet sayısını artırabilirsiniz.
  • Satır sayısı demet sayısının beş katına çıksa bile, çoğu durumda performans yine de iyidir.

Karma dizinin 10.000.000 ayrı anahtar değerine sahip olduğunu varsayalım.

  • 2.000.000 kova sayısı kabul edebileceğiniz en düşük değer olabilir. Performans düşüşü derecesi tolere edilebilir olabilir.

Dizinde çok fazla yinelenen değer var mı?

Karma dizinlenen değerlerin yinelenme oranı yüksekse, karma kovaları daha uzun zincirlerden etkilenir.

Önceki T-SQL söz dizimi kod bloğundan aynı SupportEvent tablosuna sahip olduğunuzu varsayalım. Aşağıdaki T-SQL kodu, tüm değerlerin benzersiz değerlerine oranını nasıl bulup görüntüleyebileceğinizi gösterir.

-- Calculate ratio of:  Rows / Unique_Values.  
DECLARE @allValues float(8) = 0.0, @uniqueVals float(8) = 0.0;  
  
SELECT @allValues = Count(*) FROM SupportEvent;  
  
SELECT @uniqueVals = Count(*) FROM  
  (SELECT DISTINCT SupportEngineerName  
      FROM SupportEvent) as d;  
  
    -- If (All / Unique) >= 10.0, use a nonclustered index, not a hash.   
SELECT Cast((@allValues / @uniqueVals) as float) as [All_divby_Unique];  
go  
  • 10,0 veya üzeri bir oran, karmanın düşük bir dizin türü olacağı anlamına gelir. Bunun yerine bir kümelenmemiş dizin kullanmayı göz önünde bulundurun,

Karma indeksi yuva sayısı sorunlarını giderme

Bu bölümde karma dizininiz için demet sayısı sorunlarını giderme adımları açıklanmıştır.

Zincirler ve boş kovalar için istatistikleri izleme

Aşağıdaki T-SQL SELECT'i çalıştırarak karma dizinlerinizin istatistiksel durumunu izleyebilirsiniz. SELECT, sys.dm_db_xtp_hash_index_statsadlı veri yönetimi görünümünü (DMV) kullanır.

SELECT  
  QUOTENAME(SCHEMA_NAME(t.schema_id)) + N'.' + QUOTENAME(OBJECT_NAME(h.object_id)) as [table],   
  i.name                   as [index],   
  h.total_bucket_count,  
  h.empty_bucket_count,  
    
  FLOOR((  
    CAST(h.empty_bucket_count as float) /  
      h.total_bucket_count) * 100)  
                            as [empty_bucket_percent],  
  h.avg_chain_length,   
  h.max_chain_length  
FROM  
        sys.dm_db_xtp_hash_index_stats  as h   
  JOIN sys.indexes                     as i  
          ON h.object_id = i.object_id  
          AND h.index_id  = i.index_id  
JOIN sys.memory_optimized_tables_internal_attributes ia ON h.xtp_object_id=ia.xtp_object_id
JOIN sys.tables t on h.object_id=t.object_id
WHERE ia.type=1
ORDER BY [table], [index];  

SELECT sonuçlarını aşağıdaki istatistiksel yönergelerle karşılaştırın:

  • Boş kovalar:
    • 33% iyi bir hedef değerdir, ancak daha büyük bir yüzde (hatta 90%) genellikle uygundur.
    • Demet sayısı ayrı anahtar değerlerinin sayısına eşit olduğunda, demetlerin yaklaşık 33% boş olur.
    • 10% altındaki bir değer çok düşük.
  • Kovalar içindeki zincirler
    • Yinelenen dizin anahtarı değerleri olmaması durumunda ortalama 1 zincir uzunluğu idealdir. 10'a kadar olan zincir uzunlukları genellikle kabul edilebilir.
    • Ortalama zincir uzunluğu 10'dan büyükse ve boş demet yüzdesi 10%'den büyükse, verilerin çok fazla yinelemesi vardır ve karma dizin en uygun tür olmayabilir.

Zincirlerin ve boş kovaların gösterimi

Aşağıdaki T-SQL kod bloğu, bir SELECT * FROM sys.dm_db_xtp_hash_index_stats;test etmenin kolay bir yolunu sunar. Kod bloğu 1 dakika içinde tamamlanır. Aşağıdaki kod bloğunun aşamaları şunlardır:

  1. Bellek için iyileştirilmiş ve birkaç karma indeks içeren bir tablo oluşturur.
  2. Tabloyu binlerce satırla doldurur.
    a. StatusCode sütunundaki yinelenen değerlerin oranını yapılandırmak için modül işleci kullanılır.
    b. Döngü yaklaşık 1 dakikada 262.144 satır ekler.
  3. PRINS, sizden önceki SELECT'i çalıştırmanızı isteyen bir mesaj iletir sys.dm_db_xtp_hash_index_stats.
DROP TABLE IF EXISTS SalesOrder_Mem;  
go  
  
  
CREATE TABLE SalesOrder_Mem  
(  
  SalesOrderId   uniqueidentifier  NOT NULL  DEFAULT newid(),  
  OrderSequence  int               NOT NULL,  
  OrderDate      datetime2(3)      NOT NULL,  
  StatusCode     tinyint           NOT NULL,  
  
  PRIMARY KEY NONCLUSTERED  
      HASH (SalesOrderId)  WITH (BUCKET_COUNT = 262144),  
  
  INDEX ix_OrderSequence  
      HASH (OrderSequence) WITH (BUCKET_COUNT = 20000),  
  
  INDEX ix_StatusCode  
      HASH (StatusCode)    WITH (BUCKET_COUNT = 8),  
  
  INDEX ix_OrderDate       NONCLUSTERED (OrderDate DESC)  
)  
  WITH (MEMORY_OPTIMIZED = ON, DURABILITY = SCHEMA_AND_DATA)  
go  
  
--------------------  
  
SET NOCOUNT ON;  
  
-- Same as PK bucket_count.  68 seconds to complete.  
DECLARE @i int = 262144;  
  
BEGIN TRANSACTION;  
  
WHILE @i > 0  
BEGIN  
  
  INSERT SalesOrder_Mem  
      (OrderSequence, OrderDate, StatusCode)  
    Values  
      (@i, GetUtcDate(), @i % 8);  -- Modulo technique.  
  
  SET @i -= 1;  
END  
COMMIT TRANSACTION;  
  
PRINT 'Next, you should query:  sys.dm_db_xtp_hash_index_stats .';  
go  

Yukarıdaki INSERT döngüsü aşağıdakileri yapar:

  • Birincil anahtar dizini ve ix_OrderSequenceiçin benzersiz değerler ekler.
  • StatusCodeiçin yalnızca sekiz ayrı değeri temsil eden birkaç yüz bin satır ekler. Bu nedenle, ix_StatusCodedizininde yüksek değer yineleme oranı vardır.

Kova sayısı en uygun olmadığında sorun giderme için, sys.dm_db_xtp_hash_index_stats'den SELECT sorgusunun aşağıdaki çıkışını inceleyin. Bu sonuçlar için D.1 bölümünden kopyalanan SELECT'e WHERE Object_Name(h.object_id) = 'SalesOrder_Mem' ekledik.

SELECT sonuçlarımız koddan sonra görüntülenir ve daha iyi görüntülenmesi için yapay olarak iki daha dar sonuç tablosuna ayrılır.

  • demet sayısının sonuçları aşağıdadır.
Dizin Adı toplam_kova_sayısı boş_kova_sayısı EmptyBucketPercent
ix_OrderSequence 32768 13 0
ix_StatusCode 8 4 50
PK_SalesOrd_B14003... 262144 96525 36
  • Ardından zincirinin uzunluk sonuçları.
Dizin Adı ortalama_zincir_uzunluğu maksimum_zincir_uzunluğu
ix_OrderSequence 8 26
ix_StatusCode 65536 65536
PK_SalesOrd_B14003... 1 8

Üç karma dizin için önceki sonuç tablolarını yorumlayalım:

ix_StatusCode:

  • Kovaların 50% boş, bu iyi.
  • Bununla birlikte, ortalama zincir uzunluğu 65536'da çok yüksektir.
    • Bu, yinelenen değerlerin yüksek oranını gösterir.
    • Bu nedenle, bu durumda karma dizin kullanmak uygun değildir. Bunun yerine bir kümelenmemiş dizin kullanılmalıdır.

ix_OrderSequence:

  • Kovalardan 0% tanesi boş, bu çok az.
  • Bu dizindeki tüm değerler benzersiz olsa da ortalama zincir uzunluğu 8'dir.
    • Bu nedenle, ortalama zincir uzunluğunu 2 veya 3'e yaklaştırmak için kova sayısı artırılmalıdır.
  • Dizin anahtarının benzersiz 262144 değeri olduğundan, demet sayısı en az 262144 olmalıdır.
    • Gelecekteki büyüme bekleniyorsa kova sayısı daha yüksek olmalıdır.

Birincil anahtar dizini (PK_SalesOrd_...):

  • Kovaların 36%'ı boş durumda, bu iyi bir durum.
  • Ortalama zincir uzunluğu 1'dir ve bu da iyidir. Değişiklik gerekmez.

Dengeyi sağlama

OLTP iş yükleri tek tek satırlara odaklanır. Tam tablo taramaları genellikle OLTP iş yükleri için performans açısından kritik yolda değildir. Bu nedenle dengelemeniz gereken denge, bellek kullanımı miktarı ile eşitlik testlerinin performansı veekleme işlemleri arasındadır.

Bellek kullanımı daha önemliyse:

  • Benzersiz dizin anahtarı değerlerinin sayısına yakın bir demet sayısı seçin.
  • Demet sayısı, benzersiz dizin anahtarı değerlerinin sayısından önemli ölçüde düşük olmamalıdır, çünkü bu durum çoğu DML işleminin yanı sıra sunucunun yeniden başlatılmasından sonra veritabanını kurtarma süresini de etkiler.

Eşitlik testlerinin performansı daha önemliyse:

  • Benzersiz dizin değerlerinin iki veya üç katı daha yüksek bir demet sayısı uygundur. Daha yüksek bir sayı şu anlama gelir:
    • Belirli bir değeri ararken daha hızlı veri alımı.
    • Daha fazla bellek kullanımı.
    • Karma dizin tam taraması için gereken sürenin artması.

Ek okuma

Memory-Optimized Tablolar için Karma Dizinleri
Kümelenmemiş Dizinler Memory-Optimized Tablolar için