9

テーブルBlah(緯度浮動小数点数、経度浮動小数点数、create_time date、owner_id int、.....)がありました

私のコードは単一のクエリのみを実行します

select * 
from Blah 
where latitude < l1 and latitude > l2   
and longitude < ll1 and longitude > ll2   
and create_time < t1 and create_time > t2 
and owner_id < o1 and owner_id > o2 ;

(もちろん、値l1、l2、....o1、o2はプログラムからの動的パラメーターです)

私の質問は、どのような種類のインデックスを作成する必要があるかです。合成指数?複合インデックスの場合、どの列を最初に配置する必要がありますか? インデックスの効果は?

私はこれについて長い間考えていましたが、オラクルのインデックスがどのように機能するかについての詳細なドキュメントを見つけることができませんでした.

私たちの場合、B ツリーを使用して実装されているドキュメントを見つけることができます。注文。

次に、上記のクエリの場合、順序が (owner_id、create_time、緯度、経度) であると仮定すると、オラクルは最初にポイント ( o1、t1、l1、ll1) までバイナリ検索する必要があると思います。この操作では、インデックスは確かに使える。しかし次に、この最初の境界の終点を見つける必要があります: (o1,t1, l1, ll2 ) を見つける必要があります。これは二分探索でも行うことができます。

次に、条件を満たす次のセクションを見つける必要があるため、(o1, t1, lx, ll1 ) を見つける必要があります。ここで、lx は l1 よりも大きい次の値です。これも二分探索で見つけることができます。しかし、私たちの場合、同じ緯度に対して経度は 1 つしか存在しない可能性が非常に高いため、ここではバイナリ サーチはリニア スキャンよりも効果的ではありません。

この精神に従って、ポイントが数日しか作成されない場合は、値の範囲のカーディナリティが小さい列 (この場合は create_time) を最初に配置する必要があるようです。また、範囲条件を実行せず、等号 (=) 条件のみを実行する場合、どの列が最初かは問題ではありませんよね?

わかりやすくするために、より簡単な例を次に示します。

XとYの2つの列があるとしましょう

データベースでは、両方の値が [1,2,....100] であるため、100x100 行になります。

私のクエリは

select * from mytable where X > 34 and X < 78 and Y > 12 and Y < 15;

インデックスが (X, Y) にあるとすると、2 つの値の比較規則は次のようになります。

v1 < v2 <=====>  v1.x < v2.x || v1.x == v2.x && v1.y < v2.y

上記の順序付けルールを考えると、インデックスの値が (x、y の値) のように連続して配置されていることがわかります。

1,1, 1,2 1,3 .... 1,100     
2,1  2,2 2,3 ......2,100
.....
100,1 100,2 ....... 100,100

ここで、クエリで値を検索するには、B ツリー トラバーサルで (78-​​34-1) 間隔を見つける必要があるため、(78-34-1)*2 ルックアップ (最初は 1 つ、最後の場所は 1 つ) 、2回のルックアップだけではありません。

したがって、次元が高くなると、間隔カウントは次元の数に応じて指数関数的に増加するため、インデックス作成はもはや役に立たない可能性があります ------ これは私の懸念事項です

どうもありがとうヤン

4

5 に答える 5

9

このクエリを最適化するためのインデックスを作成することが唯一の目的である場合は、複合インデックスの列を最も選択的な列から順に並べることをお勧めします。述語 onlatitudeが他の述語よりも実質的に多くの行を削除する場合、その列を最初に持つ方が効率的です。述語 onowner_idが他の述語よりも実質的に多くの行を削除する場合、その列を最初に持つ方が効率的です。

ただし、実際には、単一のクエリを最適化することのみを目的としたインデックスを作成することはほとんどありません。一般に、インデックス メンテナンスのオーバーヘッドを価値のあるものにするために、インデックスが多くのクエリで役立つようにしたいと考えています。複合インデックスの場合、これは、クエリがその列に述語を持つ確率によって列を並べ替えることを意味します。たとえば、に複合インデックスがある場合owner_id, create_time, latitude, longitude、 で述語を指定するだけのクエリにそれを使用できますowner_id。しかし、現実的には、述語 on を指定するだけのクエリにそのインデックスを使用することはありませんlongitude

于 2012-05-04T17:26:05.150 に答える
3

まず、「Bツリー」の「B」は「バイナリ」ではないことに注意してください。

次に、Oracleでのインデックス作成に関しては、次の場合にビットマップインデックスを選択することもできます。

  1. エンタープライズエディションのライセンスがあります
  2. テーブルを同時に変更するセッションは多くありません
  3. インデックス付けされた値は一意に近くありません(ビットマップインデックスはカーディナリティの低い列にのみ使用できるという記述は一般的に誇張されています)

ビットマップインデックスが優れているクエリの1つのタイプは、特に述語列のセットが変化する場合に、複数の列の述語を効率的に組み合わせることにあります(もちろんそうではない場合があります)。上記の3つの条件を満たしている場合は、テーブルに4つの個別のビットマップインデックスがあることの影響をテストする価値があります。

于 2012-05-18T09:51:30.843 に答える
1

簡単な強引な解決策の 1 つは、同じテーブルに複数のインデックスの組み合わせを作成し、EXPLAIN PLANをオンにしてクエリを実行し、DBMS が使用することを好むインデックスを選択することです。

于 2012-05-23T01:32:12.857 に答える
0

多次元範囲クエリは、標準の B ツリー インデックスの外で処理するのが最適です。一般的なトピックに関するいくつかの論文は、「多次元範囲クエリ」に関する Web 検索で見つけることができます。

Oracle は、Oracle Spatial という製品を提供しています。この製品のドキュメントには、第 4 章に、空間インデックスの作成とクエリの実行に関する例と説明が含まれています。新しい SQL 構文はありません。インデックス作成の例は次のとおりです。

CREATE INDEX territory_idx ON territories (territory_geom)
    INDEXTYPE IS MDSYS.SPATIAL_INDEX;

R ツリー インデックスを作成します。

R ツリー、kdb ツリー、および同様の空間構造の存在は、標準の B ツリーがおそらくこれらの種類のアプリケーションに適していないという事実の証拠だと思います。

于 2012-05-18T17:49:34.867 に答える
0

このテーブルは OLTP または DWH として使用されますか? このテーブルに単一行/マルチスレッド DML ステートメントがあまりない場合は、ビットマップ インデックスを使用できます。ビットマップ インデックスを使用すると、複数のインデックス間で ROWID AND 演算子を使用できます (別名スター型変換)。これを行うには、各列にビットマップ インデックスを作成します。私が言ったように、このソリューションは、単一のバッチ挿入がある DWH システムに最適です。

于 2012-05-18T12:41:15.390 に答える