Redrock Postgres 文档
主页 切换暗/亮/自动模式 切换暗/亮/自动模式 切换暗/亮/自动模式 返回首页
编辑页面

修改表数据会影响索引扫描吗?

问题解答

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更新和删除一部分数据后,原来的查询使用的执行计划没有发生变化,查询执行的时间也没有受到影响。