Bellek İçi Tablonun performansı disk tabanlı bir tablodan daha kötü


10

SQL Server 2014'te aşağıdaki gibi bir tablo var:

CREATE TABLE dbo.MyTable
(
[id1] [bigint] NOT NULL,
[id2] [bigint] NOT NULL,
[col1] [int] NOT NULL default(0),
[col2] [int] NOT NULL default(0)
)

(id1, id2) PK olur. Temel olarak id1, pk id2 olan bir sonuç grubunu (id2, col1, col2) gruplamak için bir tanımlayıcıdır.

Benim darboğaz olan disk tabanlı bir tablodan kurtulmak için bir bellek içi tablo kullanmaya çalışıyorum.

  • Tablodaki veriler bir kez yazılır -> okunur -> silinir.
  • Her id1 değerinin binlerce (on / yüzlerce) binlerce id2 değeri vardır.
  • Veriler çok kısa bir süre, örneğin 20 saniye gibi tabloda depolanır.

Bu tabloda gerçekleştirilen sorgular şunlardır:

-- INSERT (can vary from 10s to 10,000s of records):
INSERT INTO MyTable
  SELECT @fixedValue, id2, col1, col2 FROM AnotherTable

-- READ:
SELECT id2, col1
FROM MyTable INNER JOIN OtherTbl ON MyTable.id2 = OtherTbl.pk
WHERE id1 = @value
ORDER BY col1

-- DELETE:
DELETE FROM MyTable WHERE id1 = @value

İşte tablo için kullandığım geçerli tanım:

CREATE TABLE dbo.SearchItems
(
  [id1] [bigint] NOT NULL,
  [id2] [bigint] NOT NULL,
  [col1] [int] NOT NULL default(0),
  [col2] [int] NOT NULL default(0)

  CONSTRAINT PK_Mem PRIMARY KEY NONCLUSTERED (id1,id2),
  INDEX idx_Mem HASH (id1,id2) WITH (BUCKET_COUNT = 131072)
) WITH (MEMORY_OPTIMIZED = ON, DURABILITY = SCHEMA_ONLY)

Ne yazık ki, bu tanım disk tabanlı bir tablodaki önceki duruma göre performansın düşmesine neden olur. Büyüklük sırası% 10 daha fazla veya daha azdır (bazı durumlarda% 100'e ulaşır, bu nedenle iki kez).

En önemlisi, Microsoft'un reklamını yaptığı kilitsiz mimari göz önüne alındığında, yüksek eşzamanlılık senaryolarında süper bir avantaj elde etmeyi umuyordum. Bunun yerine, en kötü performanslar tam olarak masada birkaç sorgu çalıştıran birkaç eşzamanlı kullanıcı olduğunda gerçekleşir.

Sorular:

  • ayarlanacak doğru BUCKET_COUNT nedir?
  • ne tür bir dizin kullanmalıyım?
  • performans neden disk tabanlı tablodan daha kötü?

Sys.dm_db_xtp_hash_index_stats sorgusu döndürür:

total_bucket_count = 131072
empty_bucket_count = 0
avg_chain_len = 873
max_chain_length = 1009

Ben sys.dm_db_xtp_hash_index_stats çıktı olacak kova sayısını değiştirdi :

total_bucket_count = 134217728
empty_bucket_count = 131664087
avg_chain_len = 1
max_chain_length = 3

Yine de, daha da kötüsü olmasa da, sonuçlar hemen hemen aynıdır.


Parametre koklamaya çalışmadığınızdan emin misiniz? Sorguları çalıştırmayı denediniz mi OPTION(OPTIMIZE FOR UNKNOWN)(bkz. Tablo İpuçları )?
TT.

Sanırım sıra zincir sorunları ile karşılaşıyorsunuz. Bize çıktı verebilir misiniz select * from sys.dm_db_xtp_hash_index_stats ? Ayrıca, bu bağlantı sorularınızın çoğuna / tümüne cevap vermelidir: msdn.microsoft.com/en-us/library/…
Sean Gallardy

4
Karma dizini yalnızca dahil edilen her iki sütundaki tahminler için yararlıdır. Tabloda karma dizini olmadan denediniz mi?
Mikael Eriksson

Bellek içi teknolojiyle en iyi performans iyileştirmelerinin yalnızca yerel olarak derlenmiş saklı yordamlar kullanılarak elde edilebildiğini tespit ettim .
Daniel Hutmacher

@DanielHutmacher FWIW Tüm faydaların mandallamayı kaldırmaktan ve yerel olarak derlenmiş prosedürleri eklemekten kaynaklandığı karşı örnekler gördüm, sıfır veya ihmal edilebilir bir gelişme sağladı. Bir battaniye bildirimi için herhangi bir yer olduğunu sanmıyorum (bu durumda doğru olabilirsiniz, hatta ayrıntılara bile bakmadım).
Aaron Bertrand

Yanıtlar:


7

Bu gönderi eksik bilgi nedeniyle tam bir cevap olmasa da, sizi doğru yöne yönlendirebilir veya daha sonra toplulukla paylaşabileceğiniz bir fikir edinebilmelidir.

Ne yazık ki, bu tanım disk tabanlı bir tablodaki önceki duruma göre performansın düşmesine neden olur. Büyüklük sırası% 10 daha fazla veya daha azdır (bazı durumlarda% 100'e ulaşır, bu nedenle iki kez).

En önemlisi, Microsoft'un reklamını yaptığı kilitsiz mimari göz önüne alındığında, yüksek eşzamanlılık senaryolarında süper bir avantaj elde etmeyi umuyordum. Bunun yerine, en kötü performanslar tam olarak masada birkaç sorgu çalıştıran birkaç eşzamanlı kullanıcı olduğunda gerçekleşir.

Kesinlikle durum böyle olmamalı çünkü bu rahatsız edici. Bellek tablolarında (SQL 2014) bazı iş yükleri için kullanılmaz ve bazı iş yükleri buna katkıda bulunur. Çoğu durumda, yalnızca uygun dizinleri geçirip seçerek performansta minimum bir artış olabilir.

Aslında bununla ilgili sorularınız hakkında çok dar düşünüyordum:

Sorular:

  • ayarlanacak doğru BUCKET_COUNT nedir?
  • ne tür bir dizin kullanmalıyım?
  • performans neden disk tabanlı tablodan daha kötü?

Başlangıçta bellek tablosunda gerçek bir sorun olduğuna inandım ve indeksler optimal değildi. Bellek için optimize edilmiş karma indeks tanımı ile ilgili bazı sorunlar olsa da ben gerçek sorunun kullanılan sorguları ile olmak inanıyorum.

-- INSERT (can vary from 10s to 10,000s of records):
INSERT INTO MyTable
  SELECT @fixedValue, id2, col1, col2 FROM AnotherTable

Bu ek, yalnızca bellek tablosunda yer alıyorsa son derece hızlı olmalıdır. Bununla birlikte, disk tabanlı bir tablo da içerir ve bununla ilişkili tüm kilitleme ve engellemeye tabidir. Böylece, burada gerçek zamanlı atık disk tabanlı tablo üzerinde.

Verileri belleğe yükledikten sonra disk tabanlı tablodan 100.000 satır ekine karşı hızlı bir test yaptığımda - ikinci yanıt süreleri oldu. Ancak, verilerinizin çoğu yalnızca 20 saniyeden daha kısa bir süre için saklanır. Bu gerçekten önbellekte yaşamak için fazla zaman vermez. Ayrıca AnotherTablegerçekte ne kadar büyük olduğundan emin değilim ve değerlerin diskten okunup okunmadığını bilmiyorum. Bu cevaplar için size güvenmeliyiz.

Seçim sorgusu ile:

SELECT id2, col1
FROM MyTable INNER JOIN OtherTbl ON MyTable.id2 = OtherTbl.pk
WHERE id1 = @value
ORDER BY col1

Yine, birlikte çalışma + disk tabanlı tablo performansının merhametindeyiz. Ayrıca, HASH dizinlerinde türler ucuz değildir ve kümelenmemiş bir dizin kullanılmalıdır. Bu, yorumlarda bağladığım Dizin kılavuzunda çağrılır .

Bazı gerçek araştırma tabanlı gerçekleri vermek için SearchItems, bellek tablosuna 10 milyon satır ve AnotherTable100.000 ile yükledim, çünkü gerçek boyutunu veya istatistiklerini bilmiyordum. Daha sonra yürütmek için yukarıdaki seçme sorgusunu kullandım. Ayrıca wait_completed üzerinde genişletilmiş olaylar oturumu oluşturdum ve bir halka arabelleğe koydu. Her çalıştırmadan sonra temizlendi. Ayrıca, tüm verilerin bellekte yerleşik olmayabileceği DBCC DROPCLEANBUFFERSbir ortamı simüle etmeye çalıştım .

Sonuçlar, boşlukta bakıldığında muhteşem bir şey değildi. Bunu test ettiğim dizüstü bilgisayar daha yüksek sınıf SSD kullandığından, kullandığım VM için yapay olarak disk tabanlı performansı düşürdüm.

Yalnızca bellek tabanlı tablodaki sorgunun 5 çalıştırılmasından sonra (birleştirme ve alt sorguları kaldırmadan) sonuçlar bekleme bilgisi olmadan geldi. Bu beklendiği gibi.

Orijinal sorguyu kullanırken, ancak, bekledim. Bu durumda veriler diskten okunurken mantıklı olan PAGEIOLATCH_SH idi. Bu sistemdeki tek kullanıcı olduğum ve ekler, güncellemeler, birleştirilmiş tabloya karşı silmeler için büyük bir test ortamı oluşturmak için zaman harcadığım için herhangi bir kilitleme veya engellemenin yürürlüğe girmesini beklemiyordum.

Bu durumda, zamanın önemli bir kısmı disk tabanlı tabloya harcandı.

Son olarak silme sorgusu. Yalnızca ID1 tabanlı satırları bulmak, bir dizin ile son derece verimli değildir. Eşitlik tahminlerinin karma indeksleri için uygun olduğu doğru olsa da, verilerin düştüğü bölüm tüm karma sütunları temel alır. Bu nedenle id1, id2, burada id1 = 1, id2 = 2 ve id1 = 1, id2 = 3, karma (1,2) ve (1,3) arasında olacağından farklı bölümlere ayrılır. Karma dizinleri aynı şekilde yapılandırılmadığından, bu basit bir B-Ağacı aralığı taraması olmaz. Daha sonra bunun bu işlem için ideal bir dizin olmasını beklemezdim, ancak daha büyük boyutta siparişleri daha uzun süre almasını beklemem. Ben wait_info bu konuda ilgilenen olacaktır.

En önemlisi, Microsoft'un reklamını yaptığı kilitsiz mimari göz önüne alındığında, yüksek eşzamanlılık senaryolarında süper bir avantaj elde etmeyi umuyordum. Bunun yerine, en kötü performanslar tam olarak masada birkaç sorgu çalıştıran birkaç eşzamanlı kullanıcı olduğunda gerçekleşir.

Kilitlerin mantıksal tutarlılık için kullanıldığı doğru olsa da, işlemler hala atomik olmalıdır. Bu, özel bir CPU tabanlı karşılaştırma operatörü aracılığıyla yapılır (bu nedenle In-Memory yalnızca belirli [son 4 yılda yapılan tüm cpuslar da olsa) işlemcilerle çalışır). Bu yüzden her şeyi ücretsiz olarak almıyoruz, bu işlemleri tamamlamak için hala biraz zaman olacak.

Ortaya konması gereken bir başka nokta, neredeyse tüm sorgularda kullanılan arayüzün, en az bir disk tabanlı tabloya dokunan T-SQL (ve doğal olarak derlenmiş SPROC'lar değil) olmasıdır. Bu yüzden, sonuçta, disk tabanlı tabloların performansıyla hala sınırlı olduğumuz için aslında herhangi bir performansımızın olmadığına inanıyorum.

Takip et:

  1. Wait_completed için genişletilmiş bir etkinlik oturumu oluşturun ve bildiğiniz bir SPID'yi belirtin. Sorguyu çalıştırın ve çıktıyı bize verin veya dahili olarak tüketin.

  2. Bize # 1'in çıktısı hakkında bir güncelleme verin.

  3. Karma indeksleri için kova sayısını belirlemek için sihirli bir sayı yoktur. Temel olarak kovalar tamamen dolmadığı ve sıra zincirleri 3 veya 4'ün altında kaldığı sürece, performans kabul edilebilir kalmalıdır. Bu, "Günlük dosyamı neye ayarlamalıyım?" - işlem başına, veritabanı başına, kullanım türüne bağlı olacaktır.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.