我正在尝试在Postgres 9.4中为大型(1.2TB)静态表创建部分索引。
我的数据是完全静态的,因此我可以插入所有数据,然后创建所有索引。
在这个1.2TB的表中,我有一列名为run_id
,它清楚地划分了数据。通过创建覆盖run_id
s 范围的索引,我们获得了出色的性能。这是一个例子:
CREATE INDEX perception_run_frame_idx_run_266_thru_270
ON run.perception
(run_id, frame)
WHERE run_id >= 266 AND run_id <= 270;
这些部分索引为我们提供了所需的查询速度。不幸的是,每个部分索引的创建大约需要70分钟。
看来我们受CPU限制(top
正在显示该进程的100%)。
我有什么办法可以加快创建部分索引的速度?
系统规格:
- 18核至强
- 192GB内存
- RAID中的12个SSD
- 自动真空关闭
- maintenance_work_mem:64GB(太高了吗?)
表规格:
- 大小:1.26 TB
- 行数:105.37亿
- 典型索引大小:3.2GB(存在〜.5GB的差异)
表定义:
CREATE TABLE run.perception(
id bigint NOT NULL,
run_id bigint NOT NULL,
frame bigint NOT NULL,
by character varying(45) NOT NULL,
by_anyone bigint NOT NULL,
by_me bigint NOT NULL,
by_s_id integer,
owning_p_id bigint NOT NULL,
obj_type_set bigint,
seq integer,
subj_id bigint NOT NULL,
subj_state_frame bigint NOT NULL,
CONSTRAINT perception_pkey PRIMARY KEY (id))
(不要在列名中读太多-我对它们有些混淆。)
背景信息:
- 我们在现场有一个单独的团队来使用此数据,但实际上只有一两个用户。(这些数据都是通过模拟生成的。)用户仅在插入完成并完全建立索引后才开始分析数据。我们主要关注的是减少生成可用数据所需的时间,而目前的瓶颈是索引创建时间。
- 使用局部函数时,查询速度已完全足够。实际上,我认为我们可以增加每个索引涵盖的运行次数,并仍然保持足够好的查询性能。
- 我的猜测是我们将不得不对表进行分区。在尝试该路线之前,我们正在尝试穷尽所有其他选择。
completely static
,那是什么意思We have a separate team onsite that consumes this data
?您只是索引范围run_id >= 266 AND run_id <= 270
还是整个表?每个索引的预期寿命是多少/将使用多少个查询?有多少个不同的值run_id
?听起来像〜15Mio。每行run_id
,这将使其大约有800个不同的值run_id
?为什么obj_type_set
,by_s_id
,seq
没有定义NOT NULL?每个值的NULL值的大致百分比是多少?
run_id
?平均分配?磁盘上所得索引的大小?数据是静态的,可以。但是,您是唯一的用户吗?