VACUUM trả lại không gian đĩa cho hệ điều hành


21

VACUUMthường không trả lại dung lượng đĩa cho hệ điều hành, trừ một số trường hợp đặc biệt.
Từ các tài liệu:

Hình thức tiêu chuẩn VACUUMloại bỏ các phiên bản hàng chết trong bảng và chỉ mục và đánh dấu không gian có sẵn để tái sử dụng trong tương lai. Tuy nhiên, nó sẽ không trả lại dung lượng cho hệ điều hành, trừ trường hợp đặc biệt khi một hoặc nhiều trang ở cuối bảng trở nên hoàn toàn miễn phí và có thể dễ dàng lấy được khóa bảng độc quyền. Ngược lại, VACUUM FULLchủ động tính toán các bảng bằng cách viết một phiên bản hoàn toàn mới của tệp bảng không có không gian chết. Điều này giảm thiểu kích thước của bảng, nhưng có thể mất nhiều thời gian. Nó cũng đòi hỏi thêm không gian đĩa cho bản sao mới của bảng, cho đến khi hoàn thành thao tác.

Câu hỏi là: làm thế nào cơ sở dữ liệu này one or more pages at the end of a table become entirely freecó thể đạt được khi đạt được? Điều này có thể được thực hiện thông qua VACUUM FULL, nhưng tôi không có đủ không gian để thực hiện nó. Vậy có khả năng nào khác không?

Câu trả lời:


29

Để trả lại dung lượng cho HĐH, hãy sử dụng VACUUM FULL. Trong khi ở đó, tôi cho rằng bạn chạy VACUUM FULL ANALYZE. Tôi trích dẫn hướng dẫn :

FULL

Chọn chân không "đầy đủ", có thể lấy lại nhiều không gian hơn , nhưng mất nhiều thời gian hơn và chỉ khóa bảng. Phương pháp này cũng cần thêm dung lượng đĩa, vì nó ghi một bản sao mới của bảng và không giải phóng bản sao cũ cho đến khi hoàn thành thao tác. Thông thường, điều này chỉ nên được sử dụng khi một lượng không gian đáng kể cần phải được thu hồi từ bên trong bảng.

Nhấn mạnh đậm của tôi.

CLUSTER đạt được điều đó, như là một hiệu ứng tài sản thế chấp.

Plain VACUUMthường không đạt được mục tiêu của bạn ( "một hoặc nhiều trang ở cuối bảng hoàn toàn miễn phí" ). Nó không sắp xếp lại các hàng và chỉ cắt các trang trống từ phần cuối vật lý của tệp khi có cơ hội - như trích dẫn của bạn từ hướng dẫn sử dụng.

Bạn có thể nhận được các trang trống ở cuối tệp vật lý khi bạn thực hiện INSERTmột loạt các hàng và DELETEchúng trước khi các bộ dữ liệu khác được nối thêm. Hoặc nó có thể xảy ra do sự trùng hợp nếu đủ hàng bị xóa.

Ngoài ra còn có các cài đặt đặc biệt có thể ngăn không cho VACUUM FULLlấy lại không gian. Xem:

Chuẩn bị các trang trống ở cuối bảng để kiểm tra

Cột hệ thống ctidđại diện cho vị trí vật lý của một hàng. Bạn cần hiểu cột đó:

Chúng tôi có thể làm việc với điều đó và chuẩn bị một bảng bằng cách xóa tất cả các hàng từ trang cuối cùng:

DELETE FROM tbl t
USING (
   SELECT (split_part(ctid::text, ',', 1) || ',0)')::tid     AS min_tid
        , (split_part(ctid::text, ',', 1) || ',65535)')::tid AS max_tid
   FROM   tbl
   ORDER  BY ctid DESC
   LIMIT  1
   ) d
WHERE t.ctid BETWEEN d.min_tid AND d.max_tid;

Bây giờ, trang cuối cùng trống rỗng. Điều này bỏ qua viết đồng thời. Hoặc bạn là người duy nhất viết vào bảng đó hoặc bạn cần thực hiện khóa ghi để tránh nhiễu.

Truy vấn được tối ưu hóa để xác định các hàng đủ điều kiện một cách nhanh chóng. Số thứ hai của a tidlà chỉ số tuple được lưu dưới dạng không dấu int265535là mức tối đa cho loại đó ( 2^16 - 1), do đó, đó là giới hạn trên an toàn.

SQL Fiddle (sử dụng lại một bảng đơn giản từ một trường hợp khác.)

Các công cụ để đo kích thước hàng / bảng:

Đĩa đầy

Bạn cần phòng ngọ nguậy trên đĩa cho bất kỳ hoạt động nào. Ngoài ra còn có công cụ cộng đồng pg_repackthay thế cho VACUUM FULL/ CLUSTER. Nó tránh các khóa độc quyền nhưng cũng cần không gian trống để làm việc. Hướng dẫn sử dụng:

Yêu cầu không gian đĩa trống lớn gấp đôi so với (các) bảng đích và các chỉ mục.

Như một phương sách cuối cùng, bạn có thể chạy một chu trình kết xuất / khôi phục. Điều đó cũng loại bỏ tất cả sự phình ra từ các bảng và chỉ mục. Câu hỏi liên quan chặt chẽ:

Câu trả lời ở đây là khá triệt để. Nếu tình huống của bạn cho phép điều đó (không có khóa ngoại hoặc tham chiếu khác ngăn chặn xóa hàng) và không có quyền truy cập đồng thời vào bảng), bạn có thể chỉ cần:

Kết xuất bảng vào đĩa kết nối từ một máy tính từ xanhiều không gian đĩa ( -acho --data-only):

Từ shell từ xa, kết xuất dữ liệu bảng:

pg_dump -h <host_name> -p <port> -t mytbl -a mydb > db_mytbl.sql

Trong một phiên pg, TRUNCATEbảng:

-- drop all indexes and constraints here for best performance
TRUNCATE mytbl;

Từ shell, khôi phục vào cùng một bảng:

psql -h <host_name> -p <port> mydb -f db_mytbl.sql
-- recreate all indexes and constraints here

Bây giờ nó là miễn phí của bất kỳ hàng chết hoặc sưng lên.

Nhưng có lẽ bạn có thể có đơn giản hơn?

  • Bạn có thể tạo đủ dung lượng trên đĩa bằng cách xóa (di chuyển) các tệp không liên quan không?

  • Bạn có thể đặt VACUUM FULLcác bảng nhỏ hơn trước, từng cái một, do đó giải phóng đủ dung lượng đĩa không?

  • Bạn có thể chạy REINDEX TABLEhoặc REINDEX INDEXđể giải phóng không gian đĩa từ các chỉ mục cồng kềnh?

Dù bạn làm gì, đừng nổi mẩn . Nếu nghi ngờ, hãy sao lưu mọi thứ vào vị trí an toàn trước.


Erwin, xin lỗi, tôi quên đề cập rằng tôi không có đủ không gian cho chân không đầy đủ. Cập nhật câu hỏi.
sai về tất cả mọi thứ

@Zapadlo: Tôi đã thêm một chương cho câu hỏi cập nhật.
Erwin Brandstetter

Cảm ơn câu trả lời toàn diện. Trên thực tế tôi đã nghĩ rằng tôi có thể đặt các hàng chết vào cuối các trang db bằng các cập nhật giả, tức là update table set field_1 = field_1, việc hút sạch bảng đó sau thao tác đó không trả lại được không gian trống, có ý tưởng nào không?
sai về tất cả mọi thứ

@Zapadlo: Những ý tưởng tôi đã có trong câu trả lời rồi. :) Tôi không biết về một công cụ có thể sắp xếp lại các bộ dữ liệu chết mà không cần phòng ngọ nguậy đáng kể trên đĩa. (Không có nghĩa là không thể có một người ngoài đó.)
Erwin Brandstetter 20/03/13

Họ nói rằng công cụ này thực hiện mánh khóe, mặc dù chưa thử: code.google.com/p/pgtoolkit/source/browse/trunk/bin/ Kẻ
sai về mọi thứ
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.