2016-06-12 23 views
3

現在最適化しようとしているワイドテーブルがあります。テーブルには、最終的に降順でランク付けする50個の列(統計)があります。現在、500万行を超えています。SQL Serverのランキング最適化インデックス

この表を最適化する方法は、複雑さの軽減と読み取り速度の向上の両方の面で優れています。書き込み速度も私たちにとって重要ですが、読み取りはより重要です。これらの統計のランクは、できるだけリアルタイムに近いものでなければならず、最適なソリューションはリクエストごとに素早くランク付けされます(新しい行が常に追加されており、できるだけ早くこれらの行のランクを表示したい。)

私たちは現在、縦型テーブルレイアウトがa)より優れているかどうかを評価しています。挿入されている統計は、必ずしも明確に定義されていないので

、それは彼らが、ハード表にコード化されていない場合はここで

(垂直テーブル構造のため、したがって好み。)私たちのために簡単です見ます私たちの現在のテーブル構造とクエリ:

CREATE TABLE Stats 
(
    Id BIGINT PRIMARY KEY NOT NULL, 
    UserId INT, 
    Name VARCHAR(32) NOT NULL, 
    Value DECIMAL(10,4) DEFAULT ((0)) NOT NULL, 
    UpdatedAt DATETIME 
); 

CREATE INDEX Leaderboard__index ON Stats (Name, Value DESC); 

SELECT 
    Id, 
    Name, 
    Value, 
    RANK() OVER (PARTITION BY Name ORDER BY Value DESC) AS Rank 
FROM 
    Stats 
ORDER BY 
    Value DESC 

は、一般的に、我々は(リーダーボードのような)任意のstatのトップN行を検索することだろうか、我々は、単一のユーザーIDを選択すると、すべてのランクを取得すると思いますそのUserIdに関連付けられた統計。

データはかなりのサイズです(前述のように、行数が多く、列数が多いため、垂直テーブル構造は2億5,000万行の範囲にあり、成長を続けます)

ハードウェアが必要な場合はできるだけ早くこのデータを取得したいと考えていますが、現在は分単位で秒が目標です。 (それはまた、唯一の10,000行をランク付けするのに約18秒かかりませんでしたけれども。)我々40万行のデータと上記のクエリの上に挿入した垂直のテーブル構造の試験で

は3分弱かかり

私は何か提案を聞いてほしいです。御時間ありがとうございます!

+1

あなたはSQLのバージョンを使用してタグを更新することができますサーバー、また、どのエディションを使用しているか(標準、エンタープライズなど) Ta。 –

+0

上記に基づいて、スコアを持つ「名前」ごとにトップ100ランクのユーザーリストを維持する別のテーブルを作成することをお勧めします。これにより、データサイズは大幅に削減されますが、トップ100以外のユーザーのランキングは許可されません。 – Alex

+0

@Alexトップ10,000行をフェッチすると、サーバーからの往復がわずか数百ミリ秒かかります。トップNテーブルの設計は、私たちのUI設計に基づいています。トップ100を見ることから100,000行を100,000のオフセットで見ることは自明です。 – lwansbrough

答えて

7

あなたが持っているインデックスは

1.Toは、ID列の値を取得しているため、SQLは、キー検索をやって終わるかさえ、それはTipping pointを横切る場合、全体他のインデックスをスキャンし終わる可能性があり、あなたの窓の機能のために便利ではありません。あなたのインデックスはまったく使用できません。

2.Youは、適切な指標ともさえendup spilling to TEMPDB

3なしでソートを必要とするvalの降順で発注されています。列によってパーティションと順序 - ウィンドウ機能がうまく実行するもう一つの興味深いfragmenationの側面について、あなたは

P、Oを意味POCインデックスが必要になります、通常

下記参照キー句であるべき
C - あなたが選択に含めているカバー--columnsが最適に動作するようにクエリ下記のためにそう

を含めるべきです。

SELECT 
    Id, 
    Name, 
    Value, 
    RANK() OVER (PARTITION BY Name ORDER BY Value DESC) AS Rank 
FROM 
    Stats 
ORDER BY 
    Value DESC 

あなたは "value desc" で作成したインデックスを持つもう一つの問題があり、インデックス

create index nci_test on dbo.table(name,value desc) 
include(id) 

の下に必要になります。

通常、インデックスにはすべての値がデフォルトで昇順に格納されますが、このインデックスを使用すると、逆の方法で格納することが要求されます。answerから見ることができる論理的な断片化が発生する可能性があります。ここの答えからの用語...

インデックスがキーの降順で作成されますが、新しい行に昇順のキー値が追加されると、すべてのページが論理的な順序から外れることがあります。これは深刻な..

1.Runインデックスは、それが助けかどうかを確認するためにあなたの周波数に基づいて再構築テーブルをスキャンするときにIOのサイズは読み込み、それがキャッシュにそういくつかのオプション

ない影響を与える可能性がインデックスは、「ヴァルDESC」オプション

SELECT 
     Id, 
     Name, 
     Value, 
     RANK() OVER (PARTITION BY Name ORDER BY Value DESC) AS Rank 
    FROM 
     Stats 
    ORDER BY 
     name DESC 

上記のクエリのdoesntを使用して作成することの必要性を排除するパーティション句で注文するクエリを2.Changing

インデックスを作成するリットルを必要としますIKEあなたはbelow..whichも

CREATE INDEX Leaderboard__index ON Stats (Name, Value) 
include(id); 

参考文献上で述べたフラグメンテーション側面の世話をするように。あなたはそれを変更することができます作成​​した1:
Microsoft SQL Server 2012 High-Performance T-SQL Using Window Functions

+0

うわー、信じられないほど慎重な対応に感謝します。私は今それを試してみるつもりです。 – lwansbrough

+0

あなたはウィザードです。 '1700年代に1から始まる400000行386ms(実行:238ms、取得:17秒148ms)' – lwansbrough

関連する問題