8DのZオーダー







自己相似スイープ曲線に基づくインデックスは、空間データ検索の整理だけでなく適切です。 それらは、整数格子上に置かれた異種データに対して機能します。



カットの下で、 Zカーブを使用してOLAPキューブに注目して8次元インデックスを実装する可能性をテストします。



前のシリーズの要約。



以前(1、2、3、4、5)、Z曲線に基づくインデックスが空間検索の編成に非常に適していることが示されました。 (バッファキャッシュに制限がない場合)速度は従来使用されているRツリーに非常に近いですが、著しくコンパクトであり、ビルドが高速で、ランダムデータを恐れず、検索時に読み取りが少なくなります。



恐怖



技術的には、このようなインデックスを実装するのに複雑なことはありません;必要なのは、8次元キーの処理を行うことだけでした。 Dimension 8は技術的な理由から選択されました。7次元のインデックスが必要な場合、座標の1つにゼロを追加しても安全です。速度はほとんど変わりませんが、キーが長くなります。 必要に応じて、16次元のキーなど、長くすることを妨げるものはありません。



どんな落とし穴が私たちに期待できるか、そしてそれに対して何をすべきかを事前に考える価値があります。





ベンチマーク



次の表は、いくつかの種類のクエリの結果をまとめたものです(以下で説明)。

データ-側面[0 ... 1 000 000]を持つ8次元立方体に均等に分布する100 000 000のランダムポイント。



測定(以前と同様)は、2つのコアと4 GBのRAMを備えた仮想マシンで実行されたため、時間は絶対値ではありませんが、読み取りページ数を信頼できます。

ホットサーバーと仮想マシンでの2回目の実行で時間が表示されます。 読み取られたバッファーの数は、新しく生成されたサーバー上にあります。



詳細
  • ここにコミットがあります:(SHA-1:36dd ... 76c7)

  • gawk -f gendata.awk〉 data.csv

     BEGIN {
       for(i = 0; i <100000000; i ++)
       {
         x = int(1000000 * rand());
         y = int(1000000 * rand());
         z = int(1000000 * rand());
         a = int(1000000 * rand());
         b = int(1000000 * rand());
         c = int(1000000 * rand());
         print "{" x "、" y "、" z "、" a "、" b "、" c "、" a "、" b "}";
       }
     } 
    「a」と「b」が2回出会うことに注意してください。縮退したデータがあり、実際の次元は6です。

  • create table test_points_8d (p integer[8]);





  • COPY test_points_8d from '/home/.../postgresql/contrib/zcurve/data.csv';





    10分

  • \ dt +

    スキーマ| 名前| タイプ| オーナー| サイズ| 説明 
     ------- + ---------------- + ------- + ---------- + ------ --- + -------------
    公開|  test_points_8d | テーブル| ポストグレス|  8056 MB | 
    


  • create index zcurve_test_points_8d on test_points_8d (zcurve_num_from_8coords (p[1], p[2], p[3], p[4], p[5], p[6], p[7], p[8]));





    15分

  • \ di +

    スキーマ| 名前| タイプ| オーナー| テーブル| サイズ| 
     -------- + ----------------------- + ------- + --------- -+ --------------- + ------- + ---
     公開|  zcurve_test_points_8d | インデックス| ポストグレス|  test_points_8d |  4743 MB  
    


  • 確認リクエスト
     select c, t_row from (select c, (select p from test_points_8d t where c = t.ctid) t_row from zcurve_8d_lookup_tidonly('zcurve_test_points_8d', 237000,291000,845000,152000,585000,193000,152000,585000, 247000,301000,855000,162000,595000,203000,162000,595000) as c) x;
          
          



    返す

    c | t_row

    ------+-----------------------------------------------------------

    (0,1) | {237787,291065,845813,152208,585537,193475,152208,585537}







    必要に応じて





リクエストタイプ NPoints Nreq 時間(ミリ秒) 読みます 共有ヒット
10,000のすべて

1.1e-4 100,000 .46 2.0175 15.3919
すべて100,000

73.9 10,000 47 57.3063 1604.18
3X100,000 +

5x10,000
0.0837 10,000 .9 8.7637 73.8852
2X100,000 +

6x10,000
0.0096 10,000 .66 5.1771 40.9089
1全体+

1X100,000 +

6X10,000
0.0978 10,000 1.5 24.2122 199.33
2全体+

6X10,000
0.9663 10,000 95 115.202 1050.8
どこで

要求タイプは次のいずれかです



NPoints-クエリで見つかった平均ポイント数

Nreq-クエリシリーズサイズ

時間(ミリ秒) -平均クエリ実行時間

読み取り -要求ごとの読み取りの平均数

共有ヒット -バッファキャッシュ内のヒット数



結論



予想どおり、要求の境界の領域は、要求のコストに重要な役割を果たします。 実際、境界線が大きいほど、横断するページ数が大きくなる可能性があり、読む必要があるほど、キャッシュ効率が低下します...



ただし、キュービッククエリの場合、クエリのコストは許容範囲内です。 実際、100,000の辺を持つキューブの場合、平均57ページが出力の74行で読み取られます。 これらの74行を読むには、おそらくさらに74ページを読む必要があります。



さらに、このデータは均一に分散されたデータで取得され、クラスター化されたデータで同じ出力電力を取得するために、要求サイズと読み取りページ数がはるかに小さくなることが予想されます。

面白いですね。



PS:タイトル画像は八角形-8次元の立方体を示しています

PPS: Andrei Borodin(Oktonik、Ekb)に感謝します。トピックのヒントについて



All Articles