Details
-
New Feature
-
Status: In Review (View Workflow)
-
Critical
-
Resolution: Unresolved
-
Q2/2025 Development
Description
See MDEV-35615, section Support ORDER BY/GROUP BY:
We need to rewrite ORDER BY vcol_expr into ORDER BY vcol_field so that the optimizer can use an index to skip sorting.
(MySQL does this, this should be easy to do)
Problem: rewrite makes covering indexes non-covering
Consider a testcase:
create table t (c int, d varchar(100), index IDX_C(c)); |
insert into t select seq,seq from seq_1_to_10000; |
alter table t |
add column vc int as (c + 1), |
add index IDX_VC(vc); |
A query using vcol_expr will use index-only scan on IDX_C :
explain select c+1 from t order by c+1 limit 2;
|
+------+-------------+-------+-------+---------------+-------+---------+------+-------+-----------------------------+
|
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
|
+------+-------------+-------+-------+---------------+-------+---------+------+-------+-----------------------------+
|
| 1 | SIMPLE | t | index | NULL | IDX_C | 5 | NULL | 10330 | Using index; Using filesort |
|
+------+-------------+-------+-------+---------------+-------+---------+------+-------+-----------------------------+
|
(and will not consider IDX_VC).
If we do rewrite in ORDER BY, it will use IDX_VC, but in a non-index-only way:
MariaDB [j4]> explain select c+1 from t order by vc limit 2;
|
+------+-------------+-------+-------+---------------+--------+---------+------+------+-------+
|
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
|
+------+-------------+-------+-------+---------------+--------+---------+------+------+-------+
|
| 1 | SIMPLE | t | index | NULL | IDX_VC | 5 | NULL | 2 | |
|
+------+-------------+-------+-------+---------------+--------+---------+------+------+-------+
|
neither IDX_C, nor IDX_VC are covering anymore.
That is, rewriting ORDER BY vcol_expr into ORDER BY vcol_field makes covering indexes non-covering.
(TODO: what about the rewrite done in MDEV-35616? Won't it have the same problem? )
Solving the Rewrite-makes-indexes-non-covering problem
It seems, the problem is that the optimizer is not aware that it has an option to compute vcol_field from vcol_expr.
What if we made it aware about that? We could take the code that computes the set of covering indexes and make sure
that vcol_field returns these indexes as covering:
- indexes that include vcol_field – this is already done now
- (vcol_expr)->covering_keys – this is new
Then, changing vcol_expr to vcol_field would not reduce the set of query's covering_keys.
Execution code doesnt re-compute stored VCOLs
Can we do it? Not yet: the execution side is missing some code:
https://mariadb.slack.com/archives/C021E77G7K2/p1746525196637819
It seems, for stored virtual columns it is missing the logic to "if the employed access method didn't read the value for column VCOL, compute the value of VCOL from VCOL_EXPR" .
Working around execution code shortcomings.
What if we only handled non-stored virtual columns? That is:
1. Solve the Rewrite-makes-indexes-non-covering problem for non-stored vcols (vcol_field->covering_keys would include vcol->expr->covering_keys).
2. Do theORDER BY rewrite only for non-stored virtual columns.
ycp, it seems that doing this would introduce no regressions?
Attachments
Issue Links
- split from
-
MDEV-35615 Query optimizer support for functional indexes: next steps
-
- Open
-
I hacked the idea of earlier read_set update into a little commit (bb-12.1-mdev-36132 ddd0d65aa652073a22d7d80cb41a4f357723f095), and it does fix the testcase and there seem to be fewer regression test failures. Will continue tomorrow.