tl; dr: Quá trình đầu tiên đọc dữ liệu sau khi được cam kết sẽ đặt các bit gợi ý. Điều đó sẽ làm bẩn trang, tạo ra hoạt động viết. Điều khác VACUUM
(nhưng không phải các lệnh khác) là đánh dấu trang là hiển thị tất cả, nếu phù hợp. VACUUM
cuối cùng sẽ phải đập bàn để đóng băng các bộ dữ liệu.
Công việc cần được thực hiện sau khi chèn không thực sự dọn dẹp, ít nhất là không phải theo nghĩa của công việc khác VACUUM
thông thường. Trước khi tôi đi vào chi tiết, lưu ý rằng câu trả lời này dựa trên mã 9.6 hiện tại (chưa được phát hành) và tôi bỏ qua các hiệu ứng của sao chép phát trực tuyến, mặc dù nó có thể ảnh hưởng đến khả năng hiển thị.
Do MVCC , mỗi khi Postgres đánh giá xem một bộ dữ liệu có thể hiển thị cho một truy vấn hay không, nó phải xem xét liệu giao dịch đã tạo bộ dữ liệu (được ghi trong trường ẩn xmin) được cam kết, cùng với một số tiêu chí khác. Kiểm tra đó rất tốn kém, vì vậy ngay khi biết rằng một giao dịch hiển thị cho tất cả các giao dịch hiện đang mở, một "bit gợi ý" được đặt trên tiêu đề tuple chỉ ra rằng. Cài đặt của bit đó làm mất hiệu lực trang, có nghĩa là nó sẽ phải được ghi vào đĩa. Điều này có thể rất khó hiểu nếu lệnh tiếp theo để đọc dữ liệu là một SELECT
thứ đột nhiên tạo ra nhiều lưu lượng ghi. Chạy một VACUUM
sau khi cam kết chèn sẽ tránh điều đó. Một điểm khác biệt quan trọng làVACUUM
sẽ LUÔN gợi ý các bộ dữ liệu trên một trang (miễn là nó có khóa dọn dẹp trên trang), nhưng hầu hết các lệnh khác sẽ chỉ gợi ý nếu giao dịch chèn được cam kết trước khi lệnh bắt đầu.
Một điểm quan trọng về việc viết tất cả các bit gợi ý này là VACUUM
có thể được điều chỉnh (và autovacuum được điều chỉnh theo mặc định). Các lệnh khác không được điều chỉnh và sẽ tạo ra dữ liệu bẩn càng nhanh càng tốt.
VACUUM
là phương pháp duy nhất để đánh dấu các trang là hiển thị toàn bộ, đây là một xem xét hiệu suất quan trọng đối với một số hoạt động (đáng chú ý là chỉ quét chỉ mục). Nếu bạn thực hiện một thao tác chèn lớn, rất có thể có nhiều trang không có gì ngoài các bộ dữ liệu mới được chèn. VACUUM
có khả năng có thể đánh dấu các trang đó là hiển thị toàn bộ, nhưng chỉ khi giao dịch cũ nhất được chạy khi VACUUM
bắt đầu mới hơn giao dịch đã chèn dữ liệu .
Do cách thức hoạt động của MVCC, các bộ dữ liệu được chèn hơn ~ 2 tỷ giao dịch trước đây phải được đánh dấu là " đóng băng ". Theo mặc định, autovacuum sẽ khởi động để thực hiện điều đó cứ sau 200 triệu giao dịch. Chạy chân không thủ công với chân không_freeze_min_age được đặt thành 0 sau khi chèn số lượng lớn có thể giúp giảm tác động của điều đó. Tích cực hơn, bạn có thể chạy VACUUM FREEZE
trên bàn sau khi chèn. Điều đó sẽ "đặt lại đồng hồ" khi lần quét đóng băng tiếp theo xảy ra.
Nếu bạn muốn biết chi tiết cụ thể, hãy xem HEAPTUPLE_LIVE
trường hợp sau khi gọi đến HeapTupleSatisfiesVacuum()
bên trong lazy_scan_heap()
. Cũng xem HeapTupleSatisfiesVacuum()
chính nó, và so sánh nó với HeapTupleSatisfiesMVCC()
.
Có hai bài thuyết trình khác của tôi có thể thú vị. Video đầu tiên có sẵn từ http://www.pgcon.org/2015/schedule/events/829.en.html , trong khi video thứ hai (mà tôi nghĩ là tốt hơn một chút) tại https://www.youtube. com / đồng hồ? v = L8nErzxPJjQ
EXPLAIN (ANALYZE, BUFFERS) outputs. But, if I understand things correctly, some of the hint bits (at least
* CAM KẾT 'và*INVALID
) có thể (có thể) đã được đặt bởiCOMMIT
hoặcROLLBACK
, phải không?