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 1vunnW-007E5o-2B for pgsql-hackers@arkaria.postgresql.org; Tue, 24 Feb 2026 08:29:38 +0000 Received: from localhost ([127.0.0.1] helo=malur.postgresql.org) by malur.postgresql.org with esmtp (Exim 4.96) (envelope-from ) id 1vunnT-0008yT-37 for pgsql-hackers@arkaria.postgresql.org; Tue, 24 Feb 2026 08:29:35 +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.96) (envelope-from ) id 1vunnT-0008yL-2A for pgsql-hackers@lists.postgresql.org; Tue, 24 Feb 2026 08:29:35 +0000 Received: from mail-wm1-x335.google.com ([2a00:1450:4864:20::335]) by magus.postgresql.org with esmtps (TLS1.3) tls TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 (Exim 4.98.2) (envelope-from ) id 1vunnQ-000000010Ju-0Uxh for pgsql-hackers@lists.postgresql.org; Tue, 24 Feb 2026 08:29:35 +0000 Received: by mail-wm1-x335.google.com with SMTP id 5b1f17b1804b1-483487335c2so47582225e9.2 for ; Tue, 24 Feb 2026 00:29:31 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1771921769; x=1772526569; darn=lists.postgresql.org; h=content-transfer-encoding:in-reply-to:from:content-language :references:cc:to:subject:user-agent:mime-version:date:message-id :from:to:cc:subject:date:message-id:reply-to; bh=PSXZUcWQU9D3kFXFreEOgQl/7YVVfv320VxEzJu+ygY=; b=iJQG/TSxTpaPp1dsjVwpLTg+e3cS8vo40FrSSOD5AqAor0RhxszQEp2pGeIBPJpdc3 48ZJSvcN8yu7Q2dAv2t4wuk232Pcpp+m+AYAKC4qqaEETreypvNPfTi9SPVeYTb4bIr4 hHc7Wp4PTacguj01qjmGI+dos68n9FcofrPydk7f9oUv95hkyH9EXEro3AHkboEksLNT lesg4JDl9CMjHhsi2ane/6EYOWCYI+A3sHJBZpLmt1GnVNBpLMLZiJazLtlBw8eG5nQ9 y1aKd32hbAb5tdYzlkc/vR3ui1t4iVVUA583n922uQ2RwI+H4pjlB072iSTJCh186/zo PngQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1771921769; x=1772526569; h=content-transfer-encoding:in-reply-to:from:content-language :references:cc:to:subject:user-agent:mime-version:date:message-id :x-gm-gg:x-gm-message-state:from:to:cc:subject:date:message-id :reply-to; bh=PSXZUcWQU9D3kFXFreEOgQl/7YVVfv320VxEzJu+ygY=; b=o4IPiHZJ5i4mF2WKD77RpGB+Zhq2vnC09rd6gcGewGUSF5O20xefJdmUr+UwwitSsh krMgmCYyuaFzG+DuWe/zzrToCeL6TdmzZC/xoeO+wxauMCXhLoK/Ky5VmVlkvRgwZ4cz WCKc927T/67F84ye+v/yvmi9iH1luROv2i6k3p6is8pGhZzf984ZlwnjAg2dLP1zY+3Y MZBY0ld7YGSYyxog3z+GZdgyVGU0utYBVeWfBtdLYZkQpXTqM2wmMEPmda4JcULUrQWi cw4uYYmfvuy/rMwDC05PvJy84vhU2LYsyucdttrkq//v6lgIi/gbwARRPqViNg5S5Bac tvsg== X-Gm-Message-State: AOJu0YzEBe9saag921J53/nnYIvpL3dEebT1JthoTmbKZuk6uYQCRFXn 7IXhZDTGbEZhn3HpeZx/9DZnSm0rw35vne1hZG/88tmWN8d3pq27jH0cJctayg== X-Gm-Gg: AZuq6aIEIq8hxPT/EYyWOrQtbNmdawuq1Doh/YNhnMXRTPHGMIyWrQDplU0E+ur+o7i tBAhFo5p/cqlPrWMyunS0ywFxcDgUlYUTQhk39nDGvaEvYjEPWwvrRzkdrRhmxPh76DumvXRdDS RrcN6sGsHQfM9Aqq5nEBW9JFGyN+yJYBuV6WvdMIn4X6rxCkrWlLL5lbGuMExrBp0GqexOHJm6i wrJGgm/debY63P5TRV5Wc4Ltor7spbi1XWnAfZaksw71SOYv+h0Ps01BYvuiHXDBmESjnHkX0f7 /nkwNqkhOnju2o2HyRhhqnWQyZ1xOMZooWSzZ6n2C7EpqLLPkMve0DHJvM+ae9q50JXICb0yNFY fE6E4WN5X6OdywLxwhS6gpu30J1l3UY4amNVXTWn0YZ+G/uzXNPiMZekCOYpvKpP/FDsqfMC4bv UOab4TtDq02kP6AU499+XdWT8h X-Received: by 2002:a05:600c:46c9:b0:483:6f37:1b51 with SMTP id 5b1f17b1804b1-483a95ea9c9mr164838655e9.23.1771921769086; Tue, 24 Feb 2026 00:29:29 -0800 (PST) Received: from [172.31.5.233] ([165.225.27.16]) by smtp.gmail.com with ESMTPSA id 5b1f17b1804b1-483a31bc0e3sm292822825e9.5.2026.02.24.00.29.28 (version=TLS1_3 cipher=TLS_AES_128_GCM_SHA256 bits=128/128); Tue, 24 Feb 2026 00:29:28 -0800 (PST) Message-ID: <3fc74079-f429-48c8-ad8c-688b21d4d1c1@gmail.com> Date: Tue, 24 Feb 2026 09:29:27 +0100 MIME-Version: 1.0 User-Agent: Mozilla Thunderbird Subject: Re: Reduce planning time for large NOT IN lists containing NULL To: Ilia Evdokimov , Zsolt Parragi Cc: PostgreSQL Developers References: <52596e08-0902-475b-ad0f-265ec6918f19@gmail.com> <7791ec74-369d-48c7-969c-cf4ad18024f2@tantorlabs.com> <6b3aebb5-f26c-4f50-abd6-e733d452af26@gmail.com> <52f3c637-465d-4f0e-9546-732ecf61ab87@tantorlabs.com> Content-Language: en-US From: David Geier In-Reply-To: <52f3c637-465d-4f0e-9546-732ecf61ab87@tantorlabs.com> Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit List-Id: List-Help: List-Subscribe: List-Post: List-Owner: List-Archive: Archived-At: Precedence: bulk >> I think it would be a good idea to add a test, I think there's a >> regression with this patch: >> >> CREATE TABLE notin_test AS SELECT generate_series(1, 1000) AS x; >> ANALYZE notin_test; >> >> CREATE FUNCTION replace_elem(arr int[], idx int, val int) >> RETURNS int[] AS $$ >> BEGIN >>      arr[idx] := val; >>      RETURN arr; >> END; >> $$ LANGUAGE plpgsql IMMUTABLE; >> >> EXPLAIN SELECT * FROM notin_test WHERE x <> ALL(ARRAY[1,99,3]); >> -- same array, constructed from an array with a NULL >> EXPLAIN SELECT * FROM notin_test WHERE x <> >> ALL(replace_elem(ARRAY[1,NULL,3], 2, 99)); >> DROP TABLE notin_test; >> DROP FUNCTION replace_elem; Good catch. The macro name is misleading here. It should have been called ARR_HASNULLBITMAP(). +1 on adding an explicit test that says why we care about that case. >> ARR_HASNULL probably should be array_contains_nulls, as ARR_HASNULL >> simply checks for the existence of a NULL bitmap. Using array_contains_nulls() seems fine. In case the IN list doesn't contain NULL, the function can immediately bail thanks to the !ARR_HASNULL() check in the beginning. It only needs to iterate over the NULL-bitmap, if it exists. This is the case if there's actually a NULL element in the array, or if the array initially contained NULL and all NULLs got removed subsequently. If we ever find the latter case to matter we could remove the NULL-bitmap in array_set_element() / array_set_element_expanded(), when the last NULL element got removed. > Could you clarify what exactly this additional test meant to verify? Zsolt's test case creates an array that initially contains NULL. The NULL element is subsequently replaced by a non-NULL value but array_set_element_expanded() keeps the NULL-bitmap around. With that, your ARR_ISNULL() check bails and causes the selectivity estimation to incorrectly return 0. > I attached this thread to commitfest: https://commitfest.postgresql.org/ > patch/6519/ I'll assign myself as reviewer. -- David Geier