我的远程 Postgres 查询似乎永远挂起
Posted
技术标签:
【中文标题】我的远程 Postgres 查询似乎永远挂起【英文标题】:My remote Postgres query seems to hang forever 【发布时间】:2018-10-12 02:55:56 【问题描述】:我正在从本地客户端对远程 Postgres 实例运行以下查询:
select * from matches_tb1 order by match_id desc limit 10;
matches_tb1
是一个外部表,并以 match_id
作为唯一索引。查询似乎永远挂起。当我使用explain verbose
时,没有ORDER BY
附加到“远程SQL”。我猜本地服务器没有将订单下推到远程服务器。我该如何解决这个问题?
附上解释结果:
explain verbose select match_id from matches_tb1 order by match_id desc limit 10;
QUERY PLAN
---------------------------------------------------------------------------------------------------
Limit (cost=33972852.96..33972852.98 rows=10 width=8)
Output: match_id
-> Sort (cost=33972852.96..35261659.79 rows=515522734 width=8)
Output: match_id
Sort Key: matches_tb1.match_id DESC
-> Foreign Scan on public.matches_tb1 (cost=100.00..22832592.02 rows=515522734 width=8)
Output: match_id
Remote SQL: SELECT match_id FROM public.matches_tb1
(8 rows)
【问题讨论】:
请在您的问题中发布完整的EXPLAIN
查询计划。
附加解释详细结果
计划中提到match_id
被用作排序键,所以我看不出有什么意外。您是否可以尝试其他任何查询,以便我们查看其他情况下是否存在此延迟问题?
sql_1 = select match_id from matches_tb1 where match_id > 4164287140 order by match_id desc limit 10; sql_2 = 从matches_tb1 中选择match_id,其中match_id > 416428 order by match_id desc limit 10;我可以很快得到 sql_1 的结果,但是 sql_2 永远挂起。如果这些 sqls 直接在远程服务器上执行(而不是通过 postgres_FDW),则两者都可以在一秒钟内结束。
我收回我上面说的话。 match_id
索引似乎没有被使用。结果,Postgres 是手动对整个 5 亿条记录表进行排序,只为找到前 10 条记录。所以,我们需要想办法让索引生效。你确定match_id
上面有一个B树索引吗?
【参考方案1】:
对于您问题中的第一个查询:
select * from matches_tb1 order by match_id desc limit 10;
根据EXPLAIN
计划,Postgres 似乎没有使用match_id
B-tree 索引。这导致查询很长,因为数据库必须扫描整个 5 亿条记录表并排序,才能找到 10 条记录。至于为什么 Postgres 不能使用索引,问题是select *
。当数据库到达索引中每个条目的叶子节点时,它只会找到match_id
的值。但是,由于您正在执行select *
,因此数据库必须查找聚集索引以查找所有其他列的值。如果您的表的相关性较低,那么优化器可能会选择完全放弃索引而只对表进行全盘扫描。
相比之下,请考虑您的其他一个执行速度很快的查询:
select match_id from matches_tb1 where match_id > 4164287140
order by match_id desc limit 10
在这种情况下,可以使用match_id
上的索引,因为您只选择了match_id
。此外,where
子句中的限制更有助于使索引更加具体。
因此,如果您希望查询快速完成,则此处解决您的问题的方法是不要将 select *
与 limit
一起使用。例如,如果您只想从表中说出两列 col1
和 col2
,那么您可以将这些列添加到索引中以覆盖它们。那么,下面的查询也应该很快:
select match_id, col1, col2 from matches_tb1 order by match_id desc limit 10;
【讨论】:
首先感谢您的回复。外部表有 5 亿行。当我直接连接到远程服务器时,我可以在几秒钟内得到结果。但是当我使用 FDW 时,我无法获得结果(永远挂起)。所以我假设 order by 没有推送到远程服务器。 实际上,您看到的延迟似乎表明 正在为LIMIT
子句进行排序步骤。
对不起,我没明白你的意思。我假设我的查询永远挂起,因为本地服务器尝试从外部表中获取所有数据(5 亿)并在本地进行排序。如果 order by 在远程服务器上完成,那么我也应该在一秒钟内看到结果。
如果你在远程运行查询,那么整个事情应该在远程运行。如果您建议 Postgres 通过网络返回 5 亿条记录,然后您在本地执行 ORDER BY
,我完全不会想到会这样。
要点是我不想在本地执行 ORDER BY,我希望在远程服务器上执行 ORDER BY,但据我所见 ORDRE BY 并没有在远程服务器上执行。如果确实如此,为什么我的查询会永远挂起?以上是关于我的远程 Postgres 查询似乎永远挂起的主要内容,如果未能解决你的问题,请参考以下文章