1

8 つのフィールドで構成される非常に大きなテーブルを作成します (正確ではありません)。

私のアプリケーションでは、この SELECT を繰り返し実行します。

SELECT d1, time, s1, s2 from Collection WHERE (d1 = 1) and (s1 = 1) and (time BETWEEN 5666300000 AND 566630700);

この SELECT を異なる時間範囲で実行します。d1 は s1 と同じ、200 ~ 300 の異なる値を持つフィールドです。主キーは d1、time、s1 です。

テーブル構造とクエリを最適化するためのヒントを探しています。問題は、時間フィールドが昇順/降順ではないことです。したがって、これは時間がかかるクエリになる可能性があります。時間フィールドのインデックス作成について疑問に思っていました。その後、クエリを変更する必要がありますか? 私はその場合、どのように?

表示されていないクエリに問題がありますか? 私のアプリケーションではこれが遅くなります。ありがとう!

4

3 に答える 3

2

他の回答で提案されている主キーの順序には同意しません。

理想的なシナリオ(正確なサンプル クエリの場合)は、関連するすべてのレコードを並べて配置することです。これにより、データに対する単一のシークが有効になります。たとえば、クラスター化(d1, s1, time)された主キーとして使用すると、次のようにデータが保存されます...

 d1 | s1 | time 
----+----+------
  1 |  1 | 1234
  1 |  1 | 1235    \
  1 |  1 | 1236     SELECT * FROM table WHERE d1 = 1 AND s1 = 1 AND time BETWEEN 1235 AND 1237
  1 |  1 | 1237    /
  1 |  1 | 1238
  1 |  2 | 1234
  1 |  2 | 1235
  1 |  2 | 1236
  1 |  2 | 1237
  1 |  2 | 1238

他の人が示唆しているtimeように、クラスター化インデックスの最初のフィールドとして持っている場合、1 つの連続したブロックですべてのデータを取得することはできません。代わりに、個々の時間値ごとに 1 つのシークを取得します...

 time | d1 | s1
------+----+----
 1234 |  1 |  1     *Desired Row 1
 1234 |  1 |  2
 1235 |  1 |  1     *Desired Row 2
 1235 |  1 |  2
 1236 |  1 |  1     *Desired Row 3
 1236 |  1 |  2
 1237 |  1 |  1     *Desired Row 4
 1237 |  1 |  2
 1238 |  1 |  1     *Desired Row 5
 1238 |  1 |  2

この構造は、実際には別のクエリに非常に適しています...

SELECT * FROM yourTable WHERE time = 1234 AND d1 = 1 AND s2 BETWEEN 2 AND 3

これは、単一の普遍的に完全なクラスター化インデックスが存在しないことを示しています。では、クラスター化インデックスは 1 つしか持てないため、クラスター化する対象をどのように選択するのでしょうか?

それは、データとクエリによって異なります。クエリごとに、引き出そうとしている連続したデータ ブロックの数を確認する必要があります。これらのブロックの数を最小限に抑えることは、非常に良い考えです。ただし、GROUP BY または ORDER by 句に適合するようにデータの順序を維持することも同様です。JOIN はこれをさらに複雑にします。

クエリの例では、最初に提案したインデックスが実際に最適です。しかし、すべてのクエリに対してではありません。

また、断片化を考慮する必要があります。データはページに保存され、データが挿入される方法を考慮する必要があります (これについて考えるときは、更新を削除と挿入として扱います)。挿入は通常、既存のデータよりも新しい時間値に対して行われる可能性が高いためtime、クラスター化されたインデックスを最初にすることで、断片化が減少します。

たとえば、各ページには 3 行のデータしか保持できないとします。上で提案された 2 つのインデックスは次のようになります...

 d1 | s1 | time            time | d1 | s1 
----+----+------          ------+----+----
  1 |  1 | 1234 \          1234 |  1 |  1   \
  1 |  1 | 1235  Page 1    1234 |  1 |  2    Page 1
  1 |  1 | 1236 /          1235 |  1 |  1   /
----+----+------          ------+----+----
  1 |  1 | 1237 \          1235 |  1 |  2   \
  1 |  1 | 1238  Page 2    1236 |  1 |  1    Page 2
  1 |  2 | 1234 /          1236 |  1 |  2   /
----+----+------          ------+----+----
  1 |  2 | 1235 \          1237 |  1 |  1   \
  1 |  2 | 1236  Page 3    1237 |  1 |  2    Page 3
  1 |  2 | 1237 /          1238 |  1 |  1   /
----+----+------          ------+----+----
  1 |  2 | 1238 -Page 4    1238 |  1 |  2   -Page 4

では、挿入してみd1 = 1, s1 = 1, time = 1239ます。

 d1 | s1 | time            time | d1 | s1 
----+----+------          ------+----+----
  1 |  1 | 1234 \          1234 |  1 |  1   \
  1 |  1 | 1235  Page 1    1234 |  1 |  2    Page 1
  1 |  1 | 1236 /          1235 |  1 |  1   /
----+----+------          ------+----+----
  1 |  1 | 1237 \          1235 |  1 |  2   \
  1 |  1 | 1238  Page 2    1236 |  1 |  1    Page 2
 *1 |  1 | 1239*/          1236 |  1 |  2   /
----+----+------          ------+----+----
  1 |  2 | 1234 -Page 3    1237 |  1 |  1   \
----+----+------           1237 |  1 |  2    Page 3
  1 |  2 | 1235 \          1238 |  1 |  1   /
  1 |  2 | 1236  Page 4   ------+----+---- 
  1 |  2 | 1237 /          1238 |  1 |  2   -Page 4
----+----+------           1239 |  1 |  1   /
  1 |  2 | 1238 -Page 5

左側のバージョンは、新しいページを作成する必要がありました。右側のバージョンは、既存のページを埋め続けただけです。

断片化が発生した場合、多くの場合、断片化を修正できる保守計画があります。多くの場合、これは夜通しのプロセスです。

それはすべて少し複雑ですよね?まあ、このトピックだけの本があります。

問題が発生するまで、通常は断片化についてあまり心配しません。しかし、それは本当に心に留めておく価値のあるものです。

于 2012-06-20T08:08:14.890 に答える
1

まず第一に、npe が言ったように、時間を Primary として使うべきではありません。にプライマリ インデックスを追加すると思いますtime - d1 - s1。このようにして、主要なプライマリインデックスのような時間を確保できるため、すべての中間が非常に高速になります。そして、d1 と s1 が登場します。また、d1 と s1 はできるだけ小さなデータ型にします。1 と 0 だけの場合は、bool などに入れます。これにより、チェックが高速化されます。

于 2012-06-20T07:34:54.320 に答える
1

time + d1 + s1 (この順序で) でクラスター化インデックス (主キー) を構築することをお勧めします。これにより、データは物理的に時間順に保存され、次に d1 と s1 の順に保存されます。

于 2012-06-20T07:31:42.260 に答える