
この記事では、例として恒星天体2MASSのアトラスを使用した低レベルコンピューティングの利点について説明します。
2MASSは、座標が提供される約4億7,100万個のオブジェクトと、関連情報(合計60個の属性)です。
物理的には、これは50GBのソースgzip圧縮されたテキストファイルです。
「重砲」に頼らずにそのような基地で作業することは可能ですか?
やってみましょう。
前戯
この作業は2009年に実施され、独自のGeo-DBMSを作成するDataEastの取り組みの一部でした。
目標は、ベンチマーククエリプロセッサをデバッグ、プロファイリング、および作成することでした。
クエリ言語として、 Turorial D方言が選択されました。むしろ、代数に関連する部分が選択されました。 方言は実生活の要件に適合しました。特に、カーソルを操作する機能が追加されました。
ただし、これは単なるコンテキストであり、この投稿の目的は、「雨の涙のように溶けた」過去の勝利についての物語ではなく、DBMSカーソルに直接計算を最大限に転送する手法のデモです。
もちろん、ストアドプロシージャや集計を使用して、PL / SQLツールでこの手法を適用できます。
はじめに
データ準備プロセスについて詳しく説明する意味はありません。データの入力に8時間26分、空間インデックスの作成に1時間17分かかったとしましょう。
検証要求はソースデータに含まれています。
select count(*) as rows, sum(pts_key::bigint) as sum_pts_key, sum(pxcntr::bigint) as sum_pxcntr, sum(scan_key::bigint) as sum_scan_key, sum(scan::bigint) as sum_scan, sum(ext_key::bigint) as sum_ext_key, sum(coadd_key::bigint) as sum_coadd_key, sum(coadd::bigint) as sum_coadd, sum(mp_flg) as sum_mp_flg, sum(gal_contam) as sum_gal_contam, sum(use_src) as sum_use_src, sum(dup_src) as sum_dup_src, sum(nopt_mchs) as sum_nopt_mchs, sum(phi_opt::bigint) as sum_phi_opt, sum(dist_edge_ew::bigint) as sum_dist_edge_ew, sum(dist_edge_ns::bigint) as sum_dist_edge_ns, sum(err_ang::bigint) as sum_err_ang FROM twomass_psc;
この場合、このクエリは次のようになります select "PSC" chew { "rows" INTEGER, "sum_pts_key" INTEGER, "sum_pxcntr" INTEGER, "sum_scan_key" INTEGER, "sum_scan" INTEGER, "sum_ext_key" INTEGER, "sum_coadd_key" INTEGER, "sum_coadd" INTEGER, "sum_mp_flg" INTEGER, "sum_gal_contam" INTEGER, "sum_use_src" INTEGER, "sum_dup_src "INTEGER, "sum_nopt_mchs" INTEGER, "sum_phi_opt" INTEGER, "sum_dist_edge_ew" INTEGER, "sum_dist_edge_ns" INTEGER, "sum_err_ang" INTEGER } hook "init" { "rows" := 0; "sum_pts_key" := 0; ... "sum_err_ang" := 0; } hook "row" { "rows" := "rows" + 1; if (not isnull("pts_key/cntr")) then "sum_pts_key" := "sum_pts_key" + "pts_key/cntr"; end if; ... if (not isnull("err_ang")) then "sum_err_ang" := "sum_err_ang" + "err_ang"; end if; } hook "finit" { call __interrupt (); };
実行の結果は次のとおりです。 ここでは、 chew演算子を使用して、元のデータストリーム(テーブル全体)を合成に変換し、特定のフィールドをローカル変数にします。 フック演算子を使用して(SQL集計と同様に)イベントをサブスクライブします-ストリームを開始/停止し、文字列を受け取ります。 __interruptが呼び出されると、ローカル変数の現在の値は結果セットに分類されます。INFO: start [04/Jun/2009:09:37:45:822] ----------------------------------------------------------------- rows sum_pts_key sum_pxcntr sum_scan_key sum_scan sum_ext_key sum_coadd_key sum_coadd sum_mp_flg sum_gal_contam sum_use_src sum_dup_src sum_nopt_mchs sum_phi_opt sum_dist_edge_ew sum_dist_edge_ns sum_err_ang ----------------------------------------------------------------- 470992970 306810325437475788 306815556538478936 16902776758555 32666066948 2048692118201 388758631396659 64617139213 16048 729878 464456155 79798372 369187043 64916239773 69388217174 2670725813652 29279563815 ----------------------------------------------------------------- INFO: stop [04/Jun/2009:12:35:59:571]
結果は検証結果と一致します。つまり、データの準備ができています。
動作時間-3時間、連続表示中の列あたり約10分。 この速度(Intel Core2 P4-2.4 GHz、2Gb、ディスクST3400620ASの場合)は、以降のすべてのリクエストで一般的です。 一方、ソーステキストファイルをアンパックしてGAWKで処理した場合、たとえば、データを読み取るのに50 mb / s = 1000秒で50 GB、アンパックするのに同じ量、ストリームを整理するだけで35分かかります。 wcを使用してすべてのデータを解凍して実行するには、1時間半かかりました。
自分の目ですべてを見たい人のために、プレートの欠陥がある空の部分があります:

一部の人々は彼を帝国艦隊の戦線と間違えています。
データマイニング
簡単な統計。 Max、Min、Avg-「jm」列(デフォルトのJバンドの大きさ)を試してみましょう。
select "PSC" chew { "nrows" INTEGER, "nulls_j_m" INTEGER, "num_j_m" INTEGER, "sum_j_m" RATIONAL, "avg_j_m" RATIONAL, "max_j_m" RATIONAL, "min_j_m" RATIONAL } hook "init" { "nrows" := 0; "nulls_j_m" := 0; "num_j_m" := 0; "sum_j_m" := 0; "avg_j_m" := 0; "max_j_m" := -1e66; "min_j_m" := 1e66; } hook "row" { nrows := nrows + 1; if (isnull("j_m")) then "nulls_j_m" := "nulls_j_m" + 1; else "num_j_m" := "num_j_m" + 1; "sum_j_m" := "sum_j_m" + "j_m"; if ("max_j_m"<"j_m") then "max_j_m" := "j_m"; end if; if ("min_j_m">"j_m") then "min_j_m" := "j_m"; end if; end if; } hook "finit" { "avg_j_m" := "sum_j_m" / "num_j_m"; call __interrupt (); };
結果:
INFO: start [04/Jun/2009:15:00:54:821] -------------------------------------------------------------------- nrows nulls_j_m num_j_m sum_j_m avg_j_m max_j_m min_j_m -------------------------------------------------------------------- 470992970 19 470992951 7.15875e+009 15.1993 25.86 -2.989 -------------------------------------------------------------------- INFO: stop [04/Jun/2009:15:18:47:743]
分散:
select "PSC" chew { "nrows" INTEGER, "nulls_j_m" INTEGER, "num_j_m" INTEGER, "disp_j_m" RATIONAL } hook "init" { "nrows" := 0; "nulls_j_m" := 0; "num_j_m" := 0; "disp_j_m" := 0; var tmp rational; var tavg rational; tavg := 15.1993; -- previously calculated } hook "row" { nrows := nrows + 1; if (isnull("j_m")) then "nulls_j_m" := "nulls_j_m" + 1; else "num_j_m" := "num_j_m" + 1; tmp := "j_m" - tavg; tmp := tmp * tmp; "disp_j_m" := "disp_j_m" + tmp; end if; } hook "finit" { "disp_j_m" := "disp_j_m" / "num_j_m"; call __interrupt (); };
結果 :
INFO: start [04/Jun/2009:15:48:27:274] -------------------------------------------------------------------- nrows nulls_j_m num_j_m disp_j_m -------------------------------------------------------------------- 470992970 19 470992951 1.98223 -------------------------------------------------------------------- INFO: stop [04/Jun/2009:16:05:01:946
ヒストグラム:
select "PSC" chew { "j_m_cell" rational, "num" INTEGER } hook "init" { var tmp integer; var tmp2 integer; var tmax rational; tmax := 26.; -- previously calculated var tmin rational; tmin := -5.; -- previously calculated var ncells integer; ncells := 500; var tcell rational; tcell := (tmax - tmin)/ncells; var htptr integer; htptr := hti_alloc (0); call hti_set (htptr, 0, 0); } hook "row" { if (not isnull("j_m")) then tmp := ("j_m" - tmin)/tcell; tmp2 := hti_get (htptr, tmp); tmp2 := tmp2 + 1; call hti_set (htptr, tmp, tmp2); end if; } hook "finit" { tmp := 0; while tmp < ncells; begin; "j_m_cell" := tmin + tcell * tmp + tcell * 0.5; "num" := hti_get (htptr, tmp); tmp := tmp + 1; call __interrupt (); end; end while; call hti_free (htptr); };
ヒストグラムセルの蓄積は、言語に配列がないため、ハッシュテーブルを使用して発生します。 この場合、結果はヒストグラムセルの印刷になります。これはgnuplotで表示するのに便利です。次の図では、列「km」(デフォルトのKs帯域の大きさ)および「hm」(デフォルトのH帯域の大きさ)の印刷も追加されています。

3D
さて、ヒストグラムの「km」と「hm」は非常に似ていますが、共有分布はどうですか?
select "PSC" chew { "cell" rational, "num" INTEGER } hook "init" { var tmp integer; var tmp2 integer; var tmp4 integer; var tmax rational; tmax := 25; var tmin rational; tmin := -5.; var ncells integer; ncells := 512; var tcell rational; tcell := (tmax - tmin)/ncells; var "hnd" integer; hnd:= img_create ( ncells, ncells, tmin, tmin, tmax, tmax, 1); var cl integer; cl := img_alloc_color (hnd, 255,0,0); } hook "row" { if ((not isnull("h_m")) and (not isnull("k_m"))) then tmp := img_get_point (hnd, "h_m", "k_m"); tmp := tmp + 1; call img_draw_point (hnd, "h_m", "k_m", tmp); end if; } hook "finit" { tmp := 0; while tmp < ncells; begin; tmp2 := 0; while tmp2 < ncells; begin; tmp4 := img_get_point (hnd, tmin + tcell * tmp, tmin + tcell * tmp2); call print ((tmin + tmp * tcell)+' '+ (tmin + tmp2* tcell)+' '+tmp4+'\n'); if tmp4 > 0 then tmp4 := cl; else tmp4 := 0; end if; call img_draw_point (hnd, tmin + tcell * tmp, tmin + tcell * tmp2, cl); tmp2 := tmp2 + 1; end; end while; tmp := tmp + 1; end; end while; call img_saveas (hnd, 'stat4.gif'); call img_destroy (hnd); };
この例では、2次元ヒストグラムを保存するために、 GDプラグインを使用して取得した画像イメージを使用し、 pm3dモードでgnuplotツールを使用してセルに再び入る対数を表示しました。

「j_m」-「k_m」対「h_m」-「k_m」の分布の同様の図:

これらのヒストグラムの作成には、列ごとに約35分から12分かかります。
しかし、特定の空間領域にこのような分布を構築する必要がある場合はどうでしょうか? 数秒でできますか? もちろん:
空間制限のあるサンプル 。
select "PSC" where sp_overlap ("Point", [rational:xmin], [rational:ymin], [rational:xmax], [rational:ymax]) chew { "m_cell" rational, "num" INTEGER } … -- below is the same text
sp_overlapを追加すると、元の識別子ストリームがテーブルから空間インデックスに変更されました。

サンプルの範囲は、セルの左下隅に示されています。
限定的な制限はどうですか?
スペースを制限するのと同じくらい簡単です。
select "PSC" where “j_snr” < 10. -- or you may combine your restrictions adding -- and sp_overlap ("Point", … ) chew { "m_cell" rational, "num" INTEGER } … -- below is the same text
そして、これが結果です。

合計
計算をカーソルに転送するものは何ですか?
- 読み取りデータを所定の場所で処理し、シリアル化、ネットワーク経由での送信、受信、非シリアル化から解放されます...
- ネットワーク経由で送信される5億行などの保存されたリソースは、長期間にわたって帯域幅のかなりの部分を占有します。
そして、このテクニックは私たちに何を脅かしていますか?
- 私たちはすべて自分でやらなければなりません。これは潜在的なエラーの原因です。
- 本当に多くの計算が共有サーバーで実行するのにあまり便利ではないアルゴリズム。
- すべての計算がストリームで実行できるわけではありません。
これはすべて真実ですが、著者はこれが常に行われるべきであると主張していません。これは、特に仮説の迅速なチェックと修正が必要な場合など、特に研究の研究部分にとっては便利ですが、データを操作するための多くのツールの1つにすぎません。