2017-02-21 14 views
0

大きなテーブル(600m行)で約300行を更新する必要があります。Redshift UPDATEはSeq Scanを非常に遅く使用します

私が使用しているクエリは少しトリッキーです:

UPDATE my_table 
SET name = CASE WHEN (event_name in ('event_1', 'event_2', 'event_3')) 
THEN 'deleted' ELSE name END 
WHERE uid IN ('id_1', 'id_2') 

私はこのクエリにEXPLAINを使用しようと私が手:

XN Seq Scan on my_table (cost=0.00..103935.76 rows=4326 width=9838) 
    Filter: (((uid)::text = 'id_1'::text) OR ((uid)::text = 'id_2'::text)) 

私は、インターリーブソートキーを持っているし、uidが1でありますこのソートキーに含まれる列の クエリがこのようになっている理由は、実際のコンテキストでは、SETのカラム数(名前とともに)は異なる可能性がありますが、おそらく10を超えないことになります。 基本的な考えは、クロス・ジョインが必要です(更新ルールはカラムに固有ですので、それらを混在させたくありません)。 は、例えば、将来的にはのようなクエリがあるでしょう:とにかく

UPDATE my_table 
SET name = CASE WHEN (event_name in ("event_1", "event_2", "event_3")) THEN 'deleted' ELSE name END, 
address = CASE WHEN (event_name in ("event_1", "event_4")) THEN 'deleted' ELSE address END 
WHERE uid IN ("id_1", "id_2") 

、戻って最初のクエリに、それは非常に長い時間(約45分)のために実行され、100%のCPUを取ります。

私も単純なクエリをチェックしてみました:

explain UPDATE my_table SET name = 'deleted' WHERE uid IN ('id_1', 'id_2') 
XN Seq Scan on my_table (cost=0.00..103816.80 rows=4326 width=9821) 
    Filter: (((uid)::text = 'id_1'::text) OR ((uid)::text = 'id_2'::text)) 

私はどんなアドバイスを聞いて幸せになる、それがより明確にするために、質問に追加することができる他に何かわかりません。

+0

CASE文のWHEREキーワードがエラーを引き起こすため、実際のクエリはかなり異なっている必要があります。そこにサブセレクトはありますか?また、テーブル上のdistkeyは何ですか? – systemjack

+0

ああ、確かに今修正しました。 –

+0

あなたの質問は私には大丈夫です。私はインタリーブされたソートキーで大したことはなかった。ソートキーの一部ではない列でのフィルタリングは、複合ソートキーとインターリーブされたものを使って、まだ10倍程度向上しています。ソートキー列でのフィルタリングは、さらに優れているはずです。 Redshiftで並べ替えるまで、インターリーブされたキーを使用して諦めました。 – systemjack

答えて

1

インターリーブされたソートキーを削除し、それをuidのシンプルソートキーまたは最初の列としてuidの複合ソートキーに置き換えてみましたか?

また、uidという名前は、値としてGUID/UUIDを使用している可能性があります。これは、Redshiftのid値、特にソートキーの場合、これはアンチパターンの値であることをお勧めします。 GUID/UUID id

問題:

    • は、多くの場合、
    • 新しい行は常にソート
  • を混乱させる完全なシーケンシャルスキャンをトリガし、予測可能な順序では発生しません。非常に貧弱に圧縮する
    • を削除してから挿入された赤方偏移で
+0

ええ、uidはMongoId文字列です。ちょうど600キロの行のうちわずか数百万がソートされているので、ソートキーが機能しない可能性が最も高いと認識しました。これはおそらく別の質問を保証するかもしれませんが、多分あなたは何かを示唆することができます:テーブルが非常に大きいので、バキューム処理に時間がかかり、ディープコピーに使用可能なディスク容量より多くのディスクスペースが必要な場合、テーブルを再インデックスする別の方法はありますか? –

+1

テーブルのTBHの大きさによって異なります。本当に巨大なテーブルでは、限定されたデータセット(週や月など)を含む小さなテーブルと元のテーブルを置き換えるためのUNION ALLビューで分割することができます。あなたはあなたの 'DISTSTYLE'について言及しませんでした - 私はタイムスタンプ列のソートキーを使って' uid'を配布キーとして使ってみます。 –

+0

スペースがない場合は、S3への増分UNLOADを実行して、アンロードした範囲を削除してから、S3から新しいテーブルにCOPYすることができます。また、スペースに問題があり、まだ圧縮を有効にしていない場合、これは素晴らしい機会になります:http://docs.aws.amazon.com/redshift/latest/dg/t_Compressing_data_on_disk.html。 – systemjack

0

更新を照会するとき

  • を読み取ることが、より多くのデータを必要なストレージのためのより多くのディスク領域が必要です。 Redshiftは、行を削除済みとしてマークし、それらを物理的に削除しない(ゴースト列)だけです。明示的真空削除のみ<テーブル名>スペースを再利用する必要があります。

    Seq。これらのゴースト行の影響を受けるスキャン。上記のコマンドを実行し、後でクエリのパフォーマンスを確認することを提案します。

  • 関連する問題