Re: [HACKERS] Add support for tuple routing to foreign partitions - Mailing list pgsql-hackers
From | Etsuro Fujita |
---|---|
Subject | Re: [HACKERS] Add support for tuple routing to foreign partitions |
Date | |
Msg-id | 5A8EAE4F.4040701@lab.ntt.co.jp Whole thread Raw |
In response to | Re: [HACKERS] Add support for tuple routing to foreign partitions (Amit Langote <Langote_Amit_f8@lab.ntt.co.jp>) |
Responses |
Re: [HACKERS] Add support for tuple routing to foreign partitions
|
List | pgsql-hackers |
(2018/02/22 11:52), Amit Langote wrote: > On 2018/02/21 20:54, Etsuro Fujita wrote: >> void >> BeginForeignRouting(ModifyTableState *mtstate, >> ResultRelInfo *resultRelInfo, >> int partition_index); >> >> Prepare for a tuple-routing operation on a foreign table. This is called >> from ExecSetupPartitionTupleRouting and ExecInitPartitionInfo. > > I wonder why partition_index needs to be made part of this API? The reason for that is because I think the FDW might want to look at the partition info stored in mtstate->mt_partition_tuple_routing for some reason or other, such as parent_child_tupconv_maps and child_parent_tupconv_maps, which are accessed with the given partition index. >> Patch foreign-routing-fdwapi-WIP.patch: main patch to add new FDW APIs, >> which is created on top of patch postgres-fdw-refactoring-WIP.patch and >> the lazy-initialization-of-partition-info patch [1]. > > Noticed a typo in the patch (s/parition/partition/g): > > + * Also let the FDW init itself if this parition is foreign. > > + * Also let the FDW init itself if this parition is foreign. Good catch! Will fix. > Perhaps an independent concern, but one thing I noticed is that it does > not seem to play well with the direct modification (update push-down) > feature. Now because updates (at least local, let's say) support > re-routing, I thought we'd be able move rows across servers via the local > server, but with direct modification we'd never get the chance. However, > since update tuple routing is triggered by partition constraint failure, > which we don't enforce for foreign tables/partitions anyway, I'm not sure > if we need to do anything about that, and even if we did, whether it > concerns this proposal. Good point! Actually, update tuple routing we have in HEAD doesn't allow re-routing tuples from foreign partitions even without direct modification. Here is an example using postgres_fdw: postgres=# create table pt (a int, b text) partition by list (a); CREATE TABLE postgres=# create table loct (a int check (a in (1)), b text); CREATE TABLE postgres=# create foreign table remp partition of pt for values in (1) server loopback options (table_name 'loct'); CREATE FOREIGN TABLE postgres=# create table locp partition of pt for values in (2); CREATE TABLE postgres=# insert into remp values (1, 'foo'); INSERT 0 1 postgres=# insert into locp values (2, 'bar'); INSERT 0 1 postgres=# select tableoid::regclass, * from pt; tableoid | a | b ----------+---+----- remp | 1 | foo locp | 2 | bar (2 rows) postgres=# create function postgres_fdw_abs(int) returns int as $$begin return abs($1); end$$ language plpgsql immutable; CREATE FUNCTION postgres=# explain verbose update pt set a = postgres_fdw_abs(a) + 1 where b = 'foo'; QUERY PLAN -------------------------------------------------------------------------------- ------------- Update on public.pt (cost=100.00..154.54 rows=12 width=42) Foreign Update on public.remp Remote SQL: UPDATE public.loct SET a = $2 WHERE ctid = $1 Update on public.locp -> Foreign Scan on public.remp (cost=100.00..127.15 rows=6 width=42) Output: (postgres_fdw_abs(remp.a) + 1), remp.b, remp.ctid Remote SQL: SELECT a, b, ctid FROM public.loct WHERE ((b = 'foo'::text)) FOR UPDATE -> Seq Scan on public.locp (cost=0.00..27.39 rows=6 width=42) Output: (postgres_fdw_abs(locp.a) + 1), locp.b, locp.ctid Filter: (locp.b = 'foo'::text) (10 rows) postgres=# update pt set a = postgres_fdw_abs(a) + 1 where b = 'foo'; ERROR: new row for relation "loct" violates check constraint "loct_a_check" DETAIL: Failing row contains (2, foo). CONTEXT: Remote SQL command: UPDATE public.loct SET a = $2 WHERE ctid = $1 To be able to move tuples across foreign servers, I think we would first have to do something to allow re-routing tuples from foreign partitions. The patches I proposed hasn't done anything about that, so the patched version would behave the same way as HEAD with/without direct modification. > That said, I saw in the changes to ExecSetupPartitionTupleRouting() that > BeginForeignRouting() is called for a foreign partition even if direct > modification might already have been set up. If direct modification is > set up, then ExecForeignRouting() will never get called, because we'd > never call ExecUpdate() or ExecInsert(). Yeah, but I am thinking to leave the support for re-routing tuples across foreign servers for another patch. One difference between HEAD and the patched version would be: we can re-route tuples from a plain partition to a foreign partition if the foreign partition supports this tuple-routing API. Here is an example using the above data: postgres=# select tableoid::regclass, * from pt; tableoid | a | b ----------+---+----- remp | 1 | foo locp | 2 | bar (2 rows) postgres=# update pt set a = 1 where b = 'bar'; UPDATE 1 postgres=# select tableoid::regclass, * from pt; tableoid | a | b ----------+---+----- remp | 1 | foo remp | 1 | bar (2 rows) This would introduce an asymmetry (we can move tuples from plain partitions to foreign partitions, but the reverse is not true), but I am thinking that it would be probably okay to document about that. Thank you for the review! Best regards, Etsuro Fujita
pgsql-hackers by date: