Ai đó có thể giải thích hành vi này cho tôi? Tôi đã chạy truy vấn sau đây trên Postgres 9.3 chạy trên OS X. Tôi đã cố gắng mô phỏng một số hành vi trong đó kích thước chỉ mục có thể lớn hơn nhiều so với kích thước bảng và thay vào đó tìm thấy thứ gì đó kỳ quái hơn.
CREATE TABLE test(id int);
CREATE INDEX test_idx ON test(id);
CREATE FUNCTION test_index(batch_size integer, total_batches integer) RETURNS void AS $$
DECLARE
current_id integer := 1;
BEGIN
FOR i IN 1..total_batches LOOP
INSERT INTO test VALUES (current_id);
FOR j IN 1..batch_size LOOP
UPDATE test SET id = current_id + 1 WHERE id = current_id;
current_id := current_id + 1;
END LOOP;
END LOOP;
END;
$$ LANGUAGE plpgsql;
SELECT test_index(500, 10000);
Tôi đã để nó chạy khoảng một giờ trên máy cục bộ của mình, trước khi tôi bắt đầu nhận được các cảnh báo về vấn đề đĩa từ OS X. Tôi nhận thấy rằng Postgres đã hút khoảng 10 MB / s từ đĩa cục bộ của tôi và cơ sở dữ liệu Postgres đã tiêu tốn tổng cộng 30GB từ máy của tôi. Tôi đã kết thúc việc hủy bỏ truy vấn. Bất kể, Postgres đã không trả lại dung lượng đĩa cho tôi và tôi đã truy vấn cơ sở dữ liệu để thống kê sử dụng với kết quả sau:
test=# SELECT nspname || '.' || relname AS "relation",
pg_size_pretty(pg_relation_size(C.oid)) AS "size"
FROM pg_class C
LEFT JOIN pg_namespace N ON (N.oid = C.relnamespace)
WHERE nspname NOT IN ('pg_catalog', 'information_schema')
ORDER BY pg_relation_size(C.oid) DESC
LIMIT 20;
relation | size
-------------------------------+------------
public.test | 17 GB
public.test_idx | 14 GB
Tuy nhiên, lựa chọn từ bảng mang lại không có kết quả.
test=# select * from test limit 1;
id
----
(0 rows)
Chạy 10000 lô 500 là 5.000.000 hàng, sẽ mang lại kích thước bảng / chỉ mục khá nhỏ (theo tỷ lệ MB). Tôi nghi ngờ rằng Postgres đang tạo một phiên bản mới của bảng / chỉ mục cho mỗi CHERTN / CẬP NHẬT đang xảy ra với chức năng, nhưng điều này có vẻ lạ. Toàn bộ chức năng được chạy giao dịch và bảng trống để bắt đầu.
Bất kỳ suy nghĩ về lý do tại sao tôi nhìn thấy hành vi này?
Cụ thể, hai câu hỏi tôi có là: tại sao không gian này chưa được cơ sở dữ liệu thu hồi và thứ hai là tại sao cơ sở dữ liệu yêu cầu nhiều không gian này ở nơi đầu tiên? 30 GB có vẻ như rất nhiều ngay cả khi chiếm MVCC