即使更新的列不是索引列,postgresql 也会更新索引吗?
Does postgresql update index even when the updated columns aren't the indexed ones?
我想用 GIN 或 GiST 索引数组列。然而,GIN 在 insert/update 操作中速度较慢这一事实让我想知道它是否会对性能产生任何影响——即使索引列本身将保持静态。
因此,假设,例如,我有一个 table 列 (A, B, C) 并且 B 被索引,如果我只更新列 C?
,索引会更新吗
视情况而定:^)
通常情况下,PostgreSQL 将不得不修改索引,即使索引列中没有任何变化,因为 PostgreSQL 中的 UPDATE
创建了一个新的行版本,因此您需要一个新的索引条目来指向table.
中行的新位置
由于这是不幸的,所以有一种称为“热更新”的优化:如果 none 的索引列被修改 和 则有在包含原始行 的块中有足够的空闲 space,PostgreSQL 可以创建一个未从外部引用的“heap-only 元组”,因此不需要新的索引条目。
您可以降低 table 上的 fillfactor
以增加热更新的可能性。
有关详细信息,您可能需要阅读 my article on the topic。
Laurenz Albe 的回答很棒。以下部分是我的解读。
因为ginarray_ops不能做index only scan。也就是说即使只查询数组列,也只能使用位图索引扫描。用于位图扫描。低填充因子,您可能不需要访问提取页面。
演示:
begin;
create table test_gin_update(cola int, colb int[]);
insert into test_gin_update values (1,array[1,2]);
insert into test_gin_update values (1,array[1,2,3]);
insert into test_gin_update(cola, colb) select g, array[g, g + 1] from generate_series(10, 10000) g;
commit;
例如,select colb from test_gin_update where colb = array[1,2];
请参阅以下查询计划。
因为 GIN 无法区分 array[1,2]
和 array[1,2,3]
那么即使我们创建了 gin 索引。 create index on test_gin_update using gin(colb array_ops );
我们只能使用位图索引扫描。
QUERY PLAN
-----------------------------------------------------------------------------
Bitmap Heap Scan on test_gin_update (actual rows=1 loops=1)
Recheck Cond: (colb = '{1,2}'::integer[])
Rows Removed by Index Recheck: 1
Heap Blocks: exact=1
-> Bitmap Index Scan on test_gin_update_colb_idx (actual rows=2 loops=1)
Index Cond: (colb = '{1,2}'::integer[])
(6 rows)
我想用 GIN 或 GiST 索引数组列。然而,GIN 在 insert/update 操作中速度较慢这一事实让我想知道它是否会对性能产生任何影响——即使索引列本身将保持静态。 因此,假设,例如,我有一个 table 列 (A, B, C) 并且 B 被索引,如果我只更新列 C?
,索引会更新吗视情况而定:^)
通常情况下,PostgreSQL 将不得不修改索引,即使索引列中没有任何变化,因为 PostgreSQL 中的 UPDATE
创建了一个新的行版本,因此您需要一个新的索引条目来指向table.
由于这是不幸的,所以有一种称为“热更新”的优化:如果 none 的索引列被修改 和 则有在包含原始行 的块中有足够的空闲 space,PostgreSQL 可以创建一个未从外部引用的“heap-only 元组”,因此不需要新的索引条目。
您可以降低 table 上的 fillfactor
以增加热更新的可能性。
有关详细信息,您可能需要阅读 my article on the topic。
Laurenz Albe 的回答很棒。以下部分是我的解读。
因为ginarray_ops不能做index only scan。也就是说即使只查询数组列,也只能使用位图索引扫描。用于位图扫描。低填充因子,您可能不需要访问提取页面。
演示:
begin;
create table test_gin_update(cola int, colb int[]);
insert into test_gin_update values (1,array[1,2]);
insert into test_gin_update values (1,array[1,2,3]);
insert into test_gin_update(cola, colb) select g, array[g, g + 1] from generate_series(10, 10000) g;
commit;
例如,select colb from test_gin_update where colb = array[1,2];
请参阅以下查询计划。
因为 GIN 无法区分 array[1,2]
和 array[1,2,3]
那么即使我们创建了 gin 索引。 create index on test_gin_update using gin(colb array_ops );
我们只能使用位图索引扫描。
QUERY PLAN
-----------------------------------------------------------------------------
Bitmap Heap Scan on test_gin_update (actual rows=1 loops=1)
Recheck Cond: (colb = '{1,2}'::integer[])
Rows Removed by Index Recheck: 1
Heap Blocks: exact=1
-> Bitmap Index Scan on test_gin_update_colb_idx (actual rows=2 loops=1)
Index Cond: (colb = '{1,2}'::integer[])
(6 rows)