Received: from malur.postgresql.org ([217.196.149.56]) by arkaria.postgresql.org with esmtps (TLS1.3:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.92) (envelope-from ) id 1o9RvI-00022X-BW for pgsql-hackers@arkaria.postgresql.org; Thu, 07 Jul 2022 13:52:05 +0000 Received: from localhost ([127.0.0.1] helo=malur.postgresql.org) by malur.postgresql.org with esmtp (Exim 4.92) (envelope-from ) id 1o9RvG-0000UI-6p for pgsql-hackers@arkaria.postgresql.org; Thu, 07 Jul 2022 13:52:02 +0000 Received: from magus.postgresql.org ([2a02:c0:301:0:ffff::29]) by malur.postgresql.org with esmtps (TLS1.3:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.92) (envelope-from ) id 1o9RvF-0000U9-Np for pgsql-hackers@lists.postgresql.org; Thu, 07 Jul 2022 13:52:01 +0000 Received: from mail.postgrespro.ru ([93.174.131.139]) by magus.postgresql.org with esmtp (Exim 4.92) (envelope-from ) id 1o9RvA-0007MS-Mo for pgsql-hackers@postgresql.org; Thu, 07 Jul 2022 13:52:01 +0000 Received: from [192.168.8.203] (unknown [93.174.131.141]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (Client did not present a certificate) by mail.postgrespro.ru (Postfix) with ESMTPSA id 8486821C04C5; Thu, 7 Jul 2022 16:51:54 +0300 (MSK) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=postgrespro.ru; s=mail; t=1657201914; bh=2saa497ieO4m/XBM4l3ruEj4CfbCIkuVr+5/3OqucqY=; h=Date:Subject:To:Cc:References:From:In-Reply-To; b=MKqTgguqkWp54yD3oOQSGXfNkbQ5F4ZGhm2G/3sM6Cov3x6EREJ+9GhmxVgzZ4gtd frlEV1ycuDvoi72sQpklFh0F6HhqNqhA/7a/LQecjxKX/x/bsDMY7BcCOGiBc8v0Ik EE1R6152M/p8mS79oN5KbvY2u8qRAABl4Pqen994= Message-ID: <811b36f0-8888-7036-f4c5-0bfbdfad0bbf@postgrespro.ru> Date: Thu, 7 Jul 2022 16:51:54 +0300 MIME-Version: 1.0 User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.15; rv:91.0) Gecko/20100101 Thunderbird/91.11.0 Subject: Re: Fast COPY FROM based on batch insert Content-Language: en-US To: Ian Barwick Cc: Justin Pryzby , Zhihong Yu , Amit Langote , tanghy.fnst@fujitsu.com, Ashutosh Bapat , Pg Hackers , Tomas Vondra , Etsuro Fujita , houzj.fnst@fujitsu.com References: <20210304203949.GQ29832@telsasoft.com> <20210323032322.GW4203@telsasoft.com> <20210409004956.GN6592@telsasoft.com> <45ad1b94-339b-a841-8885-67ebe6fc5bc1@postgrespro.ru> <065fde84-f688-c411-28eb-a3b9084b38b7@enterprisedb.com> From: Andrey Lepikhov Organization: Postgres Professional In-Reply-To: <065fde84-f688-c411-28eb-a3b9084b38b7@enterprisedb.com> Content-Type: text/plain; charset=UTF-8; format=flowed Content-Transfer-Encoding: 8bit List-Id: List-Help: List-Subscribe: List-Post: List-Owner: List-Archive: Archived-At: Precedence: bulk On 7/7/2022 06:14, Ian Barwick wrote: > 2022年3月24日(木) 15:44 Andrey V. Lepikhov : > > > > On 3/22/22 06:54, Etsuro Fujita wrote: > > > On Fri, Jun 4, 2021 at 5:26 PM Andrey Lepikhov > > > wrote: > > >> We still have slow 'COPY FROM' operation for foreign tables in > current > > >> master. > > >> Now we have a foreign batch insert operation And I tried to > rewrite the > > >> patch [1] with this machinery. > > > > > > The patch has been rewritten to something essentially different, but > > > no one reviewed it.  (Tsunakawa-san gave some comments without looking > > > at it, though.)  So the right status of the patch is “Needs review”, > > > rather than “Ready for Committer”?  Anyway, here are a few review > > > comments from me: > > > > > > * I don’t think this assumption is correct: > > > > > > @@ -359,6 +386,12 @@ CopyMultiInsertBufferFlush(CopyMultiInsertInfo > *miinfo, > > > > (resultRelInfo->ri_TrigDesc->trig_insert_after_row || > > >                    resultRelInfo->ri_TrigDesc->trig_insert_new_table)) > > >          { > > > +           /* > > > +            * AFTER ROW triggers aren't allowed with the foreign > bulk insert > > > +            * method. > > > +            */ > > > +           Assert(resultRelInfo->ri_RelationDesc->rd_rel->relkind != > > > RELKIND_FOREIGN_TABLE); > > > + > > > > > > In postgres_fdw we disable foreign batch insert when the target table > > > has AFTER ROW triggers, but the core allows it even in that case.  No? > > Agree > > > > > * To allow foreign multi insert, the patch made an invasive change to > > > the existing logic to determine whether to use multi insert for the > > > target relation, adding a new member ri_usesMultiInsert to the > > > ResultRelInfo struct, as well as introducing a new function > > > ExecMultiInsertAllowed().  But I’m not sure we really need such a > > > change.  Isn’t it reasonable to *adjust* the existing logic to allow > > > foreign multi insert when possible? > > Of course, such approach would look much better, if we implemented it. > > I'll ponder how to do it. > > > > > I didn’t finish my review, but I’ll mark this as “Waiting on Author”. > > I rebased the patch onto current master. Now it works correctly. I'll > > mark it as "Waiting for review". > > I took a look at this patch as it would a useful optimization to have. > > It applies cleanly to current HEAD, but as-is, with a large data set, it > reproducibly fails like this (using postgres_fdw): > >     postgres=# COPY foo FROM '/tmp/fast-copy-from/test.csv' WITH > (format csv); >     ERROR:  bind message supplies 0 parameters, but prepared statement > "pgsql_fdw_prep_19422" requires 6 >     CONTEXT:  remote SQL command: INSERT INTO public.foo_part_1(t, v1, > v2, v3, v4, v5) VALUES ($1, $2, $3, $4, $5, $6) >     COPY foo, line 17281589 > > This occurs because not all multi-insert buffers being flushed actually > contain > tuples; the fix is simply not to call ExecForeignBatchInsert() if that's > the case, > e.g: > > >         /* Flush into foreign table or partition */ >         do { >             int size = (resultRelInfo->ri_BatchSize < nused - sent) ? >                         resultRelInfo->ri_BatchSize : (nused - sent); > >             if (size) >             { >                 int inserted = size; > > > resultRelInfo->ri_FdwRoutine->ExecForeignBatchInsert(estate, > > resultRelInfo, > > &slots[sent], >                                                                      NULL, > > &inserted); >                 sent += size; >             } >         } while (sent < nused); > > > There might a case for arguing that the respective FDW should check that > it has > actually received some tuples to insert, but IMHO it's much preferable > to catch > this as early as possible and avoid a superfluous call. > > FWIW, with the above fix in place, with a simple local test the patch > produces a > consistent speed-up of about 8 times compared to the existing > functionality. Thank you for the attention to the patch. I have a couple of questions: 1. It's a problem for me to reproduce the case you reported. Can you give more details on the reproduction? 2. Have you tried to use previous version, based on bulk COPY machinery, not bulk INSERT? Which approach looks better and have better performance in your opinion? -- regards, Andrey Lepikhov Postgres Professional