我在 Postgres 14.7 中有下表
create table product
(
id uuid,
description varchar,
created_at timestamptz,
primary key (id)
);
create index idx__product__created_at on product(created_at);
该表有数亿条记录,并且为了简化而省略了更多列。现在我想做以下改变:
alter table product
add column published_to_kafka timestamptz default null;
create index idx__product_published_to_kafka on product (created_at asc) where published_to_kafka is null;
我无法承受数据库的性能问题,即使是很短的一段时间,我担心创建索引会让数据库变慢。
如果执行创建索引的命令时,数据库中的大部分记录
published_to_kafka
列不为空,那么创建索引的性能是否会更快?
我无法承受数据库的性能问题,即使是很短的一段时间,我担心创建索引会让数据库变慢。
我认为你需要清楚“慢数据库”和“锁定表”之间的区别——常规的
CREATE INDEX
会锁定表直到索引建立,暂时阻止用户获取一些数据。虽然用户可能会感觉到网页加载缓慢,但这实际上是短暂的中断,因为数据无法访问。如果您希望防止这种服务中断,则必须使用 CREATE INDEX CONCURRENTLY
,它可以解决锁定行为。
如果您真正关心索引构建的性能,我认为重要的是要记住,要创建索引,必须访问每一行,并且需要分析相关列才能创建索引。我们无法避免扫描每一行。但话又说回来,如果没有索引,您可能必须在
SELECT
期间扫描每一行(当然,除非您正在具有唯一约束的列上搜索,并且前几行返回您要查找的内容) ).
建立索引后,索引的内容将驻留在内存中(因为需要对事物进行排序),直到准备好将其持久化到磁盘。因此,如果
maintenance_work_mem
不够大,一些排序操作将在磁盘上而不是在内存中完成,从而会减慢 CREATE INDEX
操作。
正如其他人在评论中提到的,如果您担心无法“承受数据库的性能问题,即使是短时间内”,您需要重新评估您当前的硬件是否足以满足您的需求。如果
SELECT * FROM <table_to_be_indexed>
减慢了数据库速度,或者 VACUUM <table_to_be_indexed>
减慢了数据库速度,则您的硬件可能不适合您的需求。
如果执行创建索引的命令时,数据库中的大部分记录
列不为空,那么创建索引的性能是否会更快?published_to_kafka
有可能——您仍然需要遍历每一行,但排序可能会更快,因为要排序的值较少。