Skip to content
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

MDEV-36106 New-style hints: [NO_]DERIVED_CONDITION_PUSHDOWN, [NO_]MERGE #3870

Open
wants to merge 1 commit into
base: bb-11.8-MDEV-35504-opt-hints-v2
Choose a base branch
from

Conversation

DaveGosselin-MariaDB
Copy link
Member

@DaveGosselin-MariaDB DaveGosselin-MariaDB commented Mar 5, 2025

Implements and tests the following optimizer hints:

  • DERIVED_CONDITION_PUSHDOWN
  • NO_DERIVED_CONDITION_PUSHDOWN
  • MERGE
  • NO_MERGE

Each of these are table-level hints. The first pair enable and disable, respectively, the condition pushdown for derived tables which is typically controlled by the condition_pushdown_for_derived optimizer switch. The second pair enable and disable, respectively, the derived table merge optimization which is typically controlled by the derived_merge optimizer switch.

@DaveGosselin-MariaDB DaveGosselin-MariaDB force-pushed the 12.0-mdev-36106-no-derived-condition-pushdown-hint branch from 7b199cb to 12c9440 Compare March 5, 2025 21:26
@spetrunia
Copy link
Member

spetrunia commented Mar 11, 2025

Note: this adds

          !this->opt_hints_table)        // Table hints are not adjusted yet
        select_lex->opt_hints_qb->fix_hints_for_table(this);

code in TABLE_LIST::init_derived() which is called from open_and_lock_tables/mysql_handle_derived.

I guess the need to make a decision whether to do merging in open_and_lock_tables() is a given (we can't change it within the scope of this project). But at least the docs in opt_hints.h need to be updated.

@spetrunia
Copy link
Member

MariaDB [test]>  explain extended select /*+ NO_MERGE(T) */ * from (select * from t1) T;
+------+-------------+------------+------+---------------+------+---------+------+------+----------+-------+
| id   | select_type | table      | type | possible_keys | key  | key_len | ref  | rows | filtered | Extra |
+------+-------------+------------+------+---------------+------+---------+------+------+----------+-------+
|    1 | PRIMARY     | <derived2> | ALL  | NULL          | NULL | NULL    | NULL | 100  |   100.00 |       |
|    2 | DERIVED     | t1         | ALL  | NULL          | NULL | NULL    | NULL | 100  |   100.00 |       |
+------+-------------+------------+------+---------------+------+---------+------+------+----------+-------+
2 rows in set, 1 warning (2.764 sec)

Without the hint, the above query would merge the derived table. It didn't, so the hint had an effect. But EXPLAIN text or optimizer trace do not have anything about the hint:

MariaDB [test]> show warnings\G
*************************** 1. row ***************************
  Level: Note
   Code: 1003
Message: /* select#1 */ select `T`.`a` AS `a`,`T`.`b` AS `b` from (/* select#2 */ select `test`.`t1`.`a` AS `a`,`test`.`t1`.`b` AS `b` from `test`.`t1`) `T`
1 row in set (0.000 sec)

      "join_optimization": {
        "select_id": 1,
        "steps": [
          {
            "hints": ""
          },
          {
            "join_optimization": {
              "select_id": 2,
              "steps": [
                {

@DaveGosselin-MariaDB
Copy link
Member Author

DaveGosselin-MariaDB commented Mar 11, 2025

MariaDB [test]>  explain extended select /*+ NO_MERGE(T) */ * from (select * from t1) T;
+------+-------------+------------+------+---------------+------+---------+------+------+----------+-------+
| id   | select_type | table      | type | possible_keys | key  | key_len | ref  | rows | filtered | Extra |
+------+-------------+------------+------+---------------+------+---------+------+------+----------+-------+
|    1 | PRIMARY     | <derived2> | ALL  | NULL          | NULL | NULL    | NULL | 100  |   100.00 |       |
|    2 | DERIVED     | t1         | ALL  | NULL          | NULL | NULL    | NULL | 100  |   100.00 |       |
+------+-------------+------------+------+---------------+------+---------+------+------+----------+-------+
2 rows in set, 1 warning (2.764 sec)

Without the hint, the above query would merge the derived table. It didn't, so the hint had an effect. But EXPLAIN text or optimizer trace do not have anything about the hint:

MariaDB [test]> show warnings\G
*************************** 1. row ***************************
  Level: Note
   Code: 1003
Message: /* select#1 */ select `T`.`a` AS `a`,`T`.`b` AS `b` from (/* select#2 */ select `test`.`t1`.`a` AS `a`,`test`.`t1`.`b` AS `b` from `test`.`t1`) `T`
1 row in set (0.000 sec)
     "join_optimization": {
       "select_id": 1,
       "steps": [
         {
           "hints": ""
         },
         {
           "join_optimization": {
             "select_id": 2,
             "steps": [
               {

@spetrunia If I’m understanding the code correctly, it is working as expected. We use a bitmap to remember which hints are specified. But this bitmap conflates “is specified as false” with “not specified”. So in the Opt_hints::print method, is_specified will return false if the hint is given but it’s hint value is false, and it won’t be printed in the optimizer trace output.

@spetrunia
Copy link
Member

@DaveGosselin-MariaDB,

Trying on MySQL (I am using 8.4 but I suppose earlier versions would work the same):

create table t1 (a int);
insert into t1 values (1),(2);
explain  select /*+ NO_MERGE(T) */ * from (select * from t1) T;
+----+-------------+------------+------------+------+---------------+------+---------+------+------+----------+-------+
| id | select_type | table      | partitions | type | possible_keys | key  | key_len | ref  | rows | filtered | Extra |
+----+-------------+------------+------------+------+---------------+------+---------+------+------+----------+-------+
|  1 | PRIMARY     | <derived2> | NULL       | ALL  | NULL          | NULL | NULL    | NULL |    2 |   100.00 | NULL  |
|  2 | DERIVED     | t1         | NULL       | ALL  | NULL          | NULL | NULL    | NULL |    2 |   100.00 | NULL  |
+----+-------------+------------+------------+------+---------------+------+---------+------+------+----------+-------+
2 rows in set, 1 warning (0,00 sec)
mysql> show warnings\G
*************************** 1. row ***************************
  Level: Note
   Code: 1003
Message: /* select#1 */ select /*+ NO_MERGE(`T`@`select#1`) */ `T`.`a` AS `a` from (/* select#2 */ select `j21`.`t1`.`a` AS `a` from `j21`.`t1`) `T`
1 row in set (0,00 sec)

Note the NO_MERGE in the warning...

@DaveGosselin-MariaDB DaveGosselin-MariaDB self-assigned this Mar 12, 2025
@DaveGosselin-MariaDB
Copy link
Member Author

@spetrunia and @Olernov, I fixed the issue with the hint name not appearing in the warnings. I'll update the PR as soon as I finish adding the new tests.

@DaveGosselin-MariaDB DaveGosselin-MariaDB force-pushed the 12.0-mdev-36106-no-derived-condition-pushdown-hint branch 2 times, most recently from a1e3615 to 9bef428 Compare March 17, 2025 19:07
Implements and tests the optimizer hints DERIVED_CONDITION_PUSHDOWN
and NO_DERIVED_CONDITION_PUSHDOWN, table-level hints to enable and
disable, respectively, the condition pushdown for derived tables
which is typically controlled by the condition_pushdown_for_derived
optimizer switch.

Implements and tests the optimizer hints MERGE and NO_MERGE, table-level
hints to enable and disable, respectively, the derived_merge optimization
which is typically controlled by the derived_merge optimizer switch.

Sometimes hints need to be fixed before TABLE instances are available, but
after TABLE_LIST instances have been created (as in the cases of MERGE and
NO_MERGE).  This commit introduces code to fix such hints provisionally,
allowing them to be fully fixed later, after their corresponding TABLE
instances have been created.
@DaveGosselin-MariaDB DaveGosselin-MariaDB force-pushed the 12.0-mdev-36106-no-derived-condition-pushdown-hint branch from 9bef428 to 4179821 Compare March 17, 2025 19:27
@DaveGosselin-MariaDB
Copy link
Member Author

This PR is in a logical place until I pick it back up in the next development sprint. I have more test cases to add, specifically for query block hints.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Development

Successfully merging this pull request may close these issues.

None yet

4 participants