Может ли кто-нибудь объяснить мне это поведение? Я выполнил следующий запрос на Postgres 9.3, работающем изначально на OS X. Я пытался смоделировать какое-то поведение, когда размер индекса мог вырасти намного больше размера таблицы, и вместо этого нашел что-то еще более странное.
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);
Я позволил этой программе работать на моем локальном компьютере около часа, прежде чем я начал получать предупреждения о проблемах диска из OS X. Я заметил, что Postgres высасывает со своего локального диска около 10 МБ / с и что база данных Postgres потребляет общую сумму. 30 ГБ с моей машины. Я закончил тем, что отменил запрос. Несмотря на это, Postgres не вернул мне дисковое пространство, и я запросил базу данных для статистики использования со следующим результатом:
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
Однако выбор из таблицы не дал результатов.
test=# select * from test limit 1;
id
----
(0 rows)
Выполнение 10000 пакетов по 500 означает 5 000 000 строк, что должно привести к довольно небольшому размеру таблицы / индекса (в масштабе МБ). Я подозреваю, что Postgres создает новую версию таблицы / индекса для каждого INSERT / UPDATE, что происходит с функцией, но это кажется странным. Вся функция выполняется транзакционно, и таблица была пуста для запуска.
Есть мысли о том, почему я вижу это поведение?
В частности, у меня есть два вопроса: почему эта область еще не была восстановлена базой данных, и второй - почему база данных потребовала столько места в первую очередь? 30 ГБ кажется много, даже если учитывать MVCC