#1. 创建测试数据表。 postgres=# CREATE TABLE testtable (i integer); CREATE TABLE #2. 为测试表创建索引。 postgres=# CREATE INDEX testtable_idx ON testtable(i); CREATE INDEX #3. 创建批量插入测试数据的函数。 postgres=# CREATE OR REPLACE FUNCTION test_insert() returns integer AS $$ DECLARE min integer; max integer; BEGIN SELECT COUNT(*) INTO min from testtable; max := min + 10000; FOR i IN min..max LOOP INSERT INTO testtable VALUES(i); END LOOP; RETURN 0; END; $$ LANGUAGE plpgsql; CREATE FUNCTION #4. 批量插入数据到测试表(执行四次) postgres=# SELECT test_insert(); test_insert ------------- 0 (1 row) #5. 确认四次批量插入都成功。 postgres=# SELECT COUNT(*) FROM testtable; count ------- 40004 (1 row) #6. 分析测试表,以便有关该表的统计信息被更新到PostgreSQL的系统表。 postgres=# ANALYZE testtable; ANALYZE #7. 查看测试表和索引当前占用的页面数量(通常每个页面为8k)。 postgres=# SELECT relname,relfilenode, relpages FROM pg_class WHERE relname = 'testtable' or relname = 'testtable_idx'; relname | relfilenode | relpages ---------------+-------------+---------- testtable | 17601 | 157 testtable_idx | 17604 | 90 #8. 批量删除数据。 postgres=# DELETE FROM testtable WHERE i < 30000; DELETE 30003 #9. 执行vacuum和analyze,以便更新系统表,同时为该表和索引记录高水标记。 #10. 这里需要额外说明的是,上面删除的数据均位于数据表的前部,如果删除的是末尾部分, # 如where i > 10000,那么在执行VACUUM ANALYZE的时候,数据表将会被物理的缩小。 postgres=# VACUUM ANALYZE testtable; ANALYZE #11. 查看测试表和索引在删除后,再通过VACUUM ANALYZE更新系统统计信息后的结果(保持不变)。 postgres=# SELECT relname,relfilenode, relpages FROM pg_class WHERE relname = 'testtable' or relname = 'testtable_idx'; relname | relfilenode | relpages ---------------+-------------+---------- testtable | 17601 | 157 testtable_idx | 17604 | 90 (2 rows) #12. 再重新批量插入两次,之后在分析该表以更新其统计信息。 postgres=# SELECT test_insert(); --执行两次。 test_insert ------------- 0 (1 row) postgres=# ANALYZE testtable; ANALYZE #13. 此时可以看到数据表中的页面数量仍然为之前的高水标记数量,索引页面数量的增加 # 是和其内部实现方式有关,但是在后面的插入中,索引所占的页面数量就不会继续增加。 postgres=# SELECT relname,relfilenode, relpages FROM pg_class WHERE relname = 'testtable' or relname = 'testtable_idx'; relname | relfilenode | relpages ---------------+-------------+---------- testtable | 17601 | 157 testtable_idx | 17604 | 173 (2 rows) postgres=# SELECT test_insert(); test_insert ------------- 0 (1 row) postgres=# ANALYZE testtable; ANALYZE #14. 可以看到索引的页面数量确实没有继续增加。 postgres=# SELECT relname,relfilenode, relpages FROM pg_class WHERE relname = 'testtable' or relname = 'testtable_idx'; relname | relfilenode | relpages ---------------+-------------+---------- testtable | 17601 | 157 testtable_idx | 17604 | 173 (2 rows) #15. 重新批量删除数据。 postgres=# DELETE FROM testtable WHERE i < 30000; DELETE 19996 #16. 从后面的查询可以看出,在执行VACUUM FULL命令之后,测试表和索引所占用的页面数量 # 确实降低了,说明它们占用的物理空间已经缩小了。 postgres=# VACUUM FULL testtable; VACUUM postgres=# SELECT relname,relfilenode, relpages FROM pg_class WHERE relname = 'testtable' or relname = 'testtable_idx'; relname | relfilenode | relpages ---------------+-------------+---------- testtable | 17602 | 118 testtable_idx | 17605 | 68 (2 rows) |