16

VerticaDBとして使用するWeb分析ツールを適応させています。私は本当の問題を抱えていoptimizing joinsます。いくつかのクエリに対して結合前のプロジェクションを作成してみました。これにより、クエリは非常に高速になりましたが、ファクト テーブルへのデータの読み込みが遅くなり、クロールされました。

ステージング テーブルからファクト テーブルにデータをロードするために使用する簡単なINSERT INTO ... SELECT * FROM方法では、5 秒から 20 分以上かかります。

このため、結合前のプロジェクションをすべて削除し、データベース デザイナーを使用してクエリ固有のプロジェクションを設計しようとしましたが、十分ではありません。これらのプロジェクションを使用しても、単純な結合には約 14 秒かかりますが、結合前のプロジェクションでは約 1 秒かかります。

私の質問は次のとおりです。結合前のプロジェクションがデータ挿入をこれほど遅くするのは正常ですか?そうでない場合、何が原因である可能性がありますか? これが正常な場合、それは私たちにとってショーストッパーです。結合を高速化するために使用できる他の手法はありますか?

Vertica を 5 ノード クラスタで実行しており、各ノードには 2 つのクアッド コア CPU と 32 GB のメモリがあります。この例のクエリのテーブルには、それぞれ 188,843,085 行と 25,712,878 行があります。

EXPLAIN の出力は次のようになります。

EXPLAIN SELECT referer_via_.url as referralPageUrl, COUNT(DISTINCT sessio
n.id) as visits FROM owa_session as session JOIN owa_referer AS referer_vi
a_ ON session.referer_id = referer_via_.id WHERE session.yyyymmdd BETWEEN 
'20121123' AND '20121123' AND session.site_id = '49' GROUP BY referer_via_
.url  ORDER BY visits DESC LIMIT 250;

Access Path:
+-SELECT  LIMIT 250 [Cost: 1M, Rows: 250 (STALE STATISTICS)] (PATH ID: 0)
|  Output Only: 250 tuples
|  Execute on: Query Initiator
| +---> SORT [Cost: 1M, Rows: 1 (STALE STATISTICS)] (PATH ID: 1)
| |      Order: count(DISTINCT "session".id) DESC
| |      Output Only: 250 tuples
| |      Execute on: All Nodes
| | +---> GROUPBY PIPELINED (RESEGMENT GROUPS) [Cost: 1M, Rows: 1 (STALE 
STATISTICS)] (PATH ID: 2)
| | |      Aggregates: count(DISTINCT "session".id)
| | |      Group By: referer_via_.url
| | |      Execute on: All Nodes
| | | +---> GROUPBY HASH (SORT OUTPUT) (RESEGMENT GROUPS) [Cost: 1M, Rows
: 1 (STALE STATISTICS)] (PATH ID: 3)
| | | |      Group By: referer_via_.url, "session".id
| | | |      Execute on: All Nodes
| | | | +---> JOIN HASH [Cost: 1M, Rows: 1 (STALE STATISTICS)] (PATH ID: 
4) Outer (RESEGMENT)
| | | | |      Join Cond: ("session".referer_id = referer_via_.id)
| | | | |      Execute on: All Nodes
| | | | | +-- Outer -> STORAGE ACCESS for session [Cost: 463, Rows: 1 (ST
ALE STATISTICS)] (PUSHED GROUPING) (PATH ID: 5)
| | | | | |      Projection: public.owa_session_projection
| | | | | |      Materialize: "session".id, "session".referer_id
| | | | | |      Filter: ("session".site_id = '49')
| | | | | |      Filter: (("session".yyyymmdd >= 20121123) AND ("session"
.yyyymmdd <= 20121123))
| | | | | |      Execute on: All Nodes
| | | | | +-- Inner -> STORAGE ACCESS for referer_via_ [Cost: 293K, Rows:
26M] (PATH ID: 6)
| | | | | |      Projection: public.owa_referer_DBD_1_seg_Potency_2012112
2_Potency_20121122
| | | | | |      Materialize: referer_via_.id, referer_via_.url
| | | | | |      Execute on: All Nodes
4

5 に答える 5

2

参加をスピードアップするには:

  • 列 "yyyymmdd" で分割されるようにセッション テーブルを設計します。これにより、パーティションプルーニングが有効になります

  • 可能であれば、列「yyyymmdd」の条件を _referer_via_ に追加し、その上でパーティション化します (ほとんどの場合不可能です)。

  • セッションの使用された(スーパー)プロジェクションでリストによる順序の先頭にできるだけ近い列site_idを持っています

    • referer_id と id に対応してセグメント化された両方のテーブルがあります。

また、クラスター内のノードを増やすと役立ちます。

于 2014-12-26T21:38:59.057 に答える
0

私の質問は次のとおりです。結合前のプロジェクションがデータ挿入をこれほど遅くするのは正常ですか?そうでない場合、何が原因である可能性がありますか? これが正常な場合、それは私たちにとってショー ストッパーです。結合を高速化するために使用できる他の手法はありますか?

影響を受ける量は、使用しているデータセットと構造によって異なると思います。しかし、これはあなたが変更した変数であるため、結合前のプロジェクションが速度低下の原因であると言っても過言ではありません。挿入時間を犠牲にしてクエリ時間を増やしています。

次のいずれかが間違っている場合は、誰かが私を修正してください。私は記憶と、他の人との会話で得た情報を頼りにしています。

いくつかの方法で、事前結合プロジェクションなしで結合を高速化できます。この場合、リファラー ID。結合述語を使用して両方のテーブルの予測をセグメント化すると、役立つと思います。データをフィルタリングするためにできること。

説明計画を見ると、マージ結合ではなくハッシュ結合を行っているため、おそらく見たいと思うでしょう。

最後に、クエリが実際にデータベース デザイナーが推奨するプロジェクションを使用しているかどうかを説明プランまたはシステム テーブルから知りたいと思います。そうでない場合は、クエリで明示的に指定して、それが役立つかどうかを確認してください。

于 2012-11-26T16:54:18.007 に答える
0

これは、Vertica (データベース システムの最近の博士号取得者) を含むカラム データベースを扱う学歴から得た私の見解です。

Blockquote 私の質問は次のとおりです。結合前のプロジェクションがデータ挿入をこれほど遅くするのは正常ですか?そうでない場合、何が原因でしょうか? これが正常な場合、それは私たちにとってショー ストッパーです。結合を高速化するために使用できる他の手法はありますか? 引用符

はい、予測の更新は非常に遅く、理想的には、更新コストを償却するために大きなバッチでのみ行う必要があります。基本的な理由は、各プロジェクションが (プロジェクションの一部である各テーブル列の) データの別のコピーを表していることです。

単一行の挿入では、プロジェクションの各列に 1 つの値 (1 つの属性) を追加する必要があります。たとえば、20 個の属性を持つテーブルに 1 行を挿入するには、少なくとも 20 回の列の更新が必要です。さらに悪いことに、各列はソートおよび圧縮されます。これは、列に新しい値を挿入するには、データの大きなチャンクに対して複数の操作が必要であることを意味します: データの読み取り/圧縮解除/更新/並べ替え/データの圧縮/データの書き戻し。Vertica には更新の最適化がいくつかありますが、コストを完全に隠すことはできません。

プロジェクションは、従来の行ストア (MySQL、PostgreSQL、Oracle など) の複数列インデックスに相当すると考えることができます。プロジェクションと従来の B ツリー インデックスの利点は、従来のインデックスを使用するよりも、それらを読み取る (それらを使用してクエリに応答する) 方がはるかに高速であることです。理由は複数あります。非クラスター化インデックスのようにヘッド データにアクセスする必要がないこと、圧縮によりサイズが小さいことなどです。裏を返せば、更新がはるかに難しいことです。トレードオフ...

于 2014-10-01T16:34:26.827 に答える
0

STALE STATISTICS がたくさんあるようです。 STALE 統計への対応は重要です。それがクエリが遅い理由です。基盤となるデータに関する統計がなければ、Vertica のクエリ オプティマイザーは最適な実行プランを選択できません。また、STALE 統計に対応しても、SELECT のパフォーマンスが向上するだけで、更新のパフォーマンスは向上しません。

テーブルを定期的に更新する場合は、VERTICA で考慮しなければならない追加事項があることを覚えておいてください。この質問に投稿した回答を確認してください。更新速度の向上に役立つことを願っています。

その回答で説明されているように、AHM 設定を調べます。テーブルで削除された行を後で選択できるようにする必要がない場合は、多くの場合、行を保持しない方がよいでしょう。最新のエポック バージョンのデータのみを保持する方法があります。または、削除されたデータを手動でパージします。それがどうなるか教えてください。

于 2013-06-20T22:06:55.583 に答える
0

あなたのクエリは、もう少し明示的であることを使用できると思います。また、その悪魔を使用しないでください BETWEENこれを試してください:

EXPLAIN SELECT 
    referer_via_.url as referralPageUrl, 
    COUNT(DISTINCT session.id) as visits 
FROM owa_session as session 
JOIN owa_referer AS referer_via_ 
    ON session.referer_id = referer_via_.id
WHERE session.yyyymmdd <= '20121123' 
AND session.yyyymmdd > '20121123' 
AND session.site_id = '49' 
GROUP BY referer_via_.url
-- this `visits` column needs a table name
ORDER BY visits DESC LIMIT 250;

DATEなぜ同じものを使用するのかについて、私は本当に困惑していると言えますBETWEEN

于 2014-06-28T06:57:33.963 に答える