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.96) (envelope-from ) id 1w0ndc-002DYW-2d for pgsql-hackers@arkaria.postgresql.org; Thu, 12 Mar 2026 21:32:12 +0000 Received: from localhost ([127.0.0.1] helo=malur.postgresql.org) by malur.postgresql.org with esmtp (Exim 4.96) (envelope-from ) id 1w0ndb-000KXz-00 for pgsql-hackers@arkaria.postgresql.org; Thu, 12 Mar 2026 21:32:11 +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.96) (envelope-from ) id 1w0nda-000KXr-1m for pgsql-hackers@lists.postgresql.org; Thu, 12 Mar 2026 21:32:11 +0000 Received: from fout-b5-smtp.messagingengine.com ([202.12.124.148]) by makus.postgresql.org with esmtps (TLS1.3) tls TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 (Exim 4.98.2) (envelope-from ) id 1w0ndY-00000001pgS-4B6t for pgsql-hackers@postgresql.org; Thu, 12 Mar 2026 21:32:10 +0000 Received: from phl-compute-02.internal (phl-compute-02.internal [10.202.2.42]) by mailfout.stl.internal (Postfix) with ESMTP id 5E9861D000E1; Thu, 12 Mar 2026 17:32:08 -0400 (EDT) Received: from phl-imap-14 ([10.202.2.87]) by phl-compute-02.internal (MEProxy); Thu, 12 Mar 2026 17:32:08 -0400 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=burd.me; h=cc: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=1773351128; x=1773437528; bh=Lk8W5+6N9tznetPGwlHD9kc0uK9PtSdUF21cIM2EhXo=; b= RTlNpBbGiT5Ugetd0EIKTtl1lArorLj3UBw562RN1WcMDlzAV/cSwky/T52aX18b 98RYxuUdoqGe7aeKoPk8dr93BTKI4zU60HyiL/K5EIfgrRuI7m4GpRyX4RnHpdpc sVKStE1wHreDPLsJHN9AVUCfs89daYTKG0Yz2LkD6q1Y73FUjbRCG+u8o0mzLIiA KycSRyntBpmQWwvvWFN+wBlf4gPWf09H/Uaqob9VfD0cYtPXVlLdq01q8cE3OYrz WilyobmKi+o4ckScOUc/b5ZPdYGYEhcnYvEWzK1i2PjTlx6s5p50b/NU1QZ4GyQF CItKLEURR+J9jqgnB0cL7Q== DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d= messagingengine.com; h=cc: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=fm1; t=1773351128; x= 1773437528; bh=Lk8W5+6N9tznetPGwlHD9kc0uK9PtSdUF21cIM2EhXo=; b=i TaGqsyC6oI5OplHrnNevnqYZCU3UcAacZxIP6skqsJQGEC8qdhNRw/eW2YHc0Lvl 6YSQInum22Qrk1aN02jVqYPBZKePKVMSnGEYJLfy7wlPdRFZNUS2jipFS8x+6qAV 6e7VUD8GmM1HRFM988ETURJ3U/N06uOhY2ejj7CV2VCVuC4DrGzS8QioCEuqHVmY KbRwjVEK4na7x/g54bSqYgosDa+KZaHkD+bY3bboy4WHOGFPttMn/rj+Yvn5UQhf yUPKuEvdI9qoyKMEPKh1EYbufSnwStWSqx9dUV8IyCoyzi8u1kN1lt/Yf+SVEu51 9AFYXOhFnIgA4QCiZgXzQ== X-ME-Sender: X-ME-Proxy-Cause: gggruggvucftvghtrhhoucdtuddrgeefgedrtddtgddvkeejkeeiucetufdoteggodetrf dotffvucfrrhhofhhilhgvmecuhfgrshhtofgrihhlpdfurfetoffkrfgpnffqhgenuceu rghilhhouhhtmecufedttdenucesvcftvggtihhpihgvnhhtshculddquddttddmnecujf gurhepofggfffhvfevkfgjfhfutgfgsehtjeertdertddtnecuhfhrohhmpedfifhrvghg uceuuhhrugdfuceoghhrvghgsegsuhhrugdrmhgvqeenucggtffrrghtthgvrhhnpedvue fhffdtvdevueffteehheefleevtedvfedtueefffeijeefudelveeftdffudenucevlhhu shhtvghrufhiiigvpedtnecurfgrrhgrmhepmhgrihhlfhhrohhmpehgrhgvghessghurh gurdhmvgdpnhgspghrtghpthhtohepfedpmhhouggvpehsmhhtphhouhhtpdhrtghpthht ohepnhgrthhhrghnuggsohhsshgrrhhtsehgmhgrihhlrdgtohhmpdhrtghpthhtohepph hgshhqlhesjhdquggrvhhishdrtghomhdprhgtphhtthhopehpghhsqhhlqdhhrggtkhgv rhhssehpohhsthhgrhgvshhqlhdrohhrgh X-ME-Proxy: Feedback-ID: i675e48f3:Fastmail Received: by mailuser.phl.internal (Postfix, from userid 501) id DF380C4006E; Thu, 12 Mar 2026 17:32:07 -0400 (EDT) X-Mailer: MessagingEngine.com Webmail Interface MIME-Version: 1.0 X-ThreadId: A1gxZgRQNkgk Date: Thu, 12 Mar 2026 17:31:47 -0400 From: "Greg Burd" To: "Nathan Bossart" Cc: pgsql-hackers , "Jeff Davis" Message-Id: <91f4dbe2-21ed-49f3-bebe-270f9bbec9d5@app.fastmail.com> In-Reply-To: References: <9bb9bdd6-e1fe-48fe-837d-4d0289396f1c@app.fastmail.com> <872b875c-0aa4-4269-9c84-532227b32361@app.fastmail.com> Subject: Re: Expanding HOT updates for expression and partial indexes Content-Type: text/plain Content-Transfer-Encoding: 7bit List-Id: List-Help: List-Subscribe: List-Post: List-Owner: List-Archive: Archived-At: Precedence: bulk On Thu, Mar 12, 2026, at 4:33 PM, Nathan Bossart wrote: > On Wed, Mar 11, 2026 at 11:51:03AM -0400, Greg Burd wrote: >> 0002 - This patch plugs a hole (bug?) in ExecGetAllUpdatedCols() which is >> triggered by an existing test in tsearch.sql and the >> tsvector_update_trigger(). That trigger uses heap_modify_tuple() to >> change an indexed attribute that is not discovered by >> ExecGetAllUpdatedCols(), which seems odd to me at best and at worst wrong >> (or even a potential security issue). This patch finds and adds columns >> that are updated into the Bitmapset returned by ExecGetAllUpdatedCols(). >> The patch includes a helper function ExecCompareSlotAttrs() that will be >> used in follow-on patches as well. > > I just looked at this one for now. Hey Nathan! Thanks for taking the time to review 0002. >> The net is that the functions like HeapDetermineColumnsInfo() have to >> scan all indexed attributes for changes rather than being able to first >> reduce the indexed set by intersecting it with the set of attributes >> known to be potentially updated. > > I noticed the patch doesn't update HeapDetermineColumnsInfo() accordingly. > Is that intended? Yes, that is intended. The 0002 patch is bug fix that I'd hidden along with what is now 0003, I pulled it out for clarity and to discuss independent of the other changes. >> This commit introduces ExecCompareSlotAttrs() as a utility function to >> identify those attributes that have changed. It compares a subset of >> attributes between two TupleTableSlots and returns a Bitmapset of >> attributes that differ. > > Hm. Most of this new function looks duplicated from > HeapDetermineColumnsInfo(), so IIUC this commit effectively adds another > scan through all the attributes. Does this produce noticeably more > overhead? Yes, it appears similar to that for a reason but it differs in one key way. It compares TupleTableSlots, not HeapTuples. The commit doesn't add another scan, the new code only scans the attributes that ExecGetAllUpdatedCols() didn't pick up earlier and have cached for us at this point. The intersection between that set and what is indexed is almost always the NULL set because most UPDATEs don't invoke functions via triggers that modify indexed columns using heap_modify_tuple() directly. But, notably there is the case in tsearch.sql that does. This introduces almost no net new overhead and when it does in fact do some work it's doing no more than what was done before in HeapDetermineColumnsInfo(). >> It would be nice to integrate this into HeapDetermineColumnsInfo(), >> however it would be a layering violation given that it is within >> heap_update(). > > It'd be good to understand whether the current behavior is intentional or > just a happy accident. I found commit 2fd8685e7f, which looks like it was > intended as a prerequisite for the WARM feature (which I don't think was > ever committed). And it seems to have scanned through all indexed columns > when HOT was first introduced in commit 282d2a03dd. Hard to tell if it was accidental or intentional, more digging required, but I'd bet that others poking in this area noticed the test failure and didn't connect the dots fully and just assumed best practice was to scan all indexed columns, even ones that could not have been updated at all. Honestly, if we wrote this section from scratch again today I'm better it'd be closer to where my patch takes us than not. > I'm also curious whether anything else could modify columns that won't be > discovered by ExecGetAllUpdatedCols(). Having HeapDetermineColumnsInfo() > scan everything seems like a defense against such things, which is perhaps > why you've left it unchanged in the patch. I haven't looked into 0003 yet. > Is 0002 a prerequisite for that or a separate fix? Other than the heap_modify_tuple() calls I don't know of something that allows for direct changes but that doesn't matter, 0002 will scan and pick up those attributes even if we introduce a new modification path in the future (as intended). HeapDetermineColumnsInfo() can't call ExecGetAllUpdatedCols() because that function needs resultRelInfo/EState both not available inside heap (table AM) calls. Also, the new helper compares TTS, not HeapTuples, which is what we have in heapam_tuple_update(), so not an option 0002 is a both a bug fix (IMO) and a pre-req for 0003 because in the next patch we use the new ExecCompareSlotAttrs() function from within the executor ahead of calling into ExecUpdate(). > -- > nathan Thanks for your time and comments, let me know if you have more. :) best. -greg