有人可以向我解释这种行为吗?我在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接收磁盘问题警告之前,我在本地计算机上运行了大约一个小时。我注意到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)
运行10000个批次(共500个)将产生5,000,000行,这将产生非常小的表/索引大小(以MB为单位)。我怀疑Postgres正在为函数发生的每个INSERT / UPDATE创建表/索引的新版本,但这似乎很奇怪。整个功能以事务方式运行,并且该表为空以启动。
对为什么我看到这种行为有任何想法吗?
具体来说,我有两个问题:为什么数据库尚未收回此空间,第二个原因是为什么数据库首先需要这么多空间?即使考虑MVCC,30GB似乎也很多