EDIT: Dựa trên một số lần gỡ lỗi và ghi nhật ký của tôi, tôi nghĩ câu hỏi sẽ giảm xuống tại sao là DELETE FROM table WHERE id = x
nhanh hơn nhiều so với DELETE FROM table WHERE id IN (x)
trong đó x
chỉ là một ID duy nhất.Xóa hàng loạt Hibernate và xóa một lần
Gần đây tôi đã thử nghiệm xóa hàng loạt so với xóa từng hàng một và nhận thấy rằng xóa hàng loạt chậm hơn nhiều. Bảng đã kích hoạt để xóa, cập nhật và chèn nhưng tôi đã thử nghiệm có và không có trình kích hoạt và mỗi lần xóa hàng loạt chậm hơn. Bất cứ ai có thể làm sáng tỏ lý do tại sao đây là trường hợp hoặc chia sẻ các mẹo về cách tôi có thể gỡ lỗi này? Từ những gì tôi hiểu, tôi thực sự không thể giảm số lần kích hoạt kích hoạt nhưng ban đầu tôi đã tìm ra rằng việc giảm số lượng truy vấn "xóa" sẽ giúp ích cho hiệu suất.
Tôi đã bao gồm một số thông tin bên dưới, vui lòng cho tôi biết nếu tôi đã loại bỏ bất kỳ điều gì có liên quan.
xóa được thực hiện theo lô 10.000 và mã nhìn cái gì đó như:
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();
}
Mã xóa chỉ một hàng duy nhất về cơ bản là:
SessionFactory.getCurrentSession().delete(obj);
Bảng này có hai chỉ số đó là không được sử dụng trong bất kỳ việc xóa nào. Sẽ không có hoạt động xếp tầng nào xảy ra.
Dưới đây là một mẫu của các GIẢI THÍCH PHÂN TÍCH của DELETE FROM table where id IN (1, 2, 3);
:
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
Tôi đã hút bụi và lập chỉ mục mỗi khi tôi tải lại dữ liệu của tôi để thử nghiệm và kiểm tra dữ liệu của tôi chứa 386.660 hàng.
Thử nghiệm là xóa tất cả các hàng và tôi không sử dụng TRUNCATE
vì thường có tiêu chí lựa chọn nhưng cho mục đích thử nghiệm, tôi đã thực hiện tiêu chí bao gồm tất cả các hàng. Với kích hoạt được kích hoạt, xóa từng hàng một từng mất 193.616ms trong khi hàng loạt-xóa mất 285.558ms. Sau đó, tôi vô hiệu hóa trình kích hoạt và nhận 93.793ms cho các lần xóa hàng đơn và 181.537ms cho xóa hàng loạt. Kích hoạt đi và tổng kết các giá trị và cập nhật một bảng khác - về cơ bản là sổ sách kế toán.
Tôi đã chơi xung quanh với kích thước lô thấp hơn (100 và 1) và tất cả dường như có hiệu suất kém hơn.
EDIT: bật Hibernate khai thác gỗ và hàng duy nhất bởi hàng delete, nó về cơ bản thực hiện: delete from table where id=?
và GIẢI THÍCH PHÂN TÍCH:
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: Đã tò mò nếu danh sách thực sự chứa 10.000 ID, nếu Postgres sẽ làm điều gì đó khác: không.
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
CHỈNH SỬA: Dựa trên GIẢI THÍCH GIẢI THÍCH ở trên, tôi đã lấy một số lần ghi lại từ các thao tác xóa thực tế. Dưới đây là ghi nhật ký hai biến thể của hàng đơn bằng xóa hàng.
Dưới đây là một số xóa duy nhất:
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=?
Đây là biến thể khác của xóa đơn (danh sách chỉ là 1 item)
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 (?)
Cả hai đều là ID mà tồn tại trong bảng và nên được tuần tự.
GIẢI THÍCH PHÂN TÍCH của 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
giải thích PHÂN TÍCH của 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 vs 0,452 khác biệt đáng kể coi?
EDIT:
Set hàng loạt kích thước đến 50.000 và Hibernate không thích ý tưởng:
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)
....
Dường như khi bạn xóa một hàng, nó sẽ sử dụng chỉ mục khác. Bạn có thể kiểm tra nó? – ntalbs
Tôi đã thêm thông tin về hàng đơn theo xóa hàng. MAX (id) của bảng là 3774904, vì vậy tôi chỉ chọn một số lớn hơn. Tôi đã thử cùng với một ID dưới 3774904 nhưng không có trong bảng và có kết quả tương tự (kết quả tương tự cho một ID trong bảng). – nevets1219
có, 0,162 so với 0,452 * là * có ý nghĩa vì 0,452 dài hơn 3 lần so với 0,152. Điều đặc biệt thú vị là giải thích cho thấy rằng họ cũng đang làm điều tương tự. Tôi sẽ nâng cao điều này với nhóm postgresql. [Pgsql-general] (http://www.postgresql.org/community/lists/) có lẽ là một nơi tốt –