7

3 つのインデックスを持つ 2 億 5000 万行を含むテーブルで UPDATE を実行しています。この UPDATE は、3,000 万行を含む別のテーブルを使用します。現在、約 36 時間実行されています。彼らがそれを行うのにどれだけ近いかを知る方法であるかどうか疑問に思っています。それでも、あと 1 日か 2 日しか必要ない場合は、そのまま実行します。コマンドクエリは次のとおりです。

UPDATE pagelinks SET pl_to = page_id
    FROM page
    WHERE 
        (pl_namespace, pl_title) = (page_namespace, page_title)
        AND
        page_is_redirect = 0
;

EXPLAIN はここでは問題ではありません。UPDATE にかかる時間をいくらか正当化するために、大きなテーブルに複数のインデックスがあることについてのみ言及します。しかし、とにかくEXPLAINは次のとおりです。

Merge Join  (cost=127710692.21..135714045.43 rows=452882848 width=57)
  Merge Cond: (("outer".page_namespace = "inner".pl_namespace) AND ("outer"."?column4?" = "inner"."?column5?"))
  ->  Sort  (cost=3193335.39..3219544.38 rows=10483593 width=41)
        Sort Key: page.page_namespace, (page.page_title)::text
        ->  Seq Scan on page  (cost=0.00..439678.01 rows=10483593 width=41)
              Filter: (page_is_redirect = 0::numeric)
  ->  Sort  (cost=124517356.82..125285665.74 rows=307323566 width=46)
        Sort Key: pagelinks.pl_namespace, (pagelinks.pl_title)::text"
        ->  Seq Scan on pagelinks  (cost=0.00..6169460.66 rows=307323566 width=46)

ここで、ページリンクのインデックスの1 つを削除するために、並列クエリ コマンドも送信しました。もちろん、UPDATE が完了するのを待っています (しかし、とにかく試してみたいと思いました!)。したがって、データが破損することを恐れて、ページリンクから何も選択できません( DROP INDEX ポストマスター プロセスを強制終了しても安全だと思わない限りは?)。

だから、デッドタプルの量を追跡するテーブルなのか、それとも何かのテーブルなのか疑問に思っています.UPDATEがタスクを完了するまでの速度や距離を知ることができれば幸いです。

Thx (PostgreSQL は思ったほどインテリジェントではありません。ヒューリスティックが必要です)

4

3 に答える 3

6

表示されている出力を解釈するために、 「 EXPLAINの使用 」に関する PostgreSQL のドキュメントを読みましたか?

私は通常の PostgreSQL ユーザーではありませんが、そのドキュメントを読んで、EXPLAIN表示されている出力と比較しました。あなたのUPDATEクエリはインデックスを使用していないようで、テーブルスキャンを実行して と の両方をソートする必要がpageありますpagelinks。ソートは間違いなく一時ディスクファイルを必要とするのに十分な大きさであり、temp_tablespace.

次に、推定データベース ページの読み取りが表示されます。EXPLAINその出力の最上位には(cost=127710692.21..135714045.43). ここでの単位は、ディスク I/O アクセスです。つまり、これを行うために 1 億 3500 万回以上ディスクにアクセスすることになりますUPDATE

シーク時間が 5 ミリ秒の 10,000rpm ディスクでも、最適な条件下では 1 秒あたり最大 200 の I/O 操作を達成できることに注意してください。これは、UPDATE188 時間 (7.8 日) のディスク I/O がかかることを意味します。たとえ、その期間、飽和状態のディスク I/O を維持できたとしても (つまり、途切れることなく継続的に読み取り/書き込みを行った場合)。これは不可能です。実際のスループットは、少なくとも 1 桁はずれていると予想されます。特に、このサーバーを他のあらゆる種類の作業に使用していることは間違いないためです。だから私はあなたがあなたのUPDATE.

私だったら、初日にこのクエリを終了し、UPDATEインデックスをより有効に活用し、ディスク上の並べ替えを必要としない別の実行方法を見つけたでしょう。おそらく、単一の SQL ステートメントでそれを行うことはできません。

あなたの についてはDROP INDEX、単にブロックしていて、テーブルへの排他的アクセスを待っていると思います。この状態にある間、おそらくそれを殺すことができると思います。

于 2009-01-09T18:55:32.527 に答える
3

これは非常に古いものですが、更新を監視する方法が必要な場合は...

create sequence yourprogress; 

UPDATE pagelinks SET pl_to = page_id
    FROM page
    WHERE 
        (pl_namespace, pl_title) = (page_namespace, page_title)
        AND
        page_is_redirect = 0 AND NEXTVAL('yourprogress')!=0;

次に、別のセッションでこれを実行します (シーケンスはグローバルに影響を受けるため、トランザクションについて心配する必要はありません)。

select last_value from yourprogress;

これにより、影響を受ける回線の数が表示されるため、所要時間を見積もることができます。

最後にシーケンスを再起動して、もう一度試してください。

alter sequence yourprogress restart with 1;

または単にドロップします:

drop sequence yourprogress;
于 2018-09-20T11:09:59.547 に答える
0

インデックスが必要です。または、ビルが指摘したように、すべてのテーブルで順次スキャンを実行する必要があります。

CREATE INDEX page_ns_title_idx on page(page_namespace, page_title);
CREATE INDEX pl_ns_title_idx on pagelink(pl_namespace, pl_title);
CREATE INDEX page_redir_idx on page(page_is_redirect);
于 2009-01-09T19:13:19.900 に答える