Waloid24 opened a new pull request, #2006:
URL: https://github.com/apache/cloudberry/pull/2006

   Addresses the proposal #2005
   
   ### What does this PR do?
   SelectivityOfPredicate() applies damping to the product of local and outer 
predicate estimates, which can increase the result above the local selectivity. 
This violates the bounds of a conjunction when .
   
   Outer predicate estimates use statistics after local filtering. Treat them 
as conditional selectivities and combine them using the existing conjunction 
estimator, then multiply by the local estimate. This preserves the local 
estimate as an upper bound and leaves it unchanged when an outer predicate has 
selectivity one.
   
   Use the active statistics configuration for this aggregation so that 
optimizer_damping_factor_filter controls the correction, rather than the 
hardcoded default. These estimates participate in index selection, so the 
change can affect planning decisions.
   
   ### Type of Change
   - [ ] Bug fix (non-breaking change)
   
   ### Test Plan
   Manually (with `lldb`) compare selectivity estimates produced by the old and 
new versions of the `CFilterStatsProcessor::SelectivityOfPredicate` function.
   
   Create tables:
   ~~~~sql
   SET optimizer = off;
   
   CREATE TABLE damping_inner (
       id integer,
       a  integer,
       b  integer,
       c  integer,
       z  integer
   ) USING heap DISTRIBUTED RANDOMLY;
   
   INSERT INTO damping_inner
   SELECT
       n,
       n % 10,
       (n / 10) % 5,
       (n / 50) % 4,
       0
   FROM generate_series(0, 9999) AS g(n);
   
   CREATE TABLE damping_outer (
       b integer,
       c integer,
       z integer
   ) USING heap DISTRIBUTED REPLICATED;
   
   INSERT INTO damping_outer VALUES (0, 0, 0);
   
   CREATE INDEX damping_inner_abcz
       ON damping_inner USING bitmap (a, b, c, z);
   
   CREATE INDEX damping_inner_bcza
       ON damping_inner USING bitmap (b, c, z, a);
   
   ANALYZE damping_inner;
   ANALYZE damping_outer;
   
   SET optimizer = on;
   SET optimizer_enable_hashjoin = off;
   ~~~~
   
   The generated data has the following properties:
   
   | Property | Value |
   |---|---:|
   | Inner rows | 10,000 |
   | NDV of `a` | 10 |
   | NDV of `b` | 5 |
   | NDV of `c` | 4 |
   | NDV of `z` | 1 |
   
   1. Only a local predicate
   ~~~~sql
   EXPLAIN (ANALYZE, TIMING OFF)
   SELECT i.*
   FROM damping_outer AS o
   CROSS JOIN damping_inner AS i
   WHERE i.a = 1;
   ~~~~
   
   As expected (and the original version does), the query returns exactly 1,000 
rows, corresponding to a selectivity of `0.1`. In the debugger, the function 
returned `0.099999003112316131`; the small difference comes from ORCA's 
normalization of floating-point frequencies.
   
   2. Add an outer predicate that excludes no rows
   ~~~~sql
   EXPLAIN (ANALYZE, TIMING OFF)
   SELECT i.*
   FROM damping_outer AS o
   CROSS JOIN damping_inner AS i
   WHERE i.a = 1
     AND i.z = o.z;
   ~~~~
   Both `i.z` and the single outer row's `o.z` are zero, so the additional 
condition excludes no rows. 
   New version leaves the estimated selectivity as `0.099999003112316131` 
(~`0.1`). While the original version returns local_selectivity/0.75^2 = 
0.177778 > 0.1*1 = 0.1
   
   3. One local predicate and two outer predicates
   ~~~~sql
   EXPLAIN (ANALYZE, TIMING OFF)
   SELECT i.*
   FROM damping_outer AS o
   CROSS JOIN damping_inner AS i
   WHERE i.a = 1
     AND i.b = o.b
     AND i.c = o.c;
   ~~~~
   
   Again, local selectivity is `0.099999003112316131`. Among `1,000` rows 
satisfying `a = 1`, exactly `200` have `b = 0`. So  `q_b = 0.2`. Similarly, 
`q_c = 0.25`. Actual output is `25` rows. At `d=0.75`, the patched calculation 
gives selectivity 0.1 * 0.2 * min(1,0.25/0.75^2) = 0.008888800276650323` 
(`0.008889` from theoretical calculation).
   
   The original implementation gives `0.011851733702200431` (from theory it 
can't be more than `0.1 * 0.2 = 0.02` and less than `0.005`).
   
   - With `SET optimizer_damping_factor_filter = 1` (predicates independence):
   The old version does not react to changes in the 
`optimizer_damping_factor_filter` parameter because it always uses the default 
value. It returns `0.011851733702200431`. The new version returns 
`0.0049999501556158062`, which is consistent with the theoretical value of 
`0.005`.
   
   - With `SET optimizer_damping_factor_filter = 0`:
   Fallback to PostgreSQL optimizer. 
   
   ### Impact
   
   **Performance:**
   Yes, potentially. The planner can choose a plan which better aligns with the 
actual data distribution in the table. 
   
   **User-facing changes:**
   No.
   
   **Dependencies:**
   No.
   
   ### Checklist
   - [ ] Followed [contribution 
guide](https://cloudberry.apache.org/contribute/code)
   - [ ] Added/updated documentation
   - [ ] Reviewed code for security implications
   - [ ] This PR contains AI-assisted code generation
   - [ ] Requested review from [cloudberry 
committers](https://github.com/orgs/apache/teams/cloudberry-committers)
   
   ---
   <!-- Join our community:
   - Mailing list: 
[[email protected]](https://lists.apache.org/[email protected])
 (subscribe: [email protected])
   - Discussions: https://github.com/apache/cloudberry/discussions -->
   


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]


---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to