在postgresql远程fdw表上使用select查询降低性能

rbl8hiat  于 2023-08-04  发布在  PostgreSQL
关注(0)|答案(1)|浏览(82)

我在同一网络的不同计算机(X和Y)上有2个postgresql示例。Y服务器上安装了PgAdmin,并连接到两个示例。
在Y示例上,我为X上的数据库创建了FDW连接。
我的问题是当我在外部表上运行选择查询时,它花了30多秒。如果我从PgAdmin直接向X服务器运行相同的查询,只需不到1秒的时间,我认为性能低下的原因可能不是网络问题。
我用onoffuse_remote_estimate都试过了,但是由于我的外键表不断更新新数据,我决定保留它off
我的查询如下

SELECT q_num,
    count(*)::integer AS total_calls,
    count(1) FILTER (WHERE na_code = 0 AND fail_code = 0)::integer AS answered,
    count(1) FILTER (WHERE na_code = 0 AND fail_code = 0 AND (wait + poll) <= '00:00:15'::interval)::integer AS answered_15,
    count(1) FILTER (WHERE na_code = 0 AND fail_code = 0 AND (wait + poll) <= '00:00:20'::interval)::integer AS answered_20,
    count(1) FILTER (WHERE na_code = 0 AND fail_code = 0 AND (wait + poll) <= '00:00:30'::interval)::integer AS answered_30,
    count(1) FILTER (WHERE na_code <> 0 OR fail_code <> 0)::integer AS missed,
    count(1) FILTER (WHERE na_code <> 0 OR fail_code <> 0 AND (wait + poll) > '00:00:15'::interval)::integer AS missed_15,
    count(1) FILTER (WHERE na_code <> 0 OR fail_code <> 0 AND (wait + poll) > '00:00:20'::interval)::integer AS missed_20,
    count(1) FILTER (WHERE na_code <> 0 OR fail_code <> 0 AND (wait + poll) > '00:00:30'::interval)::integer AS missed_30,
    EXTRACT(epoch FROM sum(wait + poll))::integer AS total_waiting,
    EXTRACT(epoch FROM max(wait + poll))::integer AS max_waiting
FROM foreign_table
WHERE time_start > (CURRENT_TIMESTAMP - '03:15:00'::interval)
GROUP BY q_num

字符串
time_start列在远程服务器上具有索引。
如何提高性能?
EDIT:尝试增加fetch_size,但仍需要20秒以上。
@弗兰克·海肯斯这是索引

CREATE INDEX IF NOT EXISTS original_table_time_start_idx
    ON public.original_table USING btree
    (time_start ASC NULLS LAST)
    TABLESPACE pg_default;


X示例上的Postgresql版本
PostgreSQL 11.9,由Visual C内部版本号1914编译,64位
Y示例上的Postgresql版本
PostgreSQL 14.5,由Visual C
编译,内部版本号1914,64位
X示例上的EXPLAIN(分析、动词、缓冲区)

GroupAggregate  (cost=8.51..8.91 rows=2 width=49) (actual time=0.148..0.150 rows=1 loops=1)    
Output: q_num, (count(*))::integer, (count(1) FILTER (WHERE ((na_code = 0) AND (fail_code = 0))))::integer, (count(1) FILTER (WHERE ((na_code = 0) AND (fail_code = 0) AND ((wait + poll) <= '00:00:15'::interval))))::integer, (count(1) FILTER (WHERE ((na_code = 0) AND (fail_code = 0) AND ((wait + poll) <= '00:00:20'::interval))))::integer, (count(1) FILTER (WHERE ((na_code = 0) AND (fail_code = 0) AND ((wait + poll) <= '00:00:30'::interval))))::integer, (count(1) FILTER (WHERE ((na_code <> 0) OR (fail_code <> 0))))::integer, (count(1) FILTER (WHERE ((na_code <> 0) OR ((fail_code <> 0) AND ((wait + poll) > '00:00:15'::interval)))))::integer, (count(1) FILTER (WHERE ((na_code <> 0) OR ((fail_code <> 0) AND ((wait + poll) > '00:00:20'::interval)))))::integer, (count(1) FILTER (WHERE ((na_code <> 0) OR ((fail_code <> 0) AND ((wait + poll) > '00:00:30'::interval)))))::integer, (date_part('epoch'::text, sum((wait + poll))))::integer, (date_part('epoch'::text, max((wait + poll))))::integer
Group Key: original_table.q_num    
Buffers: shared hit=4   
->  Sort (cost=8.51..8.51 rows=3 width=45) (actual time=0.099..0.101 rows=3 loops=1) 
Output: q_num, na_code, fail_code, wait, poll 
Sort Key: original_table.q_num 
Sort Method: quicksort  
Memory: 25kB 
Buffers: shared hit=4
->  Index Scan using original_table_time_start_idx on public.original_table  (cost=0.43..8.48 rows=3 width=45) (actual time=0.052..0.060 rows=3 loops=1) 
Output: q_num, na_code, fail_code, wait, poll 
Index Cond: (original_table.time_start > (CURRENT_TIMESTAMP - '00:15:00'::interval)) 
Buffers: shared hit=4 
Planning Time: 1.383 ms 
Execution Time: 0.638 ms


Y示例上的EXPLAIN(分析、动词、缓冲区)

GroupAggregate  (cost=48287.41..48295.41 rows=6 width=49) (actual time=22846.842..22846.847 rows=1 loops=1)   
Output: q_num, (count(*))::integer, (count(1) FILTER (WHERE ((na_code = 0) AND (fail_code = 0))))::integer, (count(1) FILTER (WHERE ((na_code = 0) AND (fail_code = 0) AND ((wait + poll) <= '00:00:15'::interval))))::integer, (count(1) FILTER (WHERE ((na_code = 0) AND (fail_code = 0) AND ((wait + poll) <= '00:00:20'::interval))))::integer, (count(1) FILTER (WHERE ((na_code = 0) AND (fail_code = 0) AND ((wait + poll) <= '00:00:30'::interval))))::integer, (count(1) FILTER (WHERE ((na_code <> 0) OR (fail_code <> 0))))::integer, (count(1) FILTER (WHERE ((na_code <> 0) OR ((fail_code <> 0) AND ((wait + poll) > '00:00:15'::interval)))))::integer, (count(1) FILTER (WHERE ((na_code <> 0) OR ((fail_code <> 0) AND ((wait + poll) > '00:00:20'::interval)))))::integer, (count(1) FILTER (WHERE ((na_code <> 0) OR ((fail_code <> 0) AND ((wait + poll) > '00:00:30'::interval)))))::integer, (EXTRACT(epoch FROM sum((wait + poll))))::integer, (EXTRACT(epoch FROM max((wait + poll))))::integer
Group Key: foreign_table.q_num   
->  Sort  (cost=48287.41..48287.59 rows=72 width=45) (actual time=22846.755..22846.759 rows=1 loops=1)
Output: q_num, na_code, fail_code, wait, poll
Sort Key: foreign_table.q_num
Sort Method: quicksort  
Memory: 25kB
->  Foreign Scan on public.foreign_table  (cost=100.00..48285.19 rows=72 width=45) (actual time=10927.554..22846.717 rows=1 loops=1)
Output: q_num, na_code, fail_code, wait, poll
Filter: (foreign_table.time_start > (CURRENT_TIMESTAMP - '03:15:00'::interval))
Rows Removed by Filter: 720077
Remote SQL: SELECT q_num, time_start, wait, poll, na_code, fail_code FROM public.original_table 
Planning Time: 0.522 ms 
Execution Time: 22849.716 ms


我希望这些信息能有所帮助。

lrl1mhuk

lrl1mhuk1#

使用CURRENT_TIMESTAMP的表达式不被视为可发送到外部端。你可以说它应该是可交付的,因为你可以把它具体化为一个文字,然后交付文字,但这就是它目前的工作方式。因此,所有行都需要被读回,并在本地测试它们的时间戳。
EDIT:尝试增加fetch_size,但仍需要20秒以上。
你把它加到多少了?也许再增加一些。

相关问题