次の形式のクエリがあります。
SELECT * FROM MyTable WHERE Timestamp > [SomeTime] AND Timestamp < [SomeOtherTime]
このクエリを最適化したいので、タイムスタンプにインデックスを付けることを考えていますが、これが役立つかどうかはわかりません。理想的には、タイムスタンプをクラスター化インデックスにしたいと考えていますが、MySQLは主キーを除いてクラスター化インデックスをサポートしていません。
MyTable
には400万行以上あります。Timestamp
は実際にはINT
型です。Timestamp
を含む行の数は平均で約20ですが、最大で200になる可能性があります。Timestamp
がありますが、最近の行の一部よりも小さい場合があります。Timestamp
のインデックスは、このクエリを最適化するのに役立ちますか?
それについての質問はありません。インデックスがない場合、クエリはテーブル内のすべての行を調べる必要があります。インデックスを使用すると、適切な行を見つける限り、クエリはほとんど瞬時に実行されます。お支払いいただく価格は、わずか挿入のパフォーマンス低下です。しかし、それは本当にわずかです。
必ずインデックスを使用する必要があります。 MySQLには、これらのタイムスタンプの順序がわからないため、特定のタイムスタンプ(またはタイムスタンプ範囲)のレコードを見つけるには、すべてのレコードを調べる必要があります。そして、それらの400万で、それはかなりの時間です!インデックスは、MySQLにデータを伝える方法です。「このフィールドを頻繁に確認するので、各値のレコードを見つけることができる場所のリストを保持してください。」
一般的にインデックスは、定期的にクエリされるフィールドに適しています。インデックスを定義する唯一の欠点は、追加のストレージスペースを使用することです。そのため、スペースが本当に限られている場合を除いて、インデックスを使用する必要があります。それらが適用されない場合、MySQLはとにかくそれらを無視します。
クエリが主にこのタイムスタンプを使用している場合、この設計をテストできます(最初の部分としてタイムスタンプを使用して主キーを拡大します)。
CREATE TABLE perf (
, ts INT NOT NULL
, oldPK
, ... other columns
, PRIMARY KEY(ts, oldPK)
, UNIQUE (oldPK)
) ENGINE=InnoDB ;
これにより、投稿したようなクエリがクラスター化(プライマリ)キーを使用するようになります。
欠点は、挿入が少し遅くなることです。また、テーブルに他のインデックスがある場合、それらは4バイト幅の主キーを含むため、もう少しスペースを使用します。
このようなクラスター化インデックスの最大の利点は、大きな範囲のスキャンを使用するクエリです。テーブルの大部分またはテーブル全体を読み取らなければならないクエリは、関連する行を必要な順序で順番に検索します(BY timestamp
)。これは、日または週または月または年でグループ化する場合にも役立ちます。
古いPKは、UNIQUE
制約を保持することで行を識別するために引き続き使用できます。
TokuDB 、 複数のクラスター化されたインデックス を許可するMySQL(およびオープンソース)バリアントもご覧ください。
選択クエリの時間を改善するためのインデックスの重要性には同意しませんが、他のキーでインデックスを作成できる場合(およびこれらのインデックスを使用してクエリを作成できる場合)、タイムスタンプでインデックスを作成する必要はありません。
たとえば、timestamp
、category
、およびuserId
を含むテーブルがある場合は、代わりにuserId
にインデックスを作成することをお勧めします。多くの異なるユーザーがいるテーブルでは、これにより、タイムスタンプを検索する残りのセットが大幅に削減されます。
...そして、私が間違っていない場合、これの利点は、各挿入でタイムスタンプインデックスを作成するオーバーヘッドを回避することです-高い挿入率と非常にユニークなタイムスタンプを持つテーブルでは、これは重要な考慮事項です。
タイムスタンプやその他のキーに基づくインデックス作成の同じ問題に苦労しています。ここで言うことの裏に証拠を置くことができるように、私はまだ行うべきテストを持っています。結果に基づいてポストバックを試みます。
より良い説明のためのシナリオ:
カテゴリ25%ユニーク
**申し訳ありませんが、計算されたオーバーヘッドまたはインデックス作成による挿入がわかりません。