私の問題は、1,400 万行のテーブルに対する更新クエリが非常に遅いことです。サーバーを調整するためにさまざまなことを試しましたが、パフォーマンスは向上しましたが、更新クエリにはなりませんでした。
私は2つのテーブルを持っています:
- 4 つの列と 3 つのインデックスを持つ T1 (530 行)
- 15 列と 3 つのインデックスを持つ T2 (1400 万行)
- テキスト フィールド stxt で 2 つのテーブルを結合して、T2 のフィールド vid (整数型) を T1 の vid と同じ値で更新したいと考えています。
ここに私のクエリとその出力があります:
explain analyse
update T2
set vid=T1.vid
from T1
where stxt2 ~ stxt1 and T2.vid = 0;
T2 の更新 (コスト = 0.00..9037530.59 行 = 2814247 幅 = 131) (実際の時間 = 25141785.741..25141785.741 行 = 0 ループ = 1)
-> ネストされたループ (コスト=0.00..9037530.59 行=2814247 幅=131) (実際の時間=32.636..25035782.995 行=679354 ループ=1)
結合フィルター: ((T2.stxt2)::text ~ (T1.stxt1)::text)
-> T2 の Seq スキャン (コスト=0.00..594772.96 行=1061980 幅=121) (実際の時間=0.067..5402.614 行=1037809 ループ=1)
フィルタ: (vid= 1)
-> マテリアライズ (コスト=0.00..17.95 行=530 幅=34) (実際の時間=0.000..0.069 行=530 ループ=1037809)
-> T1 の Seq スキャン (コスト = 0.00..15.30 行 = 530 幅 = 34) (実際の時間 = 0.019..0.397 行 = 530 ループ = 1)
総実行時間: 25141785.904 ミリ秒
ご覧のとおり、クエリには約 25141 秒 (~ 7 時間) かかりました。fよくわかりました、プランナーは実行時間を 9037 秒 (~ 2.5 時間) と見積もっています。ここで何か不足していますか?
私のサーバー構成に関する情報は次のとおりです。
- CentOS 5.8、20 GB の RAM
- 共有バッファ = 12GB
- work_mem = 64MB
- Maintenance_work_mem = 64MB
- bgwriter_lru_maxpages = 500
- チェックポイント_セグメント = 64
- チェックポイント完了ターゲット = 0.9
- effective_cache_size = 10GB
テーブル T2 で完全にバキュームを実行して数回分析しましたが、それでも状況はあまり改善されません。
PS: full_page_writes を off に設定すると、更新クエリが大幅に改善されますが、データ損失の危険は冒したくありません。何かお勧めはありますか?