修改表数据会影响索引扫描吗?
Redrock Postgres 引入了撤消日志,修改元组时会标记删除索引记录,给索引记录标记事务状态信息。在不更新每个索引的情况下,只执行相关索引列的更新,修改表数据并不会影响索引扫描。
下面我们创建了一个表,插入一些数据,在表的id
字段上创建索引。提前执行下涉及索引扫描的查询,将索引数据加载到共享缓冲区。
CREATE TABLE t_large (id integer, name text);
INSERT INTO t_large (id, name)
SELECT i, repeat('Pg', 32)
FROM generate_series(1, 1000000) AS s(i);
CREATE INDEX large_idx ON t_large (id);
SET max_parallel_workers_per_gather = 0;
SELECT count(*) FROM t_large;
让我们先确认下这个查询确实使用了索引扫描,并记录下该查询的执行计划和统计信息。
EXPLAIN (analyze, buffers, costs off)
SELECT count(*) FROM t_large;
QUERY PLAN
---------------------------------------------------------------------------------------------------
Aggregate (actual time=102.074..102.075 rows=1 loops=1)
Buffers: shared hit=2
-> Index Only Scan using large_idx on t_large (actual time=0.017..57.880 rows=1000000 loops=1)
Heap Fetches: 0
Buffers: shared hit=2
Planning time: 0.075 ms
Execution time: 102.094 ms
让我们对表中的一部分数据进行一些更新,当然,也可以删除一部分数据。
UPDATE t_large SET name = 'dummy' WHERE mod(id, 100) = 1;
DELETE FROM t_large WHERE mod(id, 100) = 50;
让我们再来看看原来的查询使用的执行计划。
EXPLAIN (analyze, buffers, costs off)
SELECT count(*) FROM t_large;
QUERY PLAN
--------------------------------------------------------------------------------------------------
Aggregate (actual time=101.703..101.703 rows=1 loops=1)
Buffers: shared hit=2
-> Index Only Scan using large_idx on t_large (actual time=0.017..57.207 rows=990000 loops=1)
Heap Fetches: 0
Buffers: shared hit=2
Planning time: 0.079 ms
Execution time: 101.724 ms
从上面的测试结果来看,在我们对表t_large
更新和删除一部分数据后,原来的查询使用的执行计划没有发生变化,查询执行的时间也没有受到影响。