web-dev-qa-db-ja.com

タイムスタンプにインデックスを作成してクエリを最適化する

次の形式のクエリがあります。

SELECT * FROM MyTable WHERE Timestamp > [SomeTime] AND Timestamp < [SomeOtherTime]

このクエリを最適化したいので、タイムスタンプにインデックスを付けることを考えていますが、これが役立つかどうかはわかりません。理想的には、タイムスタンプをクラスター化インデックスにしたいと考えていますが、MySQLは主キーを除いてクラスター化インデックスをサポートしていません。

  • MyTableには400万行以上あります。
  • Timestampは実際にはINT型です。
  • 行が挿入されると、変更されることはありません。
  • 特定のTimestampを含む行の数は平均で約20ですが、最大で200になる可能性があります。
  • 新しく挿入された行には、既存の行のほとんどよりも大きいTimestampがありますが、最近の行の一部よりも小さい場合があります。

Timestampのインデックスは、このクエリを最適化するのに役立ちますか?

49
DanielGibbs

それについての質問はありません。インデックスがない場合、クエリはテーブル内のすべての行を調べる必要があります。インデックスを使用すると、適切な行を見つける限り、クエリはほとんど瞬時に実行されます。お支払いいただく価格は、わずか挿入のパフォーマンス低下です。しかし、それは本当にわずかです。

49
Chris Nash

必ずインデックスを使用する必要があります。 MySQLには、これらのタイムスタンプの順序がわからないため、特定のタイムスタンプ(またはタイムスタンプ範囲)のレコードを見つけるには、すべてのレコードを調べる必要があります。そして、それらの400万で、それはかなりの時間です!インデックスは、MySQLにデータを伝える方法です。「このフィールドを頻繁に確認するので、各値のレコードを見つけることができる場所のリストを保持してください。」

一般的にインデックスは、定期的にクエリされるフィールドに適しています。インデックスを定義する唯一の欠点は、追加のストレージスペースを使用することです。そのため、スペースが本当に限られている場合を除いて、インデックスを使用する必要があります。それらが適用されない場合、MySQLはとにかくそれらを無視します。

7
Ryan P

クエリが主にこのタイムスタンプを使用している場合、この設計をテストできます(最初の部分としてタイムスタンプを使用して主キーを拡大します)。

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(およびオープンソース)バリアントもご覧ください。

5
ypercubeᵀᴹ

選択クエリの時間を改善するためのインデックスの重要性には同意しませんが、他のキーでインデックスを作成できる場合(およびこれらのインデックスを使用してクエリを作成できる場合)、タイムスタンプでインデックスを作成する必要はありません。

たとえば、timestampcategory、およびuserIdを含むテーブルがある場合は、代わりにuserIdにインデックスを作成することをお勧めします。多くの異なるユーザーがいるテーブルでは、これにより、タイムスタンプを検索する残りのセットが大幅に削減されます。

...そして、私が間違っていない場合、これの利点は、各挿入でタイムスタンプインデックスを作成するオーバーヘッドを回避することです-高い挿入率と非常にユニークなタイムスタンプを持つテーブルでは、これは重要な考慮事項です。

タイムスタンプやその他のキーに基づくインデックス作成の同じ問題に苦労しています。ここで言うことの裏に証拠を置くことができるように、私はまだ行うべきテストを持っています。結果に基づいてポストバックを試みます。

より良い説明のためのシナリオ:

  1. タイムスタンプ99%一意
  2. userId 80%一意
  3. カテゴリ25%ユニーク

    • タイムスタンプでのインデックス作成により、クエリ結果がテーブルサイズの1%にすばやく減少します。
    • UserIdでインデックスを作成すると、クエリ結果がテーブルサイズの20%にすばやく減少します。
    • カテゴリのインデックス作成により、クエリ結果がテーブルサイズの75%にすばやく削減されます。
    • タイムスタンプにインデックスを挿入すると、オーバーヘッドが高くなります**
    • 挿入はタイムスタンプの増分という事実を尊重するという知識があるにもかかわらず、増分キーに基づくMySQL最適化の議論は見当たりません。
    • UserIdにインデックスを挿入すると、かなり高いオーバーヘッドが発生します。
    • カテゴリにインデックスを挿入すると、オーバーヘッドがかなり低くなります。

**申し訳ありませんが、計算されたオーバーヘッドまたはインデックス作成による挿入がわかりません。

4
blackstrype