編集:私のデバッグとロギングのいくつかに基づいて、DELETE FROM table WHERE id = x
はなぜよりもはるかに高速であるのかという質問があると思います。x
は単なるIDです。Hibernateのバッチ削除と単一の削除
私は最近、バッチ削除と各行の削除を1つずつテストし、バッチ削除がはるかに遅いことに気付きました。テーブルには削除、更新、挿入のトリガがありましたが、トリガの有無にかかわらずテストしました。毎回バッチ削除が遅くなりました。 これはなぜ、私はこれをデバッグすることができますか?私が理解しているように、私は実際にトリガーが起動する回数を減らすことはできませんが、私はもともと「削除」クエリの数を減らすことがパフォーマンスに役立つと考えていました。
私は以下の情報をいくつか掲載しました。関連するものは除外していますか?
削除は万のバッチなどのコードを見て何かに行われています。
private void batchDeletion(Collection<Long> ids) {
StringBuilder sb = new StringBuilder();
sb.append("DELETE FROM ObjImpl WHERE id IN (:ids)");
Query sql = getSession().createQuery(sb.toString());
sql.setParameterList("ids", ids);
sql.executeUpdate();
}
1つだけの行を削除するためのコードは、基本的に次のとおりです。
SessionFactory.getCurrentSession().delete(obj);
の表は、2つのインデックスを持っています削除のいずれにも使用されません。カスケード操作は行われません。
Delete on table (cost=12.82..24.68 rows=3 width=6) (actual time=0.143..0.143 rows=0 loops=1)
-> Bitmap Heap Scan on table (cost=12.82..24.68 rows=3 width=6) (actual time=0.138..0.138 rows=0 loops=1)
Recheck Cond: (id = ANY ('{1,2,3}'::bigint[]))
-> Bitmap Index Scan on pk_table (cost=0.00..12.82 rows=3 width=0) (actual time=0.114..0.114 rows=0 loops=1)
Index Cond: (id = ANY ('{1,2,3}'::bigint[]))
Total runtime: 3.926 ms
私は真空にし、私はテストのために自分のデータをリロードし、私のテストデータは386660行が含まれているたびに、インデックスを再作成しました:ここ
はDELETE FROM table where id IN (1, 2, 3);
のANALYZE EXPLAINのサンプルです。
テストではすべての行が削除され、通常は選択基準があるのでTRUNCATE
を使用していませんが、テスト目的ですべての行が含まれています。トリガを有効にすると、各行を1つずつ削除すると193,616ミリ秒かかりましたが、バッチ削除は285,558ミリ秒かかりました。その後、トリガーを無効にして、単列の削除で93,793ms、バッチ削除で181,537msを得ました。トリガーは値を合計して別のテーブルを更新します。基本的には簿記です。
低バッチサイズ(100と1)で遊んだことがありますが、それらはすべてパフォーマンスが悪いようです。
EDIT:ANALYZE delete from table where id=?
とEXPLAIN:
Delete on table (cost=0.00..8.31 rows=1 width=6) (actual time=0.042..0.042 rows=0 loops=1)
-> Index Scan using pk_table on table (cost=0.00..8.31 rows=1 width=6) (actual time=0.037..0.037 rows=0 loops=1)
Index Cond: (id = 3874904)
Total runtime: 0.130 ms
EDIT:Hibernateのログを、行によって、単一の行のために回したが、それは基本的にやって削除リストが実際万IDが含まれている場合、Postgresが希望の場合、興味がありました違うことをする:いいえ。
Delete on table (cost=6842.01..138509.15 rows=9872 width=6) (actual time=17.170..17.170 rows=0 loops=1)
-> Bitmap Heap Scan on table (cost=6842.01..138509.15 rows=9872 width=6) (actual time=17.160..17.160 rows=0 loops=1)
Recheck Cond: (id = ANY ('{NUMBERS 1 THROUGH 10,000}'::bigint[]))
-> Bitmap Index Scan on pk_table (cost=0.00..6839.54 rows=9872 width=0) (actual time=17.139..17.139 rows=0 loops=1)
Index Cond: (id = ANY ('{NUMBERS 1 THROUGH 10,000}'::bigint[]))
Total runtime: 17.391 ms
EDIT:上記の、EXPLAIN ANALYZEをもとに、私は実際の削除操作から、いくつかのログを取得しました。以下は、1行1行削除の2つのバリエーションのロギングです。ここ
は、いくつかの単一の削除である:ここ
2013-03-14 13:09:25,424:delete from table where id=?
2013-03-14 13:09:25,424:delete from table where id=?
2013-03-14 13:09:25,424:delete from table where id=?
2013-03-14 13:09:25,424:delete from table where id=?
2013-03-14 13:09:25,424:delete from table where id=?
2013-03-14 13:09:25,424:delete from table where id=?
2013-03-14 13:09:25,424:delete from table where id=?
2013-03-14 13:09:25,424:delete from table where id=?
2013-03-14 13:09:25,424:delete from table where id=?
2013-03-14 13:09:25,424:delete from table where id=?
は、単一の削除の他の変形例である(リストは単に1つのアイテムである)
2013-03-14 13:49:59,858:delete from table where id in (?)
2013-03-14 13:50:01,460:delete from table where id in (?)
2013-03-14 13:50:03,040:delete from table where id in (?)
2013-03-14 13:50:04,544:delete from table where id in (?)
2013-03-14 13:50:06,125:delete from table where id in (?)
2013-03-14 13:50:07,707:delete from table where id in (?)
2013-03-14 13:50:09,275:delete from table where id in (?)
2013-03-14 13:50:10,833:delete from table where id in (?)
2013-03-14 13:50:12,369:delete from table where id in (?)
2013-03-14 13:50:13,873:delete from table where id in (?)
は、両方のテーブルに存在するIDとすべきです逐次的である。
DELETE FROM table WHERE id = 3774887;
Delete on table (cost=0.00..8.31 rows=1 width=6) (actual time=0.097..0.097 rows=0 loops=1)
-> Index Scan using pk_table on table (cost=0.00..8.31 rows=1 width=6) (actual time=0.055..0.058 rows=1 loops=1)
Index Cond: (id = 3774887)
Total runtime: 0.162 ms
のEXPLAIN ANALYZEでは有意差が考慮さ0.452対DELETE FROM table WHERE id IN (3774887);
Delete on table (cost=0.00..8.31 rows=1 width=6) (actual time=0.279..0.279 rows=0 loops=1)
-> Index Scan using pk_table on table (cost=0.00..8.31 rows=1 width=6) (actual time=0.210..0.213 rows=1 loops=1)
Index Cond: (id = 3774887)
Total runtime: 0.452 ms
0.162のANALYZE EXPLAIN?
EDIT:50,000および休止状態へ
セットバッチサイズは、そのアイデアのようにしませんでした:
java.lang.StackOverflowError
at org.hibernate.hql.ast.util.NodeTraverser.visitDepthFirst(NodeTraverser.java:40)
at org.hibernate.hql.ast.util.NodeTraverser.visitDepthFirst(NodeTraverser.java:41)
at org.hibernate.hql.ast.util.NodeTraverser.visitDepthFirst(NodeTraverser.java:42)
....
単一行を削除すると、他のインデックスが使用されているようです。それを確認できますか? – ntalbs
1行ずつ削除に関する情報を追加しました。テーブルのMAX(id)は3774904なので、私はちょうどより大きな数字を選んだだけです。私は3774904以下のIDで同じことを試みましたが、テーブルにはなかったし、同様の結果が得られました(テーブルのIDと同様の結果)。 – nevets1219
はい、0.162対0.452 *は0.452が0.162よりほぼ3倍長いため重要です。説明は、彼らが同じことをうまくやっていることを示唆していることは特に興味深い。私はpostgresqlチームでこれを上げます。 [pgsql-general](http://www.postgresql.org/community/lists/)はおそらく良い場所です –