Reduce planning time for large NOT IN lists containing NULL

Ilia Evdokimov <ilya.evdokimov@tantorlabs.com>

From: Ilia Evdokimov <ilya.evdokimov@tantorlabs.com>
To: PostgreSQL Developers <pgsql-hackers@lists.postgresql.org>
Date: 2026-02-18T14:11:56Z
Lists: pgsql-hackers

Attachments

Hi hackers,

In this thread [0] an interesting idea came up about avoiding 
unnecessary work during selectivity estimation for x <> ALL (NULL, ...) 
or x NOT IN (NULL, ...)

Semantically, if the array contains at least one NULL, the selectivity 
of x NOT IN (...) is always 0.0, regardless of the other elements in the 
list.

Currently, the planner still iterates over all array elements and 
invokes the operator's selectivity estimator for each of them. For large 
IN / ALL lists, this increases planning time.

For constant arrays I propose adding a simple pre-check before entering 
the per-element loop: detect whether the array contains at least one 
NULL element (e.g., via memchr() for the deconstructed array case). If 
so, and we are in the ALL / NOT IN case, we can immediately return 
selectivity = 0.0 and skip all further computation. This would avoid 
extra per-element estimation work while preserving semantics.

In cases where array elements are not known to be constants in advance, 
such a pre-check is less straightforward, because each element must 
first be inspected to determine whether it is a Const and whether it is 
NULL. That already requires iterating through the list, so introducing a 
separate early pass would not actually reduce the amount of work. 
Therefore, it like makes sense to keep the current behavior in that 
situation.

Thoughts?

[0]: 
https://www.postgresql.org/message-id/CAHza6qdAH99C0xa27YDTixiNVFa99j90QYquUPAxL0JwahmggA%40mail.gmail.com

-- 
Best regards.
Ilia Evdokimov,
Tantor Labs LLC,
https://tantorlabs.com/

Commits

  1. Short-circuit row estimation in NOT IN containing NULL consts

  2. Move planner row-estimation tests to new planner_est.sql