Postgres FDW Remote only JOIN 导致获取所有数据
Postgres FDW Remote only JOIN causes fetch all data
我正在尝试使用仅涉及远程表的 JOIN 子句从远程服务器获取数据,但它非常慢,因为计划者决定从两个表中获取所有数据并在本地合并。
当我添加 WHERE 子句时,它解决了问题并且 JOIN 在远程服务器上完全执行。
问题在小例子上是可重现的:
-- remote server
create table test
(
id serial
constraint test_pk
primary key,
name text
);
create table test2
(
test_id int
constraint test2_test_id_fk
references test (id),
info text
);
SELECT 查询:
SELECT "test".id FROM "test" JOIN "test2" ON "test"."id"="test2".test_id;
EXPLAIN VERBOSE 的输出(在空表上!):
Merge Join (cost=732.29..1388.59 rows=42778 width=4)
Output: test.id
Merge Cond: (test.id = test2.test_id)
-> Sort (cost=366.15..373.46 rows=2925 width=4)
Output: test.id
Sort Key: test.id
-> Foreign Scan on public.test (cost=100.00..197.75 rows=2925 width=4)
Output: test.id
Remote SQL: SELECT id FROM public.test
-> Sort (cost=366.15..373.46 rows=2925 width=4)
Output: test2.test_id
Sort Key: test2.test_id
-> Foreign Scan on public.test2 (cost=100.00..197.75 rows=2925 width=4)
Output: test2.test_id
Remote SQL: SELECT test_id FROM public.test2
添加后WHERE test.id=1
Foreign Scan (cost=100.00..198.75 rows=225 width=4)
Output: test.id
Relations: (public.test) INNER JOIN (public.test2)
Remote SQL: SELECT r1.id FROM (public.test r1 INNER JOIN public.test2 r2 ON (((r2.test_id = 1)) AND ((r1.id = 1))))
我在两边都使用 AWS RDS Postgres v10.18。
这是怎么回事?如何强制在远程服务器上执行?
我没有找到任何与该问题相关的内容。
感谢您的帮助。
PostgreSQL 估计连接结果将包含 42778 行,因此它认为在本地连接表比传输大结果集更有效。
如果那个估计不正确,ANALYZE
两个外部表都得到准确的统计数据,然后再试一次。请记住,不会自动分析外部表。
一般来说,在询问性能问题时,总是包含 EXPLAIN (ANALYZE, BUFFERS)
输出。
PostgreSQL 不知道它会在这些表中找到多少数据,它完全武断的猜测不是很好。
你可以这样做来帮助它:
alter server fdw options (add use_remote_estimate 'on');
规划将花费更长的时间,因为它需要多次往返于外部服务器来进行规划,但 IME 通常是值得的。
您可以改为在本地端分析外部表,以便它在本地存储统计信息。计划时间不应像 use_remote_estimate 那样受到影响。您需要偶尔重复,因为它们不会自动重新计算。我在这方面的经验很差,但那是几个版本前的版本,所以它可能有所改进。
任何一个都可以帮我修好你的复制器案例
我正在尝试使用仅涉及远程表的 JOIN 子句从远程服务器获取数据,但它非常慢,因为计划者决定从两个表中获取所有数据并在本地合并。 当我添加 WHERE 子句时,它解决了问题并且 JOIN 在远程服务器上完全执行。
问题在小例子上是可重现的:
-- remote server
create table test
(
id serial
constraint test_pk
primary key,
name text
);
create table test2
(
test_id int
constraint test2_test_id_fk
references test (id),
info text
);
SELECT 查询:
SELECT "test".id FROM "test" JOIN "test2" ON "test"."id"="test2".test_id;
EXPLAIN VERBOSE 的输出(在空表上!):
Merge Join (cost=732.29..1388.59 rows=42778 width=4)
Output: test.id
Merge Cond: (test.id = test2.test_id)
-> Sort (cost=366.15..373.46 rows=2925 width=4)
Output: test.id
Sort Key: test.id
-> Foreign Scan on public.test (cost=100.00..197.75 rows=2925 width=4)
Output: test.id
Remote SQL: SELECT id FROM public.test
-> Sort (cost=366.15..373.46 rows=2925 width=4)
Output: test2.test_id
Sort Key: test2.test_id
-> Foreign Scan on public.test2 (cost=100.00..197.75 rows=2925 width=4)
Output: test2.test_id
Remote SQL: SELECT test_id FROM public.test2
添加后WHERE test.id=1
Foreign Scan (cost=100.00..198.75 rows=225 width=4)
Output: test.id
Relations: (public.test) INNER JOIN (public.test2)
Remote SQL: SELECT r1.id FROM (public.test r1 INNER JOIN public.test2 r2 ON (((r2.test_id = 1)) AND ((r1.id = 1))))
我在两边都使用 AWS RDS Postgres v10.18。
这是怎么回事?如何强制在远程服务器上执行? 我没有找到任何与该问题相关的内容。
感谢您的帮助。
PostgreSQL 估计连接结果将包含 42778 行,因此它认为在本地连接表比传输大结果集更有效。
如果那个估计不正确,ANALYZE
两个外部表都得到准确的统计数据,然后再试一次。请记住,不会自动分析外部表。
一般来说,在询问性能问题时,总是包含 EXPLAIN (ANALYZE, BUFFERS)
输出。
PostgreSQL 不知道它会在这些表中找到多少数据,它完全武断的猜测不是很好。
你可以这样做来帮助它:
alter server fdw options (add use_remote_estimate 'on');
规划将花费更长的时间,因为它需要多次往返于外部服务器来进行规划,但 IME 通常是值得的。
您可以改为在本地端分析外部表,以便它在本地存储统计信息。计划时间不应像 use_remote_estimate 那样受到影响。您需要偶尔重复,因为它们不会自动重新计算。我在这方面的经验很差,但那是几个版本前的版本,所以它可能有所改进。
任何一个都可以帮我修好你的复制器案例