Postgresql 如何在postgres上的列表分区表中按id获取元素,而无需扫描所有表中的索引?

Postgresql 如何在postgres上的列表分区表中按id获取元素,而无需扫描所有表中的索引?,postgresql,table-partitioning,Postgresql,Table Partitioning,我在pg专业11中有以下场景: DROP TABLE IF EXISTS public.agent_sessions_partitioned; CREATE TABLE public.agent_sessions_partitioned ( id uuid NOT NULL DEFAULT uuid_generate_v4(), account_id uuid, user_i

我在pg专业11中有以下场景:

DROP TABLE IF EXISTS public.agent_sessions_partitioned;

CREATE TABLE public.agent_sessions_partitioned
            (
                id uuid NOT NULL DEFAULT uuid_generate_v4(),
                account_id uuid,
                user_id uuid
            ) PARTITION BY LIST (account_id);

CREATE TABLE "agent_sessions_bcbc5acc-f020-4073-bdf4-3098bc043e8b"
                  PARTITION OF agent_sessions_partitioned
                  FOR VALUES IN ('bcbc5acc-f020-4073-bdf4-3098bc043e8b'); 

INSERT INTO agent_sessions_partitioned (id, account_id, user_id)
    SELECT agent_sessions.id, account_id, user_id FROM agent_sessions; 

ALTER TABLE "agent_sessions_bcbc5acc-f020-4073-bdf4-3098bc043e8b" ADD PRIMARY KEY (id); 
等等

当我遇到这样的问题时,这种方法非常有效:

Select * from agent_sessions_partitioned where account_id = 'XX'
但是,因为我使用的是ORM(Rails-Active record),所以我没有在对账单中以及需要执行以下操作时始终使用帐户id的选项:

UPDATE agent_sessions_partitioned set user_id = 'x' where id = 'y'
PG扫描所有试图找到此元组的子表,请参见下面的解释分析:

"Append  (cost=0.28..2612.12 rows=355 width=558) (actual time=0.956..277.658 rows=1 
loops=1)"
"  ->  Index Scan using "agent_sessions_a13f3c88-3022-4676-bd48-6580d8877ae2_pkey" on 
"agent_sessions_a13f3c88-3022-4676-bd48-6580d8877ae2"  (cost=0.28..8.30 rows=1 width=500)             
(actual time=0.955..0.956 rows=1 loops=1)"
"        Index Cond: (id = 'b21a0178-f97c-4598-ba39-bf763ba377b5'::uuid)"
"  ->  Index Scan using "agent_sessions_325774d6-e5e7-4fae-9659-8b76349a6c2a_pkey" on 
"agent_sessions_325774d6-e5e7-4fae-9659-8b76349a6c2a"  (cost=0.29..8.30 rows=1 width=481) 
(actual time=0.750..0.750 rows=0 loops=1)"
"        Index Cond: (id = 'b21a0178-f97c-4598-ba39-bf763ba377b5'::uuid)"
"  ->  Index Scan using "agent_sessions_1f781bcd-b941-4915-949a-9af893d8f066_pkey" on 
"agent_sessions_1f781bcd-b941-4915-949a-9af893d8f066"  (cost=0.29..8.30 rows=1 width=507) 
 (actual time=1.523..1.523 rows=0 loops=1)"

由于我无法更改此按id更新记录的查询,在postgres方面我可以做些什么吗?任何可能对我有帮助的配置或其他类型的分区,甚至升级到第12/13页的版本?

不,除非以不同的方式分区表,否则无法避免增加的计划和执行成本

与通常的看法相反,对表进行分区会减慢大多数使用该表的SQL语句的速度。只有在极少数情况下,当您可以将顺序扫描限制为分区的子集时,您才会看到性能的提高。请注意,大表上的索引扫描并不明显比小表上的索引扫描慢

相反,您可以使用分区来获得在批量操作中添加和删除许多表行的速度和灵活性(在PostgreSQL中,它也有助于在大型表上使用autovacuum)。对查询的性能影响是您为此付出的代价


除非你有太多的分区(小心!),否则影响不会太大。您可以使用准备好的语句来减少查询的计划时间,如您问题中的查询。

不,除非您以不同的方式划分表,否则无法避免增加的计划和执行成本

与通常的看法相反,对表进行分区会减慢大多数使用该表的SQL语句的速度。只有在极少数情况下,当您可以将顺序扫描限制为分区的子集时,您才会看到性能的提高。请注意,大表上的索引扫描并不明显比小表上的索引扫描慢

相反,您可以使用分区来获得在批量操作中添加和删除许多表行的速度和灵活性(在PostgreSQL中,它也有助于在大型表上使用autovacuum)。对查询的性能影响是您为此付出的代价


除非你有太多的分区(小心!),否则影响不会太大。您可以使用预先准备好的语句来减少查询的计划时间,如您问题中的查询。

请问您为什么要使用分区?你的桌子特别大吗?您最好使用一个在“id”上有索引,在“account_id”上有索引的常规表。您应该始终按照分区规则访问数据,否则postgres无法确定数据位于何处。是的,我的表越来越大,我发现的策略之一就是对表进行分区。例如,我有一张180米长的桌子。我可以问一下你为什么使用分区吗?你的桌子特别大吗?您最好使用一个在“id”上有索引,在“account_id”上有索引的常规表。您应该始终按照分区规则访问数据,否则postgres无法确定数据位于何处。是的,我的表越来越大,我发现的策略之一就是对表进行分区。例如,我有一张180米长的桌子。记录。嗨,Laurenz,谢谢你的回答,我现在大概有350个分区。对于PostgreSQL v12或v13,应该可以。我仍然会运行测试。嗨,Laurenz,谢谢你的回答,我现在会有大约350个分区。对于PostgreSQL v12或v13,应该可以。我仍然会运行测试。