PostgreSQL
 sql >> Cơ Sở Dữ Liệu >  >> RDS >> PostgreSQL

Tốc độ cắt bỏ Postgresql

Điều này đã xuất hiện một vài lần gần đây, cả trên SO và trên danh sách gửi thư PostgreSQL.

TL; DR cho hai điểm cuối cùng của bạn:

(a) Bộ đệm chia sẻ lớn hơn có thể là lý do tại sao TRUNCATE chậm hơn trên máy chủ CI. Cấu hình fsync khác nhau hoặc việc sử dụng phương tiện quay thay vì SSD cũng có thể bị lỗi.

(b) TRUNCATE có chi phí cố định, nhưng không nhất thiết phải chậm hơn DELETE , cộng với nó hoạt động nhiều hơn. Xem giải thích chi tiết sau đây.

CẬP NHẬT: Một cuộc thảo luận quan trọng về hiệu suất pgsql đã phát sinh từ bài đăng này. Xem chuỗi này.

CẬP NHẬT 2: Các cải tiến đã được thêm vào 9.2beta3 sẽ giúp thực hiện việc này, hãy xem bài đăng này.

Giải thích chi tiết về TRUNCATE so với DELETE FROM :

Mặc dù không phải là chuyên gia về chủ đề này, nhưng hiểu biết của tôi là TRUNCATE có chi phí gần như cố định cho mỗi bảng, trong khi DELETE là ít nhất O (n) cho n hàng; tệ hơn nếu có bất kỳ khóa ngoại nào tham chiếu đến bảng bị xóa.

Tôi luôn giả định rằng chi phí cố định của một TRUNCATE thấp hơn chi phí của một DELETE trên một chiếc bàn gần như trống rỗng, nhưng điều này hoàn toàn không đúng.

TRUNCATE table; thực hiện nhiều hơn DELETE FROM table;

Trạng thái của cơ sở dữ liệu sau TRUNCATE table cũng giống như nếu thay vào đó bạn chạy:

  • DELETE FROM table;
  • VACCUUM (FULL, ANALYZE) table; (Chỉ 9.0+, xem chú thích)

... tất nhiên là TRUNCATE không thực sự đạt được hiệu quả của nó với DELETE và một VACUUM .

Vấn đề là DELETETRUNCATE làm những việc khác nhau, vì vậy bạn không chỉ so sánh hai lệnh có kết quả giống hệt nhau.

Một bảng DELETE FROM table; cho phép giữ lại các hàng chết và khối phồng, cho phép các chỉ mục mang các mục đã chết, không cập nhật thống kê bảng được sử dụng bởi trình lập kế hoạch truy vấn, v.v.

TRUNCATE cung cấp cho bạn một bảng hoàn toàn mới và các chỉ mục như thể chúng chỉ là CREATE ed. Nó giống như bạn đã xóa tất cả các bản ghi, lập chỉ mục lại bảng và thực hiện VACUUM FULL .

Nếu bạn không quan tâm đến việc có mảnh vụn còn sót lại trong bảng hay không vì bạn chuẩn bị đi và điền lại, bạn có thể tốt hơn nên sử dụng DELETE FROM table; .

Vì bạn không chạy VACUUM bạn sẽ thấy rằng các hàng chết và các mục nhập chỉ mục tích tụ như một khối phồng phải được quét sau đó bỏ qua; điều này làm chậm tất cả các truy vấn của bạn. Nếu các thử nghiệm của bạn không thực sự tạo và xóa tất cả nhiều dữ liệu mà bạn có thể không nhận thấy hoặc không quan tâm và bạn luôn có thể thực hiện VACUUM hoặc hai phần trong quá trình chạy thử nghiệm của bạn nếu bạn làm như vậy. Tốt hơn, hãy để cài đặt autovacuum tích cực đảm bảo rằng autovacuum thực hiện điều đó trong nền cho bạn.

Bạn vẫn có thể TRUNCATE tất cả các bảng của bạn sau toàn bộ bộ thử nghiệm chạy để đảm bảo không có hiệu ứng nào tích tụ trong nhiều lần chạy. Trên 9.0 và mới hơn, VACUUM (FULL, ANALYZE); trên toàn cầu ít nhất là tốt nếu không muốn nói là tốt hơn và nó dễ dàng hơn rất nhiều.

IIRC Pg có một vài điểm tối ưu có nghĩa là nó có thể nhận thấy khi giao dịch của bạn là giao dịch duy nhất có thể nhìn thấy bảng và ngay lập tức đánh dấu các khối là miễn phí. Trong quá trình thử nghiệm, khi tôi muốn tạo bloat, tôi phải có nhiều hơn một kết nối đồng thời để làm điều đó. Tuy nhiên, tôi sẽ không dựa vào điều này.

DELETE FROM table; rất rẻ cho các bàn nhỏ không có f / k refs

Tới DELETE tất cả các bản ghi từ một bảng không có tham chiếu khóa ngoại đến nó, tất cả Pg phải thực hiện quét bảng tuần tự và đặt xmax trong số các bộ giá trị gặp phải. Đây là một hoạt động rất rẻ - về cơ bản là đọc tuyến tính và ghi bán tuyến tính. AFAIK nó không phải chạm vào các chỉ mục; chúng tiếp tục trỏ đến các bộ giá trị đã chết cho đến khi chúng được làm sạch bởi một VACUUM sau điều đó cũng đánh dấu các khối trong bảng chỉ chứa các bộ giá trị đã chết là miễn phí.

DELETE chỉ đắt tiền nếu có nhiều trong số các bản ghi, nếu có nhiều tham chiếu khóa ngoại phải được kiểm tra hoặc nếu bạn đếm bảng VACUUM (FULL, ANALYZE) table; cần để khớp với TRUNCATE các hiệu ứng trong phạm vi chi phí của DELETE của bạn .

Trong các bài kiểm tra của tôi ở đây, một bảng DELETE FROM table; thường nhanh hơn 4 lần so với TRUNCATE ở 0,5ms so với 2ms. Đó là DB thử nghiệm trên SSD, chạy với fsync=off bởi vì tôi không quan tâm nếu tôi mất tất cả dữ liệu này. Tất nhiên, DELETE FROM table; không thực hiện tất cả các công việc giống nhau và nếu tôi theo dõi với bảng VACUUM (FULL, ANALYZE); đó là 21ms đắt hơn nhiều, vì vậy DELETE chỉ là một chiến thắng nếu tôi thực sự không cần bàn nguyên sơ.

TRUNCATE table; thực hiện nhiều công việc với chi phí cố định và trông nhà hơn DELETE

Ngược lại, TRUNCATE phải làm rất nhiều việc. Nó phải cấp phát các tệp mới cho bảng, bảng TOAST của nó nếu có và mọi chỉ mục mà bảng có. Tiêu đề phải được ghi vào các tệp đó và danh mục hệ thống cũng có thể cần cập nhật (không chắc về điểm đó, chưa kiểm tra). Sau đó, nó phải thay thế các tệp cũ bằng tệp mới hoặc loại bỏ tệp cũ và phải đảm bảo hệ thống tệp đã bắt kịp các thay đổi bằng hoạt động đồng bộ hóa - fsync () hoặc tương tự - thường xóa tất cả các bộ đệm vào đĩa . Tôi không chắc liệu quá trình đồng bộ hóa có bị bỏ qua hay không nếu bạn đang chạy với tùy chọn (ăn dữ liệu) fsync=off .

Gần đây tôi đã biết rằng TRUNCATE cũng phải xóa tất cả các bộ đệm của PostgreSQL liên quan đến bảng cũ. Việc này có thể mất một khoảng thời gian không nhỏ với shared_buffers khổng lồ . Tôi nghi ngờ đây là lý do tại sao nó chậm hơn trên máy chủ CI của bạn.

Số dư

Dù sao, bạn có thể thấy rằng một TRUNCATE của một bảng có bảng TOAST được liên kết (hầu hết đều có) và một số chỉ mục có thể mất vài phút. Không dài, nhưng lâu hơn một DELETE từ một bảng gần như trống.

Do đó, bạn có thể tốt hơn nên thực hiện DELETE FROM table; .

-

Lưu ý:trên các DB trước 9.0, CLUSTER table_id_seq ON table; ANALYZE table; hoặc bảng VACUUM FULL ANALYZE table; REINDEX table; sẽ gần tương đương với TRUNCATE . VACUUM FULL impl đã thay đổi thành tốt hơn nhiều trong 9.0.



  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Chức năng cửa sổ và tổng hợp cục bộ hơn

  2. Cột postgres không tồn tại

  3. Chạy tập lệnh SQL thông qua psql đưa ra lỗi cú pháp không xảy ra trong PgAdmin

  4. Cài đặt postgresql với NSIS

  5. PostgreSQL:FATAL - Xác thực ngang hàng không thành công cho người dùng (PG ::ConnectionBad)