-
Notifications
You must be signed in to change notification settings - Fork 3.8k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
sql/opt: prove partial index implication with in-exact atoms containing virtual computed columns #122352
Comments
I wonder if this is at all related to #112978? |
Here's a smaller reproduction, which I believe has the same underlying cause: CREATE TABLE t (
a JSON,
b INT AS ((a->>'c')::INT) VIRTUAL,
INDEX i (b) WHERE b IS NOT NULL
);
SELECT * FROM t@i WHERE b > 4;
-- ERROR: index "i" is a partial index that does not contain all the rows needed to execute this query
-- SQLSTATE: 42809 The problem is that the partial index implicator cannot prove that I think to fix this we'll have to make the partial index implicator aware of virtual computed columns so that it can build constraints on those columns, instead of trying to bulid constraints on the columns referenced in the computed column expression. So in this case we'd build the constraint |
During the opt phase, I checked that |
The I'm fairly confident that |
Sorry, I mixed up the column name here. I was referring to the column b in your example table t. During the execution, I indeed see the predicate being added correctly, and it's aware that the column b in the index can't be null. It looks like the later optimization or the transformation should incorporate that information. |
When attempting the produce the partial index scan, the query plan being operated on looks like:
Notice that the filter However, no filter constraint is generated for |
The partial index implicator is now aware of computed columns and their expressions. This allows implication to be proven in more cases. For example, consider the table and query: CREATE TABLE ( j JSONB, i INT AS ((j->>'x')::INT) VIRTUAL, INDEX (i) WHERE i IS NOT NULL ); SELECT * FROM t WHERE i = 10; Prior to this commit, the optimizer would not plan a constrained scan over the partial index because the implicator could not prove that the query filters, pushed into the projection as `(j->>'x')::INT = 10`, imply the partial index predicate, built as `(j->>'x')::INT IS NOT NULL`. To prove implication cases like this where the expressions are not exact matches, the implicator must build constraints to check if the predicate contains the filter. Constraints cannot be built from these expressions, so verifying containment was impossible. Now that the implicator is aware of computed columns and their expressions, it converts the filter and predicate into expressions referencing virtual computed columns: `i = 10` and `i IS NOT NULL`. Constraints can be built from expressions in this forms, containment can be checked, and implication can be proven. Fixes cockroachdb#122352 Release note (sql change): The optimizer can now plan constrained scans over partial indexes in more cases, particularly on partial indexes with predicates referencing virtual computed columns.
123163: opt: improve partial index implication with virtual columns r=mgartner a=mgartner #### opt: add Implicator benchmarks with virtual columns Release note: None #### opt: improve partial index implication with virtual columns The partial index implicator is now aware of computed columns and their expressions. This allows implication to be proven in more cases. For example, consider the table and query: CREATE TABLE ( j JSONB, i INT AS ((j->>'x')::INT) VIRTUAL, INDEX (i) WHERE i IS NOT NULL ); SELECT * FROM t WHERE i = 10; Prior to this commit, the optimizer would not plan a constrained scan over the partial index because the implicator could not prove that the query filters, pushed into the projection as `(j->>'x')::INT = 10`, imply the partial index predicate, built as `(j->>'x')::INT IS NOT NULL`. To prove implication cases like this where the expressions are not exact matches, the implicator must build constraints to check if the predicate contains the filter. Constraints cannot be built from these expressions, so verifying containment was impossible. Now that the implicator is aware of computed columns and their expressions, it converts the filter and predicate into expressions referencing virtual computed columns: `i = 10` and `i IS NOT NULL`. Constraints can be built from expressions in this forms, containment can be checked, and implication can be proven. Fixes #122352 Release note (sql change): The optimizer can now plan constrained scans over partial indexes in more cases, particularly on partial indexes with predicates referencing virtual computed columns. #### opt: add session setting for virtual computed column implication The `optimizer_prove_implication_with_virtual_computed_columns` has been added which, when enabled, indicates that virtual computed columns should be considered during partial index implication to try to prove that a filter implies a predicate. Release note: None Co-authored-by: Marcus Gartner <marcus@cockroachlabs.com>
The partial index implicator is now aware of computed columns and their expressions. This allows implication to be proven in more cases. For example, consider the table and query: CREATE TABLE ( j JSONB, i INT AS ((j->>'x')::INT) VIRTUAL, INDEX (i) WHERE i IS NOT NULL ); SELECT * FROM t WHERE i = 10; Prior to this commit, the optimizer would not plan a constrained scan over the partial index because the implicator could not prove that the query filters, pushed into the projection as `(j->>'x')::INT = 10`, imply the partial index predicate, built as `(j->>'x')::INT IS NOT NULL`. To prove implication cases like this where the expressions are not exact matches, the implicator must build constraints to check if the predicate contains the filter. Constraints cannot be built from these expressions, so verifying containment was impossible. Now that the implicator is aware of computed columns and their expressions, it converts the filter and predicate into expressions referencing virtual computed columns: `i = 10` and `i IS NOT NULL`. Constraints can be built from expressions in this forms, containment can be checked, and implication can be proven. Fixes cockroachdb#122352 Release note (sql change): The optimizer can now plan constrained scans over partial indexes in more cases, particularly on partial indexes with predicates referencing virtual computed columns.
The partial index implicator is now aware of computed columns and their expressions. This allows implication to be proven in more cases. For example, consider the table and query: CREATE TABLE ( j JSONB, i INT AS ((j->>'x')::INT) VIRTUAL, INDEX (i) WHERE i IS NOT NULL ); SELECT * FROM t WHERE i = 10; Prior to this commit, the optimizer would not plan a constrained scan over the partial index because the implicator could not prove that the query filters, pushed into the projection as `(j->>'x')::INT = 10`, imply the partial index predicate, built as `(j->>'x')::INT IS NOT NULL`. To prove implication cases like this where the expressions are not exact matches, the implicator must build constraints to check if the predicate contains the filter. Constraints cannot be built from these expressions, so verifying containment was impossible. Now that the implicator is aware of computed columns and their expressions, it converts the filter and predicate into expressions referencing virtual computed columns: `i = 10` and `i IS NOT NULL`. Constraints can be built from expressions in this forms, containment can be checked, and implication can be proven. Fixes cockroachdb#122352 Release note (sql change): The optimizer can now plan constrained scans over partial indexes in more cases, particularly on partial indexes with predicates referencing virtual computed columns.
The partial index implicator is now aware of computed columns and their expressions. This allows implication to be proven in more cases. For example, consider the table and query: CREATE TABLE ( j JSONB, i INT AS ((j->>'x')::INT) VIRTUAL, INDEX (i) WHERE i IS NOT NULL ); SELECT * FROM t WHERE i = 10; Prior to this commit, the optimizer would not plan a constrained scan over the partial index because the implicator could not prove that the query filters, pushed into the projection as `(j->>'x')::INT = 10`, imply the partial index predicate, built as `(j->>'x')::INT IS NOT NULL`. To prove implication cases like this where the expressions are not exact matches, the implicator must build constraints to check if the predicate contains the filter. Constraints cannot be built from these expressions, so verifying containment was impossible. Now that the implicator is aware of computed columns and their expressions, it converts the filter and predicate into expressions referencing virtual computed columns: `i = 10` and `i IS NOT NULL`. Constraints can be built from expressions in this forms, containment can be checked, and implication can be proven. Fixes cockroachdb#122352 Release note (sql change): The optimizer can now plan constrained scans over partial indexes in more cases, particularly on partial indexes with predicates referencing virtual computed columns.
Describe the problem
Please describe the issue you observed, and any steps we can take to reproduce it:
Spent quite some time investigating the problem, even tried to force the index scan. The exception was thrown here:
cockroach/pkg/sql/opt/exec/execbuilder/relational.go
Line 598 in 67547d7
Changed the code to force the scan the flags.index, the query worked, but empty result was returned, likely due to predicate matching.
It seemed to me that the predict added here can be further pruned:
cockroach/pkg/sql/opt/optbuilder/select.go
Line 643 in 67547d7
and it might also have something to do with virtual columns, because they are always applied a projection
Expected behavior
The query should not fail.
Environment:
cockroach sql
]Jira issue: CRDB-37825
The text was updated successfully, but these errors were encountered: