For non-trivial expressions you have to repeat the more or less verbatim condition in queries to make the Postgres query planner understand it can rely on the CHECK
constraint. Even if it seems redundant!
With constraint exclusion enabled, the planner will examine the constraints of each partition and try to prove that the partition need not be scanned because it could not contain any rows meeting the query's
WHERE
clause. When the planner can prove this, it excludes the partition from the query plan.
Bold emphasis mine. The planner does not understand complex expressions. Of course, this has to be met, too:
Ensure that the constraint_exclusion configuration parameter is not disabled in
postgresql.conf
. If it is, queries will not be optimized as desired.
Instead of
SELECT * FROM foo WHERE (id = 2);
Try:
SELECT * FROM foo WHERE id % 30 = 2 AND id = 2;
And:
The default (and recommended) setting of constraint_exclusion is actually neither
on
noroff
, but an intermediate setting calledpartition
, which causes the technique to be applied only to queries that are likely to be working on partitioned tables. The on setting causes the planner to examineCHECK
constraints in all queries, even simple ones that are unlikely to benefit.
You can experiment with the constraint_exclusion = on
to see if the planner catches on without redundant verbatim condition. But you have to weigh cost and benefit of this setting.
The alternative would be simpler conditions for your partitions as already outlined by @harmic.
An no, increasing the number for STATISTICS
will not help in this case. Only the CHECK
constraints and your WHERE
conditions in the query matter.