2

私たちは、鳥の記録の大規模な(そして成長している)MySQL データベースを持っています。現在、次のように簡略化された 3 つのメイン テーブルがあります。

RECORDS (id, birdid, tripid, gender, age) PRIMARY KEY id
BIRDTRIPS (id, locid, date, starttime, endtime, notes) PRIMARY KEY id
LOCATIONS (id, description, centerlat, centerlng) PRIMARY KEY id

すべての ID は INT で、日付は DATE 型です。

パフォーマンスを向上させるために、日付と locid を RECORDS に複製することで非正規化を行うことにしました。

RECORDS (id, birdid, tripid, gender, age, locid, date) PRIMARY KEY id

このようにして、多くのクエリで BIRDTRIPS と LOCATIONS への高価な結合を回避できます。

MySQL にはテーブルごとにクラスター化されたインデックスが 1 つだけあり、これが常に主キーになります。RECORDS
を試しPRIMARY KEY (date, id)て、クラスター化されたインデックスを活用して、日付列の範囲スキャンとテーブルのパーティション分割を高速化しようとしています。同じ日付に多くのレコードが存在する可能性があるため、ID はキーにのみ含まれています。理論的には、主キーは多くの場合、ID で「無駄」になることが多く、ルックアップにはクラスター化されていない UNIQUE インデックスで十分です。

そして今、私の質問:

このアプローチで実際の経験をお持ちの方はいらっしゃいますか? 私が見落としているかもしれない欠点はありますか?

4

1 に答える 1

1

誰かがそれに出くわした場合に備えて、私は自分の質問に答えます。このアプローチのパフォーマンスがテストされているこの非常に素晴らしいブログ投稿を見つけました:クラスター化されたインデックス作成とクエリのパフォーマンス

ブログ投稿で行われた実験の結論は次のとおりです。

長所:

  1. 複合主キー (私の場合は ) を使用するとPRIMARY KEY (date, id)、日付範囲クエリが約 9 倍高速化されます。

  2. 日付範囲クエリのパフォーマンスは、テーブルが大きくなってもほぼ一定のままですが、主キーが「id」のみにある場合は徐々に低下します。

短所:

  1. 「id」列の単純なルックアップ (テーブルの結合など) は、複合インデックスを使用するとほぼ 3 倍遅くなります。

  2. クラスター化インデックスが大きくなると、ディスク使用率が著しく高くなります。これは、他のすべてのインデックスがクラスター化インデックスを指しているためです。つまり、クラスター化インデックスが大きいと、他のすべてのインデックスのサイズが大きくなります。これにより、メモリに収まるテーブルが少なくなるため、クエリのキャッシュ ヒットが少なくなる可能性があります。

したがって、テーブルに対するクエリの大部分がビジネス クリティカルな日付範囲クエリであり、システムがルックアップのペナルティを "許容" できる場合は、このアプローチが役立つ可能性があります。

私自身の結論は、私は本番環境でこれを敢えてしないということです。代わりに、日付列の YEAR でテーブルのパーティション分割を行い、日付範囲クエリでの完全なテーブル スキャンを防ぎます。

これが、同様の課題に直面している誰かの助けになることを願っています。

于 2014-08-05T12:22:16.743 に答える