誰かがこの動作を私に説明できますか?OS Xでネイティブに実行されているPostgres 9.3で次のクエリを実行しました。インデックスサイズがテーブルサイズよりも大きくなる可能性がある動作をシミュレートしようとしましたが、さらに奇妙なものが見つかりました。
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からディスクの問題の警告を受け取る前に、ローカルマシンでこれを約1時間実行しました。Postgresがローカルディスクから約10MB / sを消費していて、Postgresデータベースが合計を消費していることに気付きました私のマシンから30GBの。クエリをキャンセルしてしまいました。とにかく、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)
500の10000バッチを実行すると5,000,000行になるため、テーブル/インデックスのサイズはかなり小さくなります(MBのスケールで)。Postgresが関数で起こっているINSERT / UPDATEごとにテーブル/インデックスの新しいバージョンを作成していると思いますが、これは奇妙に見えます。関数全体がトランザクションで実行され、開始時にテーブルは空でした。
なぜ私はこの動作を見ているのですか?
具体的には、私が持っている2つの質問は次のとおりです。なぜこのスペースがデータベースによってまだ再利用されていないのですか。MVCCを考慮に入れても、30 GBは多くのようです