Received: from malur.postgresql.org ([217.196.149.56]) by arkaria.postgresql.org with esmtps (TLS1.3) tls TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 (Exim 4.94.2) (envelope-from ) id 1uggnA-006Kxd-KQ for pgsql-hackers@arkaria.postgresql.org; Tue, 29 Jul 2025 09:38:41 +0000 Received: from localhost ([127.0.0.1] helo=malur.postgresql.org) by malur.postgresql.org with esmtp (Exim 4.94.2) (envelope-from ) id 1uggn8-00H2lW-NK for pgsql-hackers@arkaria.postgresql.org; Tue, 29 Jul 2025 09:38:39 +0000 Received: from magus.postgresql.org ([2a02:c0:301:0:ffff::29]) by malur.postgresql.org with esmtps (TLS1.3) tls TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 (Exim 4.94.2) (envelope-from ) id 1uggn8-00H2lM-C8 for pgsql-hackers@lists.postgresql.org; Tue, 29 Jul 2025 09:38:38 +0000 Received: from mail-il1-x133.google.com ([2607:f8b0:4864:20::133]) by magus.postgresql.org with esmtps (TLS1.3) tls TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 (Exim 4.96) (envelope-from ) id 1uggn5-001SVi-19 for pgsql-hackers@lists.postgresql.org; Tue, 29 Jul 2025 09:38:38 +0000 Received: by mail-il1-x133.google.com with SMTP id e9e14a558f8ab-3e3e4419362so5936605ab.3 for ; Tue, 29 Jul 2025 02:38:36 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1753781915; x=1754386715; darn=lists.postgresql.org; h=cc:to:subject:message-id:date:from:in-reply-to:references :mime-version:from:to:cc:subject:date:message-id:reply-to; bh=M9qbrkRx4gtWY80YbCqqYdlJBH5we18oLfi60VyoXfg=; b=KbJIFpmyCp/AWvur9RyaeOUMUxFEnGklQY0WkG3+ALr9VeTf8ug1d9ZgTXShPUKJqa r1u6n2lUQnyZtH+uoOyY1y2LpFwXwELClxFWHVQ4M0WgmC+jwq3GmyvPFdgZ9WhGXWH6 e/ZP9BYsdptcjuTl06zyX4B9fm/jmJNTAmyzeYH3a3acqNpN3ffsEXdcT/Of2VgraP12 Bro/2CBVwX7amORHmK0NJltuwjvtF+njSVGu+B0hPGn/v8Evwst63DY5fkrKOZAyKse+ UpNfqQD47oXjO9MYybJkBbzrjVIBD+Q6bZyRKnV/Gv+MTdakJMfgCTllgdDMICawavy0 TgTw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1753781915; x=1754386715; h=cc:to:subject:message-id:date:from:in-reply-to:references :mime-version:x-gm-message-state:from:to:cc:subject:date:message-id :reply-to; bh=M9qbrkRx4gtWY80YbCqqYdlJBH5we18oLfi60VyoXfg=; b=ZzZu5fVnfay3bZzFziKFQvgDi6iGTt0RTPAPCNqCZ96gbrh3v3Jk34Lq6Hv+3p7IEU b2dLyS0Z8/Tr/ktFjiFb53WwuMMYUE/9HahHiDBeylt4hd7d3PYy6nbEMclpgAHWONj3 j5Do1XzgF3JKMON97O/pvGT5vbYI+QOvUTQ3bbgMEYCAONWv1lz+WomzqS7Hx6orQkGu o2Go7PjEZI0hVRojrt1tsWzifxkO7HNFX8o7sAK3ijerwZ1dlST+Pr6FjqjskY4lYtVp mv9hmmPfN9OQtBoHuLuKcOsfGDC+bjNPP+UsVA9gLwMn7jTS2+9IAE3IDkuvI99TqjpA LyeA== X-Forwarded-Encrypted: i=1; AJvYcCXxqSBuFlJ9mbCQzXmfdRqlwtoRtQ9PS3NsdpZkK5jbVeiCZ8obUnja/4RdU7+hBCjs5fPFHSqdyfP59p/S@lists.postgresql.org X-Gm-Message-State: AOJu0YzGT0JdRAFKpPooR6WUkuZz5zVDc0i6T+jNSr5XGh42rrvU5lo6 2ObL3T/HIU/WKSy4/44Pb9yXaZXPnpf7cGXQ9V0iYK4onoPx4WVlwaWdSrhfgRd3+GbuTLSpwv8 usuyKyZrHErSuylz4SdruT4An8ertyQc= X-Gm-Gg: ASbGncsEqYWEXyrhwq4/2LvprQNM9QFGFZAkGrmdfOr7Lgke6baMF+2ggh6BpvNOj4C 02Ru/1SgWIRZUDfDAlwcSvRJVXm6H9mXQ74FWyTut/TT7Hoyu9PQlegoO0eF9vLNButNfIaL6wG azdVEhOIRDd/2XAQ8ZlFpuLy3/QekQRvRhuq+OcSLIE5sFDJsrSx5xFDPwWa/H2kPSsLrmh7bGL vMgeJ4= X-Google-Smtp-Source: AGHT+IFeelxKHvp0TSmYsN8Y2JQXH6Wm9uYF6M0ks5TFpvCahFVtzuR8jwD2XMCaDlfLKgYdUIpv9gAuLOZf7xuDXio= X-Received: by 2002:a05:6e02:164b:b0:3e3:ceab:9001 with SMTP id e9e14a558f8ab-3e3ceab90ffmr222966955ab.21.1753781914486; Tue, 29 Jul 2025 02:38:34 -0700 (PDT) MIME-Version: 1.0 References: <171085360143.2046436.7217841141682511557.pgcf@coridan.postgresql.org> <7e1c67b8-ceba-4a04-964a-853eedeb02cc@postgrespro.ru> <0b3907b4-83b9-4873-9feb-2b60b29cda33@postgrespro.ru> <4f19550b-eb41-4649-8bf5-566dc020a720@postgrespro.ru> <195b67ee-ef41-4451-9396-844442eef1a4@postgrespro.ru> In-Reply-To: From: Alexander Korotkov Date: Tue, 29 Jul 2025 12:38:22 +0300 X-Gm-Features: Ac12FXxuA07X9ySWriiQ75IamJ59U32hL6I_fqOTNncvlFIHGCgK7nQ0axAJ8iA Message-ID: Subject: Re: Add SPLIT PARTITION/MERGE PARTITIONS commands To: Dmitry Koval Cc: jian he , pgsql-hackers@lists.postgresql.org Content-Type: multipart/alternative; boundary="00000000000006c970063b0e2ced" List-Id: List-Help: List-Subscribe: List-Post: List-Owner: List-Archive: Archived-At: Precedence: bulk --00000000000006c970063b0e2ced Content-Type: text/plain; charset="UTF-8" Hi, Dmitry! I went through the patches. Both of them applied with a small conflict in the parallel_schedule, which is easy to resolve. + ExecClearTuple(insertslot); + + memcpy(insertslot->tts_values, srcslot->tts_values, + sizeof(Datum) * srcslot->tts_nvalid); + memcpy(insertslot->tts_isnull, srcslot->tts_isnull, + sizeof(bool) * srcslot->tts_nvalid); + + ExecStoreVirtualTuple(insertslot); Similar fragments are present in SplitPartitionMoveRows() and MergePartitionsMoveRows(). Do you think we could use ExecCopySlot() (or similar) instead? The presence of the same name in the split partition list is checked with equal() (similar concern was already raised about the merge case [1]). If one of the names is schema-qualified, the error message is different. Could we make them the same? # alter table part_test split partition part_test_1_2 into (partition part_test_1 for values in (1), partition part_test_1 for values in (2)); ERROR: name "part_test_1" is already used LINE 1: ...artition part_test_1 for values in (1), partition part_test_... ^ Time: 1.194 ms # alter table part_test split partition part_test_1_2 into (partition part_test_1 for values in (1), partition public.part_test_1 for values in (2)); ERROR: relation "part_test_1" already exists Time: 6.187 ms + /* Search partition for current slot srcslot. */ + foreach(listptr, partContexts) + { + pc = (SplitPartitionContext *) lfirst(listptr); + + /* skip DEFAULT partition */ + if (pc->partqualstate && ExecCheck(pc->partqualstate, econtext)) + { + found = true; + break; + } + } I see we're searching for a partition to place each row using the sequential application of partition constraints. I concerned if this could be exhausting when the number of new partitions is large. Could we use something like binary search here? New split/drop commands do the full reorganization of the involved partitions. As Robert previously stated [2], there are other possible strategies. While they are hard to implement, I don't think we need them in the initial version. But I think it's worth mentioning in the docs that we're completely rewriting the involved partitions. And this is not recommended to use for merging very big partitions with small ones, and splitting a small fraction of rows out of a very big partition. Both patches could use pgindent run. Links 1. https://www.postgresql.org/message-id/CACJufxHHnJm6Jb2YQpuRU1RX__tO%3DJJNJ5%3DEUMuzif_KNxGd9A%40mail.gmail.com 2. https://www.postgresql.org/message-id/CA%2BTgmoY0%3DbT_xBP8csR%3DMFE%3DFxGE2n2-me2-31jBOgEcLvW7ug%40mail.gmail.com ------ Regards, Alexander Korotkov Supabase --00000000000006c970063b0e2ced Content-Type: text/html; charset="UTF-8" Content-Transfer-Encoding: quoted-printable
Hi, Dmitry!

I went through the patches. Both of the= m applied with a small conflict in the parallel_schedule, which is easy to = resolve.

+ =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 ExecClearTuple(insertslot);
+
+ =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 memcpy(insertslot->tts_values, srcslot-&= gt;tts_values,
+ =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0= =C2=A0 =C2=A0 =C2=A0sizeof(Datum) * srcslot->tts_nvalid);
+ =C2=A0 = =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 memcpy(insertslot->tts_isnull,= srcslot->tts_isnull,
+ =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0sizeof(bool) * srcslot->tts_nvalid);
+=
+ =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 ExecStoreVirtualTupl= e(insertslot);

Similar fragments are present in SplitPartitio= nMoveRows() and=C2=A0MergePartitionsMoveRows().=C2=A0 Do you think we could= use=C2=A0ExecCopySlot() (or similar) instead?

The prese= nce of the same name in the split partition list is checked with equal() (s= imilar concern was already raised about the merge case [1]).=C2=A0 If one o= f the names is schema-qualified, the error message is different.=C2=A0 Coul= d we make them the same?=C2=A0=C2=A0

# alter table= part_test split partition part_test_1_2 into (partition part_test_1 for va= lues in (1), partition part_test_1 for values in (2));
ERROR: =C2=A0name= "part_test_1" is already used
LINE 1: ...artition part_test_1= for values in (1), partition part_test_...
=C2=A0 =C2=A0 =C2=A0 =C2=A0 = =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 = =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0^
Time: 1.194 ms
# alter tab= le part_test split partition part_test_1_2 into (partition part_test_1 for = values in (1), partition public.part_test_1 for values in (2));
ERROR: = =C2=A0relation "part_test_1" already exists
Time: 6.187 ms
=
+ =C2=A0 =C2=A0 =C2=A0 /* Search partition for= current slot srcslot. */
+ =C2=A0 =C2=A0 =C2=A0 foreach(listptr, partCo= ntexts)
+ =C2=A0 =C2=A0 =C2=A0 {
+ =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0= pc =3D (SplitPartitionContext *) lfirst(listptr);
+
+ =C2=A0 =C2=A0 = =C2=A0 =C2=A0 =C2=A0 /* skip DEFAULT partition */
+ =C2=A0 =C2=A0 =C2=A0= =C2=A0 =C2=A0 if (pc->partqualstate && ExecCheck(pc->partqua= lstate, econtext))
+ =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 {
+ =C2=A0 = =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 found =3D true;
+ =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 break;
+ =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 }
+ =C2=A0 =C2=A0 =C2=A0 }

I see we're sear= ching for a partition to place each row using the sequential application=C2= =A0of partition constraints.=C2=A0 I concerned if this could be exhausting = when the number of new partitions is large.=C2=A0 Could we use something li= ke binary search here?

New split/drop commands do = the full reorganization of the involved partitions.=C2=A0 As Robert previou= sly stated [2], there are other possible strategies.=C2=A0 While they are h= ard to implement, I don't think we need them in the initial version.=C2= =A0 But I think it's worth mentioning=C2=A0in the docs that we're c= ompletely rewriting the involved partitions.=C2=A0 And this is not recommen= ded to use for merging very big partitions with small ones, and splitting a= small fraction of rows out of a=C2=A0very big partition.
--00000000000006c970063b0e2ced--