mirror of
https://github.com/postgres/postgres.git
synced 2025-06-11 20:28:21 +03:00
postgres_fdw: Add ORDER BY to some remote SQL queries.
If the join problem's entire ORDER BY clause can be pushed to the remote server, consider a path that adds this ORDER BY clause. If use_remote_estimate is on, we cost this path using an additional remote EXPLAIN. If not, we just estimate that the path costs 20% more, which is intended to be large enough that we won't request a remote sort when it's not helpful, but small enough that we'll have the remote side do the sort when in doubt. In some cases, the remote sort might actually be free, because the remote query plan might happen to produce output that is ordered the way we need, but without remote estimates we have no way of knowing that. It might also be useful to request sorted output from the remote side if it enables an efficient merge join, but this patch doesn't attempt to handle that case. Ashutosh Bapat with revisions by me. Also reviewed by Fabrízio de Royes Mello and Jeevan Chalke.
This commit is contained in:
@ -134,15 +134,13 @@ ALTER FOREIGN TABLE ft2 OPTIONS (use_remote_estimate 'true');
|
||||
-- ===================================================================
|
||||
-- simple queries
|
||||
-- ===================================================================
|
||||
-- single table, with/without alias
|
||||
-- single table without alias
|
||||
EXPLAIN (COSTS false) SELECT * FROM ft1 ORDER BY c3, c1 OFFSET 100 LIMIT 10;
|
||||
QUERY PLAN
|
||||
---------------------------------
|
||||
QUERY PLAN
|
||||
---------------------------
|
||||
Limit
|
||||
-> Sort
|
||||
Sort Key: c3, c1
|
||||
-> Foreign Scan on ft1
|
||||
(4 rows)
|
||||
-> Foreign Scan on ft1
|
||||
(2 rows)
|
||||
|
||||
SELECT * FROM ft1 ORDER BY c3, c1 OFFSET 100 LIMIT 10;
|
||||
c1 | c2 | c3 | c4 | c5 | c6 | c7 | c8
|
||||
@ -159,20 +157,21 @@ SELECT * FROM ft1 ORDER BY c3, c1 OFFSET 100 LIMIT 10;
|
||||
110 | 0 | 00110 | Sun Jan 11 00:00:00 1970 PST | Sun Jan 11 00:00:00 1970 | 0 | 0 | foo
|
||||
(10 rows)
|
||||
|
||||
EXPLAIN (VERBOSE, COSTS false) SELECT * FROM ft1 t1 ORDER BY t1.c3, t1.c1 OFFSET 100 LIMIT 10;
|
||||
-- single table with alias - also test that tableoid sort is not pushed to remote side
|
||||
EXPLAIN (VERBOSE, COSTS false) SELECT * FROM ft1 t1 ORDER BY t1.c3, t1.c1, t1.tableoid OFFSET 100 LIMIT 10;
|
||||
QUERY PLAN
|
||||
-------------------------------------------------------------------------------------
|
||||
Limit
|
||||
Output: c1, c2, c3, c4, c5, c6, c7, c8
|
||||
Output: c1, c2, c3, c4, c5, c6, c7, c8, tableoid
|
||||
-> Sort
|
||||
Output: c1, c2, c3, c4, c5, c6, c7, c8
|
||||
Sort Key: t1.c3, t1.c1
|
||||
Output: c1, c2, c3, c4, c5, c6, c7, c8, tableoid
|
||||
Sort Key: t1.c3, t1.c1, t1.tableoid
|
||||
-> Foreign Scan on public.ft1 t1
|
||||
Output: c1, c2, c3, c4, c5, c6, c7, c8
|
||||
Output: c1, c2, c3, c4, c5, c6, c7, c8, tableoid
|
||||
Remote SQL: SELECT "C 1", c2, c3, c4, c5, c6, c7, c8 FROM "S 1"."T 1"
|
||||
(8 rows)
|
||||
|
||||
SELECT * FROM ft1 t1 ORDER BY t1.c3, t1.c1 OFFSET 100 LIMIT 10;
|
||||
SELECT * FROM ft1 t1 ORDER BY t1.c3, t1.c1, t1.tableoid OFFSET 100 LIMIT 10;
|
||||
c1 | c2 | c3 | c4 | c5 | c6 | c7 | c8
|
||||
-----+----+-------+------------------------------+--------------------------+----+------------+-----
|
||||
101 | 1 | 00101 | Fri Jan 02 00:00:00 1970 PST | Fri Jan 02 00:00:00 1970 | 1 | 1 | foo
|
||||
@ -189,17 +188,14 @@ SELECT * FROM ft1 t1 ORDER BY t1.c3, t1.c1 OFFSET 100 LIMIT 10;
|
||||
|
||||
-- whole-row reference
|
||||
EXPLAIN (VERBOSE, COSTS false) SELECT t1 FROM ft1 t1 ORDER BY t1.c3, t1.c1 OFFSET 100 LIMIT 10;
|
||||
QUERY PLAN
|
||||
-------------------------------------------------------------------------------------
|
||||
QUERY PLAN
|
||||
----------------------------------------------------------------------------------------------------------
|
||||
Limit
|
||||
Output: t1.*, c3, c1
|
||||
-> Sort
|
||||
-> Foreign Scan on public.ft1 t1
|
||||
Output: t1.*, c3, c1
|
||||
Sort Key: t1.c3, t1.c1
|
||||
-> Foreign Scan on public.ft1 t1
|
||||
Output: t1.*, c3, c1
|
||||
Remote SQL: SELECT "C 1", c2, c3, c4, c5, c6, c7, c8 FROM "S 1"."T 1"
|
||||
(8 rows)
|
||||
Remote SQL: SELECT "C 1", c2, c3, c4, c5, c6, c7, c8 FROM "S 1"."T 1" ORDER BY c3 ASC, "C 1" ASC
|
||||
(5 rows)
|
||||
|
||||
SELECT t1 FROM ft1 t1 ORDER BY t1.c3, t1.c1 OFFSET 100 LIMIT 10;
|
||||
t1
|
||||
@ -650,6 +646,32 @@ SELECT * FROM ft2 WHERE c1 = ANY (ARRAY(SELECT c1 FROM ft1 WHERE c1 < 5));
|
||||
4 | 4 | 00004 | Mon Jan 05 00:00:00 1970 PST | Mon Jan 05 00:00:00 1970 | 4 | 4 | foo
|
||||
(4 rows)
|
||||
|
||||
-- we should not push order by clause with volatile expressions or unsafe
|
||||
-- collations
|
||||
EXPLAIN (VERBOSE, COSTS false)
|
||||
SELECT * FROM ft2 ORDER BY ft2.c1, random();
|
||||
QUERY PLAN
|
||||
-------------------------------------------------------------------------------
|
||||
Sort
|
||||
Output: c1, c2, c3, c4, c5, c6, c7, c8, (random())
|
||||
Sort Key: ft2.c1, (random())
|
||||
-> Foreign Scan on public.ft2
|
||||
Output: c1, c2, c3, c4, c5, c6, c7, c8, random()
|
||||
Remote SQL: SELECT "C 1", c2, c3, c4, c5, c6, c7, c8 FROM "S 1"."T 1"
|
||||
(6 rows)
|
||||
|
||||
EXPLAIN (VERBOSE, COSTS false)
|
||||
SELECT * FROM ft2 ORDER BY ft2.c1, ft2.c3 collate "C";
|
||||
QUERY PLAN
|
||||
-------------------------------------------------------------------------------
|
||||
Sort
|
||||
Output: c1, c2, c3, c4, c5, c6, c7, c8, ((c3)::text)
|
||||
Sort Key: ft2.c1, ft2.c3 COLLATE "C"
|
||||
-> Foreign Scan on public.ft2
|
||||
Output: c1, c2, c3, c4, c5, c6, c7, c8, c3
|
||||
Remote SQL: SELECT "C 1", c2, c3, c4, c5, c6, c7, c8 FROM "S 1"."T 1"
|
||||
(6 rows)
|
||||
|
||||
-- ===================================================================
|
||||
-- parameterized queries
|
||||
-- ===================================================================
|
||||
|
Reference in New Issue
Block a user