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 1u6tIo-007AE7-Le for pgsql-general@arkaria.postgresql.org; Mon, 21 Apr 2025 15:43:23 +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 1u6tIm-006Rmg-H2 for pgsql-general@arkaria.postgresql.org; Mon, 21 Apr 2025 15:43:21 +0000 Received: from makus.postgresql.org ([2001:4800:3e1:1::229]) by malur.postgresql.org with esmtps (TLS1.3) tls TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 (Exim 4.94.2) (envelope-from ) id 1u6tIl-006RmL-4V for pgsql-general@lists.postgresql.org; Mon, 21 Apr 2025 15:43:20 +0000 Received: from fhigh-a3-smtp.messagingengine.com ([103.168.172.154]) by makus.postgresql.org with esmtps (TLS1.3) tls TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 (Exim 4.96) (envelope-from ) id 1u6tIg-001CY5-09 for pgsql-general@lists.postgresql.org; Mon, 21 Apr 2025 15:43:18 +0000 Received: from phl-compute-02.internal (phl-compute-02.phl.internal [10.202.2.42]) by mailfhigh.phl.internal (Postfix) with ESMTP id B4A561140264 for ; Mon, 21 Apr 2025 11:43:12 -0400 (EDT) Received: from phl-mailfrontend-01 ([10.202.2.162]) by phl-compute-02.internal (MEProxy); Mon, 21 Apr 2025 11:43:12 -0400 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=aklaver.com; h= cc:content-transfer-encoding:content-type:content-type:date:date :from:from:in-reply-to:in-reply-to:message-id:mime-version :references:reply-to:subject:subject:to:to; s=fm1; t=1745250192; x=1745336592; bh=DR4Sf9liW8Hp/ZklALRKIaPmLD/7GH1+QBm5mBgeKCI=; b= cHkLb9fs5qPSAtIlsePMCmqkdL12bd6bCi4nEGTu6hp8ij49LxTtgt5G0Lyi1Wzv JyLkwSGCXp0urbpB2IASrOD3gsZv7yI/AAYxyP7oIelN+rl/u6bmnV+KiTjNtf6U 5Fp3uz23LnFl5F3q+YcxkqK3m+FacZ/q2KwxrENHUtt/oKSrVgi6OQE5u7Y+IBtB VEUX0sL7mGPjawnr6E/m6+KOGblk9akiIj1HyWL0IP28n6DSR1kylNbIWrpcoJy7 lOwP29xRR1p6XfzCWaakixF8+2HAmWvC1Cj9kwslpq/mKQrmS5Ziqh1tZ+Z36Z/x FpvxWt8NKLNEut2zzBGgIA== DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d= messagingengine.com; h=cc:content-transfer-encoding:content-type :content-type:date:date:feedback-id:feedback-id:from:from :in-reply-to:in-reply-to:message-id:mime-version:references :reply-to:subject:subject:to:to:x-me-proxy:x-me-sender :x-me-sender:x-sasl-enc; s=fm2; t=1745250192; x=1745336592; bh=D R4Sf9liW8Hp/ZklALRKIaPmLD/7GH1+QBm5mBgeKCI=; b=qO/lcPZYCfgeS7p8n HqjhcJSYsc6Yjm0JajVoC9gtepqxgKBMpzbYSPccNUlfxHfvvptIJv9WwluWwHjJ L1g1hW+MV3mBAEZIKLQL7uNcoWVJWzOEbREGItkSDtN1aP5GozxMSoob5B6Kt2XK 3SYEZFRaZ0kIxibrIRQWxbQAiLbiBAxh/vyTwcWKFzfaoj+AV/N2enaLXZeKLzZ4 yq+fMJm6XtTJXODfePRMTOMjlx842sF+JaXWWTvYntVmBvATMujA+75xKpkmi/8o B2c4CsFN9mxT8WUx4cm7N/+XGstKI7AuADHOIqR/QPvaAvFVoFqo0GJH+qibtq5c jgdZA== X-ME-Sender: X-ME-Received: X-ME-Proxy-Cause: gggruggvucftvghtrhhoucdtuddrgeefvddrtddtgddvgeduvdegucetufdoteggodetrf dotffvucfrrhhofhhilhgvmecuhfgrshhtofgrihhlpdggtfgfnhhsuhgsshgtrhhisggv pdfurfetoffkrfgpnffqhgenuceurghilhhouhhtmecufedttdenucenucfjughrpefkff ggfgfuvfhfhfgjtgfgsehtkeertddtvdejnecuhfhrohhmpeetughrihgrnhcumfhlrghv vghruceorggurhhirghnrdhklhgrvhgvrhesrghklhgrvhgvrhdrtghomheqnecuggftrf grthhtvghrnhepleegveekkeekueeigfdtveeileeuhfefudefteekjeffkeejueejheeg heegkedtnecuffhomhgrihhnpehpohhsthhgrhgvshhqlhdrohhrghenucevlhhushhtvg hrufhiiigvpedtnecurfgrrhgrmhepmhgrihhlfhhrohhmpegrughrihgrnhdrkhhlrghv vghrsegrkhhlrghvvghrrdgtohhmpdhnsggprhgtphhtthhopedupdhmohguvgepshhmth hpohhuthdprhgtphhtthhopehpghhsqhhlqdhgvghnvghrrghlsehlihhsthhsrdhpohhs thhgrhgvshhqlhdrohhrgh X-ME-Proxy: Feedback-ID: i76984098:Fastmail Received: by mail.messagingengine.com (Postfix) with ESMTPA for ; Mon, 21 Apr 2025 11:43:12 -0400 (EDT) Message-ID: Date: Mon, 21 Apr 2025 08:43:11 -0700 MIME-Version: 1.0 User-Agent: Mozilla Thunderbird Subject: Re: Order of update To: pgsql-general@lists.postgresql.org References: <20250420091033.n437fdrkihtjrncd@hjp.at> <20250421084717.4edbhu6a7duiqw42@hjp.at> Content-Language: en-US From: Adrian Klaver In-Reply-To: <20250421084717.4edbhu6a7duiqw42@hjp.at> 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 4/21/25 01:47, Peter J. Holzer wrote: > > If the hash was the other way around it wouldn't work. > > So let's try if we can get the optimizer to flip the plan by changing > the number of updated rows. > > [a few minutes later] > > #v+ > hjp=> explain > with a as (select id from id_update where id > 90000 order by id desc) > update id_update as t set id = a.id + 1 from a where a.id = t.id; > ╔════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════╗ > ║ QUERY PLAN ║ > ╟────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╢ > ║ Update on id_update t (cost=732.53..2675.61 rows=0 width=0) ║ > ║ -> Hash Join (cost=732.53..2675.61 rows=10006 width=38) ║ > ║ Hash Cond: (t.id = a.id) ║ > ║ -> Seq Scan on id_update t (cost=0.00..1443.00 rows=100000 width=10) ║ > ║ -> Hash (cost=607.46..607.46 rows=10006 width=32) ║ > ║ -> Subquery Scan on a (cost=0.29..607.46 rows=10006 width=32) ║ > ║ -> Index Only Scan Backward using id_update_pkey on id_update (cost=0.29..507.40 rows=10006 width=4) ║ > ║ Index Cond: (id > 90000) ║ > ╚════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════╝ > #v- > > Looks like we got it. > > And indeed: > > #v+ > hjp=> with a as (select id from id_update where id > 90000 order by id desc) > update id_update as t set id = a.id + 1 from a where a.id = t.id; > ERROR: duplicate key value violates unique constraint "id_update_pkey" > DETAIL: Key (id)=(90002) already exists. > #v- > > So, obviously that isn't guaranteed to work. I read from here: https://www.postgresql.org/docs/current/sql-update.html "Use of an ORDER BY clause allows the command to prioritize which rows will be updated; it can also prevent deadlock with other update operations if they use the same ordering." I went back to those docs and realized I had missed the FOR UPDATE in the example. explain with a as (select id from id_update where id > 90000 order by id desc for update) update id_update as t set id = a.id + 1 from a where a.id = t.id; QUERY PLAN ------------------------------------------------------------------------------------------------------------- Update on id_update t (cost=3609.71..3856.94 rows=0 width=0) CTE a -> LockRows (cost=0.29..872.71 rows=9840 width=10) -> Index Scan Backward using id_update_pkey on id_update (cost=0.29..774.31 rows=9840 width=10) Index Cond: (id > 90000) -> Hash Join (cost=2737.00..2984.23 rows=9840 width=38) Hash Cond: (a.id = t.id) -> CTE Scan on a (cost=0.00..196.80 rows=9840 width=32) -> Hash (cost=1487.00..1487.00 rows=100000 width=10) -> Seq Scan on id_update t (cost=0.00..1487.00 rows=100000 width=10) (10 rows) and then: with a as (select id from id_update where id > 90000 order by id desc for update) update id_update as t set id = a.id + 1 from a where a.id = t.id; UPDATE 10000 Though at this point I would agree with you on the no guarantee point. > > hjp > -- Adrian Klaver adrian.klaver@aklaver.com