SQL Server 2014に次のようなテーブルがあります。
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です。基本的に、id1は結果のセット(id2、col1、col2)をグループ化する識別子であり、pkはid2です。
私のボトルネックである既存のディスクベースのテーブルを取り除くために、メモリ内のテーブルを使用しようとしています。
- テーブル内のデータが書き込まれます->読み取り->一度削除されます。
- 各id1値には、数千(数十/数十万)のid2があります。
- データは、非常に短時間、たとえば20秒の間、テーブルに保存されます。
このテーブルで実行されるクエリは次のとおりです。
-- 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
これが、テーブルに使用した現在の定義です。
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)
残念ながら、この定義では、ディスクベースのテーブルに関する以前の状況と比較してパフォーマンスが低下します。大きさの順序は多かれ少なかれ10%高くなります(場合によっては100%に達するため、2倍の時間になります)。
何よりも、マイクロソフトがアドバタイズしたロックフリーアーキテクチャを考えると、同時実行性の高いシナリオで非常に有利になると期待していました。代わりに、最悪のパフォーマンスは、テーブルに対して複数のクエリを実行している複数の同時ユーザーがいる場合です。
質問:
- 設定する正しいBUCKET_COUNTはいくつですか?
- どのようなインデックスを使用する必要がありますか?
- なぜディスクベースのテーブルよりもパフォーマンスが悪いのですか?
sys.dm_db_xtp_hash_index_statsのクエリは次を返します:
total_bucket_count = 131072 empty_bucket_count = 0 avg_chain_len = 873 max_chain_length = 1009
sys.dm_db_xtp_hash_index_statsからの出力が次のようになるようにバケット数を変更しました。
total_bucket_count = 134217728 empty_bucket_count = 131664087 avg_chain_len = 1 max_chain_length = 3
それでも、結果は悪くはないとしても、ほとんど同じです。
select * from sys.dm_db_xtp_hash_index_stats
か?また、このリンクは、あなたの質問のすべて/ほとんどに答える必要があります。msdn.microsoft.com/en-us/library/...
OPTION(OPTIMIZE FOR UNKNOWN)
(表のヒントを参照)?