我在同一网络的不同计算机(X和Y)上有2个postgresql示例。Y服务器上安装了PgAdmin,并连接到两个示例。
在Y示例上,我为X上的数据库创建了FDW连接。
我的问题是当我在外部表上运行选择查询时,它花了30多秒。如果我从PgAdmin直接向X服务器运行相同的查询,只需不到1秒的时间,我认为性能低下的原因可能不是网络问题。
我用on
和off
对use_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
型
我希望这些信息能有所帮助。
1条答案
按热度按时间lrl1mhuk1#
使用CURRENT_TIMESTAMP的表达式不被视为可发送到外部端。你可以说它应该是可交付的,因为你可以把它具体化为一个文字,然后交付文字,但这就是它目前的工作方式。因此,所有行都需要被读回,并在本地测试它们的时间戳。
EDIT:尝试增加fetch_size,但仍需要20秒以上。
你把它加到多少了?也许再增加一些。