Details

    Description

      This is a self-contained description of Optimizer Hints in MariaDB, whatever is already implemented in the current patch.

      Optimizer hints in MariaDB

      General idea is to be compatible with MySQL.
      MySQL hint docs: https://dev.mysql.com/doc/refman/8.4/en/optimizer-hints.html

      1. Hint syntax

      Hints are placed after the main statement verb

      UPDATE /*+ hints */ table ...;
      DELETE /*+ hints */ FROM table... ;
      SELECT /*+ hints */  ...
      

      or after the SELECT keyword in any subquery:

      SELECT * FROM t1 WHERE a IN (SELECT /*+ hints */ ...) 
      

      There can be one or more hints separated with space

        hints:  hint hint ...
      

      Each individual hint is hint name and arguments. In case there are no arguments,
      the () brackets are still present:

      hint:  hint_name([arguments])
      

      Incorrect hints produce warnings (a setting to make them errors is not implemented yet).

      Hints that are not ignored are kept in the query text (you can see them in SHOW PROCESSLIST, Slow Query Log, EXPLAIN EXTENDED)
      Hints that were incorrect and were ignored are removed from there.

      2. Hint hierarchy

      (todo: elaborate)
      Hints can be

      • global - applies to whole query
      • table-level - applies to a table
      • index-level - applies to an index in a table

      2.1 Table-level hints

      hint_name([table_name [table_name [,...]] )
      

      2.2 Index-level hints

      Index-level hints apply to index(es).
      Possible syntax variants:

      hint_name(table_name [index_name [, index_name] ...])
      hint_name(table_name@query_block [index_name [, index_name] ...])
      hint_name(@query_block  table_name [index_name [, index_name] ...])
      

      3. Query block naming: QB_NAME hint

      QB_NAME hint is used to assign a name to the query block the hint is in. The Query Block is either a SELECT or a top-level construct of UPDATE or DELETE statement.

      SELECT /*+ QB_NAME(foo) */ select_list FROM ...
      

      The name can then can be used

      • to refer to the query block
      • to refer to a table in the query block as table_name@query_block_name.

      Query block scope is the whole statement. It is invalid to use the same name for multiple query blocks.
      One can refer to the query block "down into subquery", "down into derived table", "up to the parent" and "to a right sibling in the UNION". One cannot refer "to a left sibling in a UNION" (It's the same in MySQL).

      Hints inside VIEWs are not supported, yet. One can neither use hints in VIEW definitions, nor control query plans inside non-merged VIEWs (This is because QB_NAME binding is done "early", before we know that some tables are VIEWs)

      3.1 select#n names.

      Besides the given name, any query block is given a name select#n. It is printed in EXPLAIN EXTENDED output:

      Warnings:
      Note	1003	select /*+ NO_RANGE_OPTIMIZATION(`t3`@`select#1` `PRIMARY`) */ ...
      

      At the moment it is NOT yet possible to use it in the hint text:

      SELECT /*+ BKA(tbl1@`select#1`) */ 1 FROM tbl1 ...;
      

      3.2 QB_NAME in CTEs.

      What QB_NAME(@name) is used in a CTE which is then used in multiple places? Hints that control @name will control the first use of the CTE.
      (This "just happens" due to the way CTEs are implemented. We could address it when addressing VIEWs)

      4. Effect of optimizer hints

      Optimizer can be controlled by
      1. Server variables - optimizer_switch, join_cache_level, etc, etc
      2. Old-style hints
      3. New-style hints

      Old-style hints did not overlap with server variable settings.

      New-style hints are more specific than server variable settings, so they override the server variable settings.

      Should new-style hints override old-style hints? TODO.

      Hints are "narrowly interpreted" and "best effort" - if a hint dictates to do something, like

      SELECT  /*+ MRR(t1 t1_index1) */  ... FROM t1 ... 
      

      that means:

      When considering a query plan that involves using t1_index1 in a way that one can use MRR, use MRR.

      if the query planning is such that use of t1_index1 doesn't allow to use MRR, it won't be used.
      The optimizer may also consider using t1_index2 and pick that over using t1_index1.
      In such cases the hint is effectively ignored and no warning is given.
      Examples: mdev35483-mrr-is-narrow.sql

      5. List of hints

      5.1 NO_RANGE_OPTIMIZATION hint

      It's an index-level hint that disables range optimization for certain index(es):

      SELECT /*+ NO_RANGE_OPTIMIZATION(tbl index1 index2) */  * FROM tbl ... 
      

      5.2 NO_ICP hint

      It's an index-level hint that disables Index Condition Pushdown for the indexes. ICP+BKA is disabled as well.

      SELECT /*+ NO_ICP(tbl index1 index2) */  * FROM tbl ... 
      

      5.3 MRR and NO_MRR hints

      Index-level hint to force or disable use of MRR.

      SELECT /*+ MRR(tbl index1 index2) */  * FROM tbl ... 
      SELECT /*+ NO_MRR(tbl index1 index2) */  * FROM tbl ... 
      

      This controls

      5.4 BKA() and NO_BKA() hints

      It's a query block or table-level hint.

      BKA() also enables MRR to make BKA possible. (This is different from session variables, where one needs to enable MRR separately).

      This also enables BKAH. TODO what was the reason for this?

      5.5 BNL() and NO_BNL() hints

      In MySQL this controls hash join, so in MariaDB it controls BNL-H.

      The implementation is "BNL() hint effectively increases join_cache_level up to 4 " .. for the table(s) it applies to)
      (FIXED: this seems to fail a fairly trivial example: mdev35483-bnl-fails-why.txt )

      5.6 MAX_EXECUTION_TIME() hint

      A global-level hint to limit query execution time:
      Example:

      SELECT /*+ MAX_EXECUTION_TIME(milliseconds) */ ...  ;
      

      A query that doesn't finish in the time specified will be aborted with an error.

      Note: if the @@max_statement_time is set, the hint will be ignored and warning produced.
      TODO: This contradicts with the stated principle that "New-style hints are more specific than server variable settings, so they override the server variable settings".

      6. Subquery hints

      6.1. SUBQUERY hint

      Query block-level hint.

      SUBQUERY([@query_block_name] MATERIALIZATION)
      SUBQUERY([@query_block_name] INTOEXISTS)
      

      This controls non-semi-join subqueries. The parameter specifies which subquery to use. Use of this hint disables conversion of subquery into semi-join.

      6.2 SEMIJOIN, NO_SEMIJOIN

      Query block-level hint.
      This controls conversion of subquery to semi-join and which semi-join strategies are allowed.

      [NO_]SEMIJOIN([@query_block_name] [strategy [, strategy] ...])
      

      where strategy is one of DUPSWEEDOUT, FIRSTMATCH, LOOSESCAN, MATERIALIZATION.

      Attachments

        Issue Links

          Activity

            psergei Sergei Petrunia created issue -
            psergei Sergei Petrunia made changes -
            Field Original Value New Value
            Description This is a self-contained description of Optimizer Hints in MariaDB, whatever is already implemented in the current patch.

            h1. Optimizer hints in MariaDB

            h2. Hint syntax
            Hints are placed after the main statement verb

            {code:sql}
            UPDATE /*+ hints */ table ...;
            DELETE /*+ hints */ FROM table... ;
            SELECT /*+ hints */ ...
            {code}

            or after the SELECT keyword in any subquery:
            {code:sql}
            SELECT * FROM t1 WHERE a IN (SELECT /*+ hints */ ...)
            {code}

            There can be one or more hints separated with space
            {code}
              hints: hint hint ...
            {code}

            Each individual hint is hint name and arguments. In case there are no arguments,
            the () brackets are still present:

            {code}
            hint: hint_name([arguments])
            {code}

            h2. Hint hierarchy


            h2. Query block naming: QB_NAME hint

            QB_NAME hint is used to assign a name to the query block the hint is in.

            {code:sql}
            SELECT /*+ QB_NAME(foo) * / select_list FROM ...
            {code}

            The name can be used to refer to the hint later.
            (TODO: what did we decide about the VIEWs)
            (TODO: QB_NAME in CTEs that are used in multiple places?)


            psergei Sergei Petrunia made changes -
            Description This is a self-contained description of Optimizer Hints in MariaDB, whatever is already implemented in the current patch.

            h1. Optimizer hints in MariaDB

            h2. Hint syntax
            Hints are placed after the main statement verb

            {code:sql}
            UPDATE /*+ hints */ table ...;
            DELETE /*+ hints */ FROM table... ;
            SELECT /*+ hints */ ...
            {code}

            or after the SELECT keyword in any subquery:
            {code:sql}
            SELECT * FROM t1 WHERE a IN (SELECT /*+ hints */ ...)
            {code}

            There can be one or more hints separated with space
            {code}
              hints: hint hint ...
            {code}

            Each individual hint is hint name and arguments. In case there are no arguments,
            the () brackets are still present:

            {code}
            hint: hint_name([arguments])
            {code}

            h2. Hint hierarchy


            h2. Query block naming: QB_NAME hint

            QB_NAME hint is used to assign a name to the query block the hint is in.

            {code:sql}
            SELECT /*+ QB_NAME(foo) * / select_list FROM ...
            {code}

            The name can be used to refer to the hint later.
            (TODO: what did we decide about the VIEWs)
            (TODO: QB_NAME in CTEs that are used in multiple places?)


            This is a self-contained description of Optimizer Hints in MariaDB, whatever is already implemented in the current patch.

            h1. Optimizer hints in MariaDB

            h2. 1. Hint syntax
            Hints are placed after the main statement verb

            {code:sql}
            UPDATE /*+ hints */ table ...;
            DELETE /*+ hints */ FROM table... ;
            SELECT /*+ hints */ ...
            {code}

            or after the SELECT keyword in any subquery:
            {code:sql}
            SELECT * FROM t1 WHERE a IN (SELECT /*+ hints */ ...)
            {code}

            There can be one or more hints separated with space
            {code}
              hints: hint hint ...
            {code}

            Each individual hint is hint name and arguments. In case there are no arguments,
            the () brackets are still present:

            {code}
            hint: hint_name([arguments])
            {code}

            h2. 2. Hint hierarchy


            h2. 3. Query block naming: QB_NAME hint

            QB_NAME hint is used to assign a name to the query block the hint is in.

            {code:sql}
            SELECT /*+ QB_NAME(foo) * / select_list FROM ...
            {code}

            The name can be used to refer to the hint later.
            (TODO: what did we decide about the VIEWs)
            (TODO: QB_NAME in CTEs that are used in multiple places?)


            psergei Sergei Petrunia made changes -
            Description This is a self-contained description of Optimizer Hints in MariaDB, whatever is already implemented in the current patch.

            h1. Optimizer hints in MariaDB

            h2. 1. Hint syntax
            Hints are placed after the main statement verb

            {code:sql}
            UPDATE /*+ hints */ table ...;
            DELETE /*+ hints */ FROM table... ;
            SELECT /*+ hints */ ...
            {code}

            or after the SELECT keyword in any subquery:
            {code:sql}
            SELECT * FROM t1 WHERE a IN (SELECT /*+ hints */ ...)
            {code}

            There can be one or more hints separated with space
            {code}
              hints: hint hint ...
            {code}

            Each individual hint is hint name and arguments. In case there are no arguments,
            the () brackets are still present:

            {code}
            hint: hint_name([arguments])
            {code}

            h2. 2. Hint hierarchy


            h2. 3. Query block naming: QB_NAME hint

            QB_NAME hint is used to assign a name to the query block the hint is in.

            {code:sql}
            SELECT /*+ QB_NAME(foo) * / select_list FROM ...
            {code}

            The name can be used to refer to the hint later.
            (TODO: what did we decide about the VIEWs)
            (TODO: QB_NAME in CTEs that are used in multiple places?)


            This is a self-contained description of Optimizer Hints in MariaDB, whatever is already implemented in the current patch.

            h1. Optimizer hints in MariaDB

            h2. 1. Hint syntax
            Hints are placed after the main statement verb

            {code:sql}
            UPDATE /*+ hints */ table ...;
            DELETE /*+ hints */ FROM table... ;
            SELECT /*+ hints */ ...
            {code}

            or after the SELECT keyword in any subquery:
            {code:sql}
            SELECT * FROM t1 WHERE a IN (SELECT /*+ hints */ ...)
            {code}

            There can be one or more hints separated with space
            {code}
              hints: hint hint ...
            {code}

            Each individual hint is hint name and arguments. In case there are no arguments,
            the () brackets are still present:

            {code}
            hint: hint_name([arguments])
            {code}

            h2. 2. Hint hierarchy


            h2. 3. Query block naming: QB_NAME hint

            QB_NAME hint is used to assign a name to the query block the hint is in. The Query Block is either a SELECT or a top-level construct of UPDATE or DELETE statement.

            {code:sql}
            SELECT /*+ QB_NAME(foo) */ select_list FROM ...
            {code}

            The name can be used to refer to the hint later.
            (TODO: what did we decide about the VIEWs)
            (TODO: QB_NAME in CTEs that are used in multiple places?)

            The name can later be used
            * to refer to a query block, where required
            * to refer to a table as {{table_name @ query_block_name}}.

            psergei Sergei Petrunia made changes -
            Description This is a self-contained description of Optimizer Hints in MariaDB, whatever is already implemented in the current patch.

            h1. Optimizer hints in MariaDB

            h2. 1. Hint syntax
            Hints are placed after the main statement verb

            {code:sql}
            UPDATE /*+ hints */ table ...;
            DELETE /*+ hints */ FROM table... ;
            SELECT /*+ hints */ ...
            {code}

            or after the SELECT keyword in any subquery:
            {code:sql}
            SELECT * FROM t1 WHERE a IN (SELECT /*+ hints */ ...)
            {code}

            There can be one or more hints separated with space
            {code}
              hints: hint hint ...
            {code}

            Each individual hint is hint name and arguments. In case there are no arguments,
            the () brackets are still present:

            {code}
            hint: hint_name([arguments])
            {code}

            h2. 2. Hint hierarchy


            h2. 3. Query block naming: QB_NAME hint

            QB_NAME hint is used to assign a name to the query block the hint is in. The Query Block is either a SELECT or a top-level construct of UPDATE or DELETE statement.

            {code:sql}
            SELECT /*+ QB_NAME(foo) */ select_list FROM ...
            {code}

            The name can be used to refer to the hint later.
            (TODO: what did we decide about the VIEWs)
            (TODO: QB_NAME in CTEs that are used in multiple places?)

            The name can later be used
            * to refer to a query block, where required
            * to refer to a table as {{table_name @ query_block_name}}.

            This is a self-contained description of Optimizer Hints in MariaDB, whatever is already implemented in the current patch.

            h1. Optimizer hints in MariaDB

            h2. 1. Hint syntax
            Hints are placed after the main statement verb

            {code:sql}
            UPDATE /*+ hints */ table ...;
            DELETE /*+ hints */ FROM table... ;
            SELECT /*+ hints */ ...
            {code}

            or after the SELECT keyword in any subquery:
            {code:sql}
            SELECT * FROM t1 WHERE a IN (SELECT /*+ hints */ ...)
            {code}

            There can be one or more hints separated with space
            {code}
              hints: hint hint ...
            {code}

            Each individual hint is hint name and arguments. In case there are no arguments,
            the () brackets are still present:

            {code}
            hint: hint_name([arguments])
            {code}

            h2. 2. Hint hierarchy


            h2. 3. Query block naming: QB_NAME hint

            QB_NAME hint is used to assign a name to the query block the hint is in. The Query Block is either a SELECT or a top-level construct of UPDATE or DELETE statement.

            {code:sql}
            SELECT /*+ QB_NAME(foo) */ select_list FROM ...
            {code}

            The name can later be used
            * to refer to a query block, where required
            * to refer to a table as {{table_name @ query_block_name}}.

            (TODO: what did we decide about the VIEWs)
            (TODO: QB_NAME in CTEs that are used in multiple places?)

            psergei Sergei Petrunia made changes -
            Description This is a self-contained description of Optimizer Hints in MariaDB, whatever is already implemented in the current patch.

            h1. Optimizer hints in MariaDB

            h2. 1. Hint syntax
            Hints are placed after the main statement verb

            {code:sql}
            UPDATE /*+ hints */ table ...;
            DELETE /*+ hints */ FROM table... ;
            SELECT /*+ hints */ ...
            {code}

            or after the SELECT keyword in any subquery:
            {code:sql}
            SELECT * FROM t1 WHERE a IN (SELECT /*+ hints */ ...)
            {code}

            There can be one or more hints separated with space
            {code}
              hints: hint hint ...
            {code}

            Each individual hint is hint name and arguments. In case there are no arguments,
            the () brackets are still present:

            {code}
            hint: hint_name([arguments])
            {code}

            h2. 2. Hint hierarchy


            h2. 3. Query block naming: QB_NAME hint

            QB_NAME hint is used to assign a name to the query block the hint is in. The Query Block is either a SELECT or a top-level construct of UPDATE or DELETE statement.

            {code:sql}
            SELECT /*+ QB_NAME(foo) */ select_list FROM ...
            {code}

            The name can later be used
            * to refer to a query block, where required
            * to refer to a table as {{table_name @ query_block_name}}.

            (TODO: what did we decide about the VIEWs)
            (TODO: QB_NAME in CTEs that are used in multiple places?)

            This is a self-contained description of Optimizer Hints in MariaDB, whatever is already implemented in the current patch.

            h1. Optimizer hints in MariaDB

            h2. 1. Hint syntax
            Hints are placed after the main statement verb

            {code:sql}
            UPDATE /*+ hints */ table ...;
            DELETE /*+ hints */ FROM table... ;
            SELECT /*+ hints */ ...
            {code}

            or after the SELECT keyword in any subquery:
            {code:sql}
            SELECT * FROM t1 WHERE a IN (SELECT /*+ hints */ ...)
            {code}

            There can be one or more hints separated with space
            {code}
              hints: hint hint ...
            {code}

            Each individual hint is hint name and arguments. In case there are no arguments,
            the () brackets are still present:

            {code}
            hint: hint_name([arguments])
            {code}

            h2. 2. Hint hierarchy

            h3. 2.1 Index-level hints
            Index-level hints apply to index(es).
            The syntax is
            {code}
            hint_name(table_name [index_name [, index_name] ...])
            {code}

            where table_name may be query_block@table_name.

            (TODO: MySQL also supports hint_name(@query_block_name tbl_name) ? )
             
            h2. 3. Query block naming: QB_NAME hint

            QB_NAME hint is used to assign a name to the query block the hint is in. The Query Block is either a SELECT or a top-level construct of UPDATE or DELETE statement.

            {code:sql}
            SELECT /*+ QB_NAME(foo) */ select_list FROM ...
            {code}

            The name can later be used
            * to refer to a query block, where required
            * to refer to a table as {{table_name@query_block_name}}.

            (TODO: what did we decide about the VIEWs)
            (TODO: QB_NAME in CTEs that are used in multiple places?)

            h2. 4. NO_RANGE_OPTIMIZATION hint
            psergei Sergei Petrunia made changes -
            Description This is a self-contained description of Optimizer Hints in MariaDB, whatever is already implemented in the current patch.

            h1. Optimizer hints in MariaDB

            h2. 1. Hint syntax
            Hints are placed after the main statement verb

            {code:sql}
            UPDATE /*+ hints */ table ...;
            DELETE /*+ hints */ FROM table... ;
            SELECT /*+ hints */ ...
            {code}

            or after the SELECT keyword in any subquery:
            {code:sql}
            SELECT * FROM t1 WHERE a IN (SELECT /*+ hints */ ...)
            {code}

            There can be one or more hints separated with space
            {code}
              hints: hint hint ...
            {code}

            Each individual hint is hint name and arguments. In case there are no arguments,
            the () brackets are still present:

            {code}
            hint: hint_name([arguments])
            {code}

            h2. 2. Hint hierarchy

            h3. 2.1 Index-level hints
            Index-level hints apply to index(es).
            The syntax is
            {code}
            hint_name(table_name [index_name [, index_name] ...])
            {code}

            where table_name may be query_block@table_name.

            (TODO: MySQL also supports hint_name(@query_block_name tbl_name) ? )
             
            h2. 3. Query block naming: QB_NAME hint

            QB_NAME hint is used to assign a name to the query block the hint is in. The Query Block is either a SELECT or a top-level construct of UPDATE or DELETE statement.

            {code:sql}
            SELECT /*+ QB_NAME(foo) */ select_list FROM ...
            {code}

            The name can later be used
            * to refer to a query block, where required
            * to refer to a table as {{table_name@query_block_name}}.

            (TODO: what did we decide about the VIEWs)
            (TODO: QB_NAME in CTEs that are used in multiple places?)

            h2. 4. NO_RANGE_OPTIMIZATION hint
            This is a self-contained description of Optimizer Hints in MariaDB, whatever is already implemented in the current patch.

            h1. Optimizer hints in MariaDB

            h2. 1. Hint syntax
            Hints are placed after the main statement verb

            {code:sql}
            UPDATE /*+ hints */ table ...;
            DELETE /*+ hints */ FROM table... ;
            SELECT /*+ hints */ ...
            {code}

            or after the SELECT keyword in any subquery:
            {code:sql}
            SELECT * FROM t1 WHERE a IN (SELECT /*+ hints */ ...)
            {code}

            There can be one or more hints separated with space
            {code}
              hints: hint hint ...
            {code}

            Each individual hint is hint name and arguments. In case there are no arguments,
            the () brackets are still present:

            {code}
            hint: hint_name([arguments])
            {code}

            h2. 2. Hint hierarchy

            h3. 2.1 Index-level hints
            Index-level hints apply to index(es).
            The syntax is
            {code}
            hint_name(table_name [index_name [, index_name] ...])
            {code}

            where table_name may be query_block@table_name.

            (TODO: MySQL also supports hint_name(@query_block_name tbl_name) ? But we don't? )
             
            h2. 3. Query block naming: QB_NAME hint

            QB_NAME hint is used to assign a name to the query block the hint is in. The Query Block is either a SELECT or a top-level construct of UPDATE or DELETE statement.

            {code:sql}
            SELECT /*+ QB_NAME(foo) */ select_list FROM ...
            {code}

            The name can later be used
            * to refer to a query block, where required
            * to refer to a table as {{table_name@query_block_name}}.

            (TODO: what did we decide about the VIEWs)
            (TODO: QB_NAME in CTEs that are used in multiple places?)

            h2. 4. NO_RANGE_OPTIMIZATION hint

            It's an index-level hint that disables range optimization for certain index(es):
            {code}
            NO_RANGE_OPTIMIZATION(table index1 index2)
            {code}

            psergei Sergei Petrunia made changes -
            Description This is a self-contained description of Optimizer Hints in MariaDB, whatever is already implemented in the current patch.

            h1. Optimizer hints in MariaDB

            h2. 1. Hint syntax
            Hints are placed after the main statement verb

            {code:sql}
            UPDATE /*+ hints */ table ...;
            DELETE /*+ hints */ FROM table... ;
            SELECT /*+ hints */ ...
            {code}

            or after the SELECT keyword in any subquery:
            {code:sql}
            SELECT * FROM t1 WHERE a IN (SELECT /*+ hints */ ...)
            {code}

            There can be one or more hints separated with space
            {code}
              hints: hint hint ...
            {code}

            Each individual hint is hint name and arguments. In case there are no arguments,
            the () brackets are still present:

            {code}
            hint: hint_name([arguments])
            {code}

            h2. 2. Hint hierarchy

            h3. 2.1 Index-level hints
            Index-level hints apply to index(es).
            The syntax is
            {code}
            hint_name(table_name [index_name [, index_name] ...])
            {code}

            where table_name may be query_block@table_name.

            (TODO: MySQL also supports hint_name(@query_block_name tbl_name) ? But we don't? )
             
            h2. 3. Query block naming: QB_NAME hint

            QB_NAME hint is used to assign a name to the query block the hint is in. The Query Block is either a SELECT or a top-level construct of UPDATE or DELETE statement.

            {code:sql}
            SELECT /*+ QB_NAME(foo) */ select_list FROM ...
            {code}

            The name can later be used
            * to refer to a query block, where required
            * to refer to a table as {{table_name@query_block_name}}.

            (TODO: what did we decide about the VIEWs)
            (TODO: QB_NAME in CTEs that are used in multiple places?)

            h2. 4. NO_RANGE_OPTIMIZATION hint

            It's an index-level hint that disables range optimization for certain index(es):
            {code}
            NO_RANGE_OPTIMIZATION(table index1 index2)
            {code}

            This is a self-contained description of Optimizer Hints in MariaDB, whatever is already implemented in the current patch.

            h1. Optimizer hints in MariaDB

            h2. 1. Hint syntax
            Hints are placed after the main statement verb

            {code:sql}
            UPDATE /*+ hints */ table ...;
            DELETE /*+ hints */ FROM table... ;
            SELECT /*+ hints */ ...
            {code}

            or after the SELECT keyword in any subquery:
            {code:sql}
            SELECT * FROM t1 WHERE a IN (SELECT /*+ hints */ ...)
            {code}

            There can be one or more hints separated with space
            {code}
              hints: hint hint ...
            {code}

            Each individual hint is hint name and arguments. In case there are no arguments,
            the () brackets are still present:

            {code}
            hint: hint_name([arguments])
            {code}

            h2. 2. Hint hierarchy

            h3. 2.1 Index-level hints
            Index-level hints apply to index(es).
            The syntax is
            {code}
            hint_name(table_name [index_name [, index_name] ...])
            {code}

            where table_name may be query_block@table_name.

            (TODO: MySQL also supports hint_name(@query_block_name tbl_name) ? But we don't? )
             
            h2. 3. Query block naming: QB_NAME hint

            QB_NAME hint is used to assign a name to the query block the hint is in. The Query Block is either a SELECT or a top-level construct of UPDATE or DELETE statement.

            {code:sql}
            SELECT /*+ QB_NAME(foo) */ select_list FROM ...
            {code}

            The name can later be used
            * to refer to a query block, where required
            * to refer to a table as {{table_name@query_block_name}}.

            (TODO: what did we decide about the VIEWs)
            (TODO: QB_NAME in CTEs that are used in multiple places?)

            h2. 5. List of hints

            h2. 5.1 NO_RANGE_OPTIMIZATION hint

            It's an index-level hint that disables range optimization for certain index(es):
            {code:sql}
            SELECT /*+ NO_RANGE_OPTIMIZATION(tbl index1 index2) */ * FROM tbl ...
            {code}

            h2. 5.2 NO_ICP hint
            It's an index-level hint that disables Index Condition Pushdown for the indexes. ICP+BKA is disabled as well.
            {code:sql}
            SELECT /*+ NO_ICP(tbl index1 index2) */ * FROM tbl ...
            {code}

            psergei Sergei Petrunia made changes -
            Description This is a self-contained description of Optimizer Hints in MariaDB, whatever is already implemented in the current patch.

            h1. Optimizer hints in MariaDB

            h2. 1. Hint syntax
            Hints are placed after the main statement verb

            {code:sql}
            UPDATE /*+ hints */ table ...;
            DELETE /*+ hints */ FROM table... ;
            SELECT /*+ hints */ ...
            {code}

            or after the SELECT keyword in any subquery:
            {code:sql}
            SELECT * FROM t1 WHERE a IN (SELECT /*+ hints */ ...)
            {code}

            There can be one or more hints separated with space
            {code}
              hints: hint hint ...
            {code}

            Each individual hint is hint name and arguments. In case there are no arguments,
            the () brackets are still present:

            {code}
            hint: hint_name([arguments])
            {code}

            h2. 2. Hint hierarchy

            h3. 2.1 Index-level hints
            Index-level hints apply to index(es).
            The syntax is
            {code}
            hint_name(table_name [index_name [, index_name] ...])
            {code}

            where table_name may be query_block@table_name.

            (TODO: MySQL also supports hint_name(@query_block_name tbl_name) ? But we don't? )
             
            h2. 3. Query block naming: QB_NAME hint

            QB_NAME hint is used to assign a name to the query block the hint is in. The Query Block is either a SELECT or a top-level construct of UPDATE or DELETE statement.

            {code:sql}
            SELECT /*+ QB_NAME(foo) */ select_list FROM ...
            {code}

            The name can later be used
            * to refer to a query block, where required
            * to refer to a table as {{table_name@query_block_name}}.

            (TODO: what did we decide about the VIEWs)
            (TODO: QB_NAME in CTEs that are used in multiple places?)

            h2. 5. List of hints

            h2. 5.1 NO_RANGE_OPTIMIZATION hint

            It's an index-level hint that disables range optimization for certain index(es):
            {code:sql}
            SELECT /*+ NO_RANGE_OPTIMIZATION(tbl index1 index2) */ * FROM tbl ...
            {code}

            h2. 5.2 NO_ICP hint
            It's an index-level hint that disables Index Condition Pushdown for the indexes. ICP+BKA is disabled as well.
            {code:sql}
            SELECT /*+ NO_ICP(tbl index1 index2) */ * FROM tbl ...
            {code}

            This is a self-contained description of Optimizer Hints in MariaDB, whatever is already implemented in the current patch.

            h1. Optimizer hints in MariaDB

            h2. 1. Hint syntax
            Hints are placed after the main statement verb

            {code:sql}
            UPDATE /*+ hints */ table ...;
            DELETE /*+ hints */ FROM table... ;
            SELECT /*+ hints */ ...
            {code}

            or after the SELECT keyword in any subquery:
            {code:sql}
            SELECT * FROM t1 WHERE a IN (SELECT /*+ hints */ ...)
            {code}

            There can be one or more hints separated with space
            {code}
              hints: hint hint ...
            {code}

            Each individual hint is hint name and arguments. In case there are no arguments,
            the () brackets are still present:

            {code}
            hint: hint_name([arguments])
            {code}

            h2. 2. Hint hierarchy

            h3. 2.1 Index-level hints
            Index-level hints apply to index(es).
            The syntax is
            {code}
            hint_name(table_name [index_name [, index_name] ...])
            {code}

            where table_name may be query_block@table_name.

            (TODO: MySQL also supports hint_name(@query_block_name tbl_name) ? But we don't? )
             
            h2. 3. Query block naming: QB_NAME hint

            QB_NAME hint is used to assign a name to the query block the hint is in. The Query Block is either a SELECT or a top-level construct of UPDATE or DELETE statement.

            {code:sql}
            SELECT /*+ QB_NAME(foo) */ select_list FROM ...
            {code}

            The name can later be used
            * to refer to a query block, where required
            * to refer to a table as {{table_name@query_block_name}}.

            (TODO: what did we decide about the VIEWs)
            (TODO: QB_NAME in CTEs that are used in multiple places?)

            h2. 4. Effect of optimizer hints

            Optimizer can be controlled by
            1. Server variables - optimizer_switch, join_cache_level, etc, etc
            2. Old-style hints
            3. New-style hints

            Old-style hints did not overlap with server variable settings.

            New-style hints are more specific than server variable settings, so they override the server variable settings.

            Should new-style hints override old-style hints? TODO.


            h2. 5. List of hints

            h2. 5.1 NO_RANGE_OPTIMIZATION hint

            It's an index-level hint that disables range optimization for certain index(es):
            {code:sql}
            SELECT /*+ NO_RANGE_OPTIMIZATION(tbl index1 index2) */ * FROM tbl ...
            {code}

            h2. 5.2 NO_ICP hint
            It's an index-level hint that disables Index Condition Pushdown for the indexes. ICP+BKA is disabled as well.
            {code:sql}
            SELECT /*+ NO_ICP(tbl index1 index2) */ * FROM tbl ...
            {code}

            h3. MRR and NO_MRR hints
            .
            psergei Sergei Petrunia made changes -
            Description This is a self-contained description of Optimizer Hints in MariaDB, whatever is already implemented in the current patch.

            h1. Optimizer hints in MariaDB

            h2. 1. Hint syntax
            Hints are placed after the main statement verb

            {code:sql}
            UPDATE /*+ hints */ table ...;
            DELETE /*+ hints */ FROM table... ;
            SELECT /*+ hints */ ...
            {code}

            or after the SELECT keyword in any subquery:
            {code:sql}
            SELECT * FROM t1 WHERE a IN (SELECT /*+ hints */ ...)
            {code}

            There can be one or more hints separated with space
            {code}
              hints: hint hint ...
            {code}

            Each individual hint is hint name and arguments. In case there are no arguments,
            the () brackets are still present:

            {code}
            hint: hint_name([arguments])
            {code}

            h2. 2. Hint hierarchy

            h3. 2.1 Index-level hints
            Index-level hints apply to index(es).
            The syntax is
            {code}
            hint_name(table_name [index_name [, index_name] ...])
            {code}

            where table_name may be query_block@table_name.

            (TODO: MySQL also supports hint_name(@query_block_name tbl_name) ? But we don't? )
             
            h2. 3. Query block naming: QB_NAME hint

            QB_NAME hint is used to assign a name to the query block the hint is in. The Query Block is either a SELECT or a top-level construct of UPDATE or DELETE statement.

            {code:sql}
            SELECT /*+ QB_NAME(foo) */ select_list FROM ...
            {code}

            The name can later be used
            * to refer to a query block, where required
            * to refer to a table as {{table_name@query_block_name}}.

            (TODO: what did we decide about the VIEWs)
            (TODO: QB_NAME in CTEs that are used in multiple places?)

            h2. 4. Effect of optimizer hints

            Optimizer can be controlled by
            1. Server variables - optimizer_switch, join_cache_level, etc, etc
            2. Old-style hints
            3. New-style hints

            Old-style hints did not overlap with server variable settings.

            New-style hints are more specific than server variable settings, so they override the server variable settings.

            Should new-style hints override old-style hints? TODO.


            h2. 5. List of hints

            h2. 5.1 NO_RANGE_OPTIMIZATION hint

            It's an index-level hint that disables range optimization for certain index(es):
            {code:sql}
            SELECT /*+ NO_RANGE_OPTIMIZATION(tbl index1 index2) */ * FROM tbl ...
            {code}

            h2. 5.2 NO_ICP hint
            It's an index-level hint that disables Index Condition Pushdown for the indexes. ICP+BKA is disabled as well.
            {code:sql}
            SELECT /*+ NO_ICP(tbl index1 index2) */ * FROM tbl ...
            {code}

            h3. MRR and NO_MRR hints
            .
            This is a self-contained description of Optimizer Hints in MariaDB, whatever is already implemented in the current patch.

            h1. Optimizer hints in MariaDB

            h2. 1. Hint syntax
            Hints are placed after the main statement verb

            {code:sql}
            UPDATE /*+ hints */ table ...;
            DELETE /*+ hints */ FROM table... ;
            SELECT /*+ hints */ ...
            {code}

            or after the SELECT keyword in any subquery:
            {code:sql}
            SELECT * FROM t1 WHERE a IN (SELECT /*+ hints */ ...)
            {code}

            There can be one or more hints separated with space
            {code}
              hints: hint hint ...
            {code}

            Each individual hint is hint name and arguments. In case there are no arguments,
            the () brackets are still present:

            {code}
            hint: hint_name([arguments])
            {code}

            h2. 2. Hint hierarchy

            h3. 2.1 Index-level hints
            Index-level hints apply to index(es).
            The syntax is
            {code}
            hint_name(table_name [index_name [, index_name] ...])
            {code}

            where table_name may be query_block@table_name.

            (TODO: MySQL also supports hint_name(@query_block_name tbl_name) ? But we don't? )
             
            h2. 3. Query block naming: QB_NAME hint

            QB_NAME hint is used to assign a name to the query block the hint is in. The Query Block is either a SELECT or a top-level construct of UPDATE or DELETE statement.

            {code:sql}
            SELECT /*+ QB_NAME(foo) */ select_list FROM ...
            {code}

            The name can later be used
            * to refer to a query block, where required
            * to refer to a table as {{table_name@query_block_name}}.

            (TODO: what did we decide about the VIEWs)
            (TODO: QB_NAME in CTEs that are used in multiple places?)

            h2. 4. Effect of optimizer hints

            Optimizer can be controlled by
            1. Server variables - optimizer_switch, join_cache_level, etc, etc
            2. Old-style hints
            3. New-style hints

            Old-style hints did not overlap with server variable settings.

            New-style hints are more specific than server variable settings, so they override the server variable settings.

            Should new-style hints override old-style hints? TODO.

            Hints are "best effort" - if a hint dictates to do something (e.g. {{MRR(t1 t1_index1)}}) but the optimizer doesn't come to the point where it would consider using index {{t1_index1}} in a way that it's possible to use MRR, then the hint will be ignored with no warnings.

            h2. 5. List of hints

            h2. 5.1 NO_RANGE_OPTIMIZATION hint

            It's an index-level hint that disables range optimization for certain index(es):
            {code:sql}
            SELECT /*+ NO_RANGE_OPTIMIZATION(tbl index1 index2) */ * FROM tbl ...
            {code}

            h2. 5.2 NO_ICP hint
            It's an index-level hint that disables Index Condition Pushdown for the indexes. ICP+BKA is disabled as well.
            {code:sql}
            SELECT /*+ NO_ICP(tbl index1 index2) */ * FROM tbl ...
            {code}

            h3. MRR and NO_MRR hints
            .
            psergei Sergei Petrunia made changes -
            Description This is a self-contained description of Optimizer Hints in MariaDB, whatever is already implemented in the current patch.

            h1. Optimizer hints in MariaDB

            h2. 1. Hint syntax
            Hints are placed after the main statement verb

            {code:sql}
            UPDATE /*+ hints */ table ...;
            DELETE /*+ hints */ FROM table... ;
            SELECT /*+ hints */ ...
            {code}

            or after the SELECT keyword in any subquery:
            {code:sql}
            SELECT * FROM t1 WHERE a IN (SELECT /*+ hints */ ...)
            {code}

            There can be one or more hints separated with space
            {code}
              hints: hint hint ...
            {code}

            Each individual hint is hint name and arguments. In case there are no arguments,
            the () brackets are still present:

            {code}
            hint: hint_name([arguments])
            {code}

            h2. 2. Hint hierarchy

            h3. 2.1 Index-level hints
            Index-level hints apply to index(es).
            The syntax is
            {code}
            hint_name(table_name [index_name [, index_name] ...])
            {code}

            where table_name may be query_block@table_name.

            (TODO: MySQL also supports hint_name(@query_block_name tbl_name) ? But we don't? )
             
            h2. 3. Query block naming: QB_NAME hint

            QB_NAME hint is used to assign a name to the query block the hint is in. The Query Block is either a SELECT or a top-level construct of UPDATE or DELETE statement.

            {code:sql}
            SELECT /*+ QB_NAME(foo) */ select_list FROM ...
            {code}

            The name can later be used
            * to refer to a query block, where required
            * to refer to a table as {{table_name@query_block_name}}.

            (TODO: what did we decide about the VIEWs)
            (TODO: QB_NAME in CTEs that are used in multiple places?)

            h2. 4. Effect of optimizer hints

            Optimizer can be controlled by
            1. Server variables - optimizer_switch, join_cache_level, etc, etc
            2. Old-style hints
            3. New-style hints

            Old-style hints did not overlap with server variable settings.

            New-style hints are more specific than server variable settings, so they override the server variable settings.

            Should new-style hints override old-style hints? TODO.

            Hints are "best effort" - if a hint dictates to do something (e.g. {{MRR(t1 t1_index1)}}) but the optimizer doesn't come to the point where it would consider using index {{t1_index1}} in a way that it's possible to use MRR, then the hint will be ignored with no warnings.

            h2. 5. List of hints

            h2. 5.1 NO_RANGE_OPTIMIZATION hint

            It's an index-level hint that disables range optimization for certain index(es):
            {code:sql}
            SELECT /*+ NO_RANGE_OPTIMIZATION(tbl index1 index2) */ * FROM tbl ...
            {code}

            h2. 5.2 NO_ICP hint
            It's an index-level hint that disables Index Condition Pushdown for the indexes. ICP+BKA is disabled as well.
            {code:sql}
            SELECT /*+ NO_ICP(tbl index1 index2) */ * FROM tbl ...
            {code}

            h3. MRR and NO_MRR hints
            .
            This is a self-contained description of Optimizer Hints in MariaDB, whatever is already implemented in the current patch.

            h1. Optimizer hints in MariaDB

            h2. 1. Hint syntax
            Hints are placed after the main statement verb

            {code:sql}
            UPDATE /*+ hints */ table ...;
            DELETE /*+ hints */ FROM table... ;
            SELECT /*+ hints */ ...
            {code}

            or after the SELECT keyword in any subquery:
            {code:sql}
            SELECT * FROM t1 WHERE a IN (SELECT /*+ hints */ ...)
            {code}

            There can be one or more hints separated with space
            {code}
              hints: hint hint ...
            {code}

            Each individual hint is hint name and arguments. In case there are no arguments,
            the () brackets are still present:

            {code}
            hint: hint_name([arguments])
            {code}

            Incorrect hints produce warnings. (TODO any thing else?)
            Hints that are not ignored are kept in the query text (you can see them in SHOW PROCESSLIST, Slow Query Log, EXPLAIN EXTENDED)
            Hints that were incorrect and were ignored are removed from there.

            h2. 2. Hint hierarchy

            h3. 2.1 Index-level hints
            Index-level hints apply to index(es).
            The syntax is
            {code}
            hint_name(table_name [index_name [, index_name] ...])
            {code}

            where table_name may be query_block@table_name.

            (TODO: MySQL also supports hint_name(@query_block_name tbl_name) ? But we don't? )
             
            h2. 3. Query block naming: QB_NAME hint

            QB_NAME hint is used to assign a name to the query block the hint is in. The Query Block is either a SELECT or a top-level construct of UPDATE or DELETE statement.

            {code:sql}
            SELECT /*+ QB_NAME(foo) */ select_list FROM ...
            {code}

            The name can later be used
            * to refer to a query block, where required
            * to refer to a table as {{table_name@query_block_name}}.

            Hints inside VIEWs are not supported, yet.

            Besides the given name, any query block is given a name {{select#n}}, so one can refer to it like so:
            {code:sql}
            SELECT /*+ BKA(tbl1@`select#1`) */ 1 FROM tbl1 ...;
            {code}
            (TODO: can one control SELECTs inside VIEWs that way? No?)
            (TODO: QB_NAME in CTEs that are used in multiple places?)

            h2. 4. Effect of optimizer hints

            Optimizer can be controlled by
            1. Server variables - optimizer_switch, join_cache_level, etc, etc
            2. Old-style hints
            3. New-style hints

            Old-style hints did not overlap with server variable settings.

            New-style hints are more specific than server variable settings, so they override the server variable settings.

            Should new-style hints override old-style hints? TODO.

            Hints are "best effort" - if a hint dictates to do something (e.g. {{MRR(t1 t1_index1)}}) but the optimizer doesn't come to the point where it would consider using index {{t1_index1}} in a way that it's possible to use MRR, then the hint will be ignored with no warnings.

            h2. 5. List of hints

            h2. 5.1 NO_RANGE_OPTIMIZATION hint

            It's an index-level hint that disables range optimization for certain index(es):
            {code:sql}
            SELECT /*+ NO_RANGE_OPTIMIZATION(tbl index1 index2) */ * FROM tbl ...
            {code}

            h2. 5.2 NO_ICP hint
            It's an index-level hint that disables Index Condition Pushdown for the indexes. ICP+BKA is disabled as well.
            {code:sql}
            SELECT /*+ NO_ICP(tbl index1 index2) */ * FROM tbl ...
            {code}

            h3. MRR and NO_MRR hints
            .
            psergei Sergei Petrunia made changes -
            Description This is a self-contained description of Optimizer Hints in MariaDB, whatever is already implemented in the current patch.

            h1. Optimizer hints in MariaDB

            h2. 1. Hint syntax
            Hints are placed after the main statement verb

            {code:sql}
            UPDATE /*+ hints */ table ...;
            DELETE /*+ hints */ FROM table... ;
            SELECT /*+ hints */ ...
            {code}

            or after the SELECT keyword in any subquery:
            {code:sql}
            SELECT * FROM t1 WHERE a IN (SELECT /*+ hints */ ...)
            {code}

            There can be one or more hints separated with space
            {code}
              hints: hint hint ...
            {code}

            Each individual hint is hint name and arguments. In case there are no arguments,
            the () brackets are still present:

            {code}
            hint: hint_name([arguments])
            {code}

            Incorrect hints produce warnings. (TODO any thing else?)
            Hints that are not ignored are kept in the query text (you can see them in SHOW PROCESSLIST, Slow Query Log, EXPLAIN EXTENDED)
            Hints that were incorrect and were ignored are removed from there.

            h2. 2. Hint hierarchy

            h3. 2.1 Index-level hints
            Index-level hints apply to index(es).
            The syntax is
            {code}
            hint_name(table_name [index_name [, index_name] ...])
            {code}

            where table_name may be query_block@table_name.

            (TODO: MySQL also supports hint_name(@query_block_name tbl_name) ? But we don't? )
             
            h2. 3. Query block naming: QB_NAME hint

            QB_NAME hint is used to assign a name to the query block the hint is in. The Query Block is either a SELECT or a top-level construct of UPDATE or DELETE statement.

            {code:sql}
            SELECT /*+ QB_NAME(foo) */ select_list FROM ...
            {code}

            The name can later be used
            * to refer to a query block, where required
            * to refer to a table as {{table_name@query_block_name}}.

            Hints inside VIEWs are not supported, yet.

            Besides the given name, any query block is given a name {{select#n}}, so one can refer to it like so:
            {code:sql}
            SELECT /*+ BKA(tbl1@`select#1`) */ 1 FROM tbl1 ...;
            {code}
            (TODO: can one control SELECTs inside VIEWs that way? No?)
            (TODO: QB_NAME in CTEs that are used in multiple places?)

            h2. 4. Effect of optimizer hints

            Optimizer can be controlled by
            1. Server variables - optimizer_switch, join_cache_level, etc, etc
            2. Old-style hints
            3. New-style hints

            Old-style hints did not overlap with server variable settings.

            New-style hints are more specific than server variable settings, so they override the server variable settings.

            Should new-style hints override old-style hints? TODO.

            Hints are "best effort" - if a hint dictates to do something (e.g. {{MRR(t1 t1_index1)}}) but the optimizer doesn't come to the point where it would consider using index {{t1_index1}} in a way that it's possible to use MRR, then the hint will be ignored with no warnings.

            h2. 5. List of hints

            h2. 5.1 NO_RANGE_OPTIMIZATION hint

            It's an index-level hint that disables range optimization for certain index(es):
            {code:sql}
            SELECT /*+ NO_RANGE_OPTIMIZATION(tbl index1 index2) */ * FROM tbl ...
            {code}

            h2. 5.2 NO_ICP hint
            It's an index-level hint that disables Index Condition Pushdown for the indexes. ICP+BKA is disabled as well.
            {code:sql}
            SELECT /*+ NO_ICP(tbl index1 index2) */ * FROM tbl ...
            {code}

            h3. MRR and NO_MRR hints
            .
            This is a self-contained description of Optimizer Hints in MariaDB, whatever is already implemented in the current patch.

            h1. Optimizer hints in MariaDB

            h2. 1. Hint syntax
            Hints are placed after the main statement verb

            {code:sql}
            UPDATE /*+ hints */ table ...;
            DELETE /*+ hints */ FROM table... ;
            SELECT /*+ hints */ ...
            {code}

            or after the SELECT keyword in any subquery:
            {code:sql}
            SELECT * FROM t1 WHERE a IN (SELECT /*+ hints */ ...)
            {code}

            There can be one or more hints separated with space
            {code}
              hints: hint hint ...
            {code}

            Each individual hint is hint name and arguments. In case there are no arguments,
            the () brackets are still present:

            {code}
            hint: hint_name([arguments])
            {code}

            Incorrect hints produce warnings. (TODO any thing else?)
            Hints that are not ignored are kept in the query text (you can see them in SHOW PROCESSLIST, Slow Query Log, EXPLAIN EXTENDED)
            Hints that were incorrect and were ignored are removed from there.

            h2. 2. Hint hierarchy

            h3. 2.1 Index-level hints
            Index-level hints apply to index(es).
            The syntax is
            {code}
            hint_name(table_name [index_name [, index_name] ...])
            {code}

            where table_name may be query_block@table_name.

            (TODO: MySQL also supports hint_name(@query_block_name tbl_name) ? But we don't? )
             
            h2. 3. Query block naming: QB_NAME hint

            QB_NAME hint is used to assign a name to the query block the hint is in. The Query Block is either a SELECT or a top-level construct of UPDATE or DELETE statement.

            {code:sql}
            SELECT /*+ QB_NAME(foo) */ select_list FROM ...
            {code}

            The name can later be used
            * to refer to a query block, where required
            * to refer to a table as {{table_name@query_block_name}}.

            Hints inside VIEWs are not supported, yet.

            Besides the given name, any query block is given a name {{select#n}}, so one can refer to it like so:
            {code:sql}
            SELECT /*+ BKA(tbl1@`select#1`) */ 1 FROM tbl1 ...;
            {code}
            (TODO: can one control SELECTs inside VIEWs that way? No?)
            (TODO: QB_NAME in CTEs that are used in multiple places?)

            h2. 4. Effect of optimizer hints

            Optimizer can be controlled by
            1. Server variables - optimizer_switch, join_cache_level, etc, etc
            2. Old-style hints
            3. New-style hints

            Old-style hints did not overlap with server variable settings.

            New-style hints are more specific than server variable settings, so they override the server variable settings.

            Should new-style hints override old-style hints? TODO.

            Hints are "narrowly interpreted" and "best effort" - if a hint dictates to do something, like
            {code:sql}
            SELECT /*+ MRR(t1 t1_index1) */ ... FROM t1 ...
            {code}
            that means:
            {quote}
            When considering a query plan that involves using t1_index1 in a way that one can use MRR, use MRR.
            {quote}
            if the query planning is such that use of {{t1_index1}} doesn't allow to use MRR, it won't be used.
            The optimizer may also consider using {{t1_index2}} and pick that over using {{t1_index1}}.
            In such cases the hint is effectively ignored and no warning is given.

            h2. 5. List of hints

            h2. 5.1 NO_RANGE_OPTIMIZATION hint

            It's an index-level hint that disables range optimization for certain index(es):
            {code:sql}
            SELECT /*+ NO_RANGE_OPTIMIZATION(tbl index1 index2) */ * FROM tbl ...
            {code}

            h2. 5.2 NO_ICP hint
            It's an index-level hint that disables Index Condition Pushdown for the indexes. ICP+BKA is disabled as well.
            {code:sql}
            SELECT /*+ NO_ICP(tbl index1 index2) */ * FROM tbl ...
            {code}

            h3. MRR and NO_MRR hints
            .
            psergei Sergei Petrunia made changes -
            Attachment mdev35483-mrr-is-narrow.sql [ 74268 ]
            psergei Sergei Petrunia made changes -
            Description This is a self-contained description of Optimizer Hints in MariaDB, whatever is already implemented in the current patch.

            h1. Optimizer hints in MariaDB

            h2. 1. Hint syntax
            Hints are placed after the main statement verb

            {code:sql}
            UPDATE /*+ hints */ table ...;
            DELETE /*+ hints */ FROM table... ;
            SELECT /*+ hints */ ...
            {code}

            or after the SELECT keyword in any subquery:
            {code:sql}
            SELECT * FROM t1 WHERE a IN (SELECT /*+ hints */ ...)
            {code}

            There can be one or more hints separated with space
            {code}
              hints: hint hint ...
            {code}

            Each individual hint is hint name and arguments. In case there are no arguments,
            the () brackets are still present:

            {code}
            hint: hint_name([arguments])
            {code}

            Incorrect hints produce warnings. (TODO any thing else?)
            Hints that are not ignored are kept in the query text (you can see them in SHOW PROCESSLIST, Slow Query Log, EXPLAIN EXTENDED)
            Hints that were incorrect and were ignored are removed from there.

            h2. 2. Hint hierarchy

            h3. 2.1 Index-level hints
            Index-level hints apply to index(es).
            The syntax is
            {code}
            hint_name(table_name [index_name [, index_name] ...])
            {code}

            where table_name may be query_block@table_name.

            (TODO: MySQL also supports hint_name(@query_block_name tbl_name) ? But we don't? )
             
            h2. 3. Query block naming: QB_NAME hint

            QB_NAME hint is used to assign a name to the query block the hint is in. The Query Block is either a SELECT or a top-level construct of UPDATE or DELETE statement.

            {code:sql}
            SELECT /*+ QB_NAME(foo) */ select_list FROM ...
            {code}

            The name can later be used
            * to refer to a query block, where required
            * to refer to a table as {{table_name@query_block_name}}.

            Hints inside VIEWs are not supported, yet.

            Besides the given name, any query block is given a name {{select#n}}, so one can refer to it like so:
            {code:sql}
            SELECT /*+ BKA(tbl1@`select#1`) */ 1 FROM tbl1 ...;
            {code}
            (TODO: can one control SELECTs inside VIEWs that way? No?)
            (TODO: QB_NAME in CTEs that are used in multiple places?)

            h2. 4. Effect of optimizer hints

            Optimizer can be controlled by
            1. Server variables - optimizer_switch, join_cache_level, etc, etc
            2. Old-style hints
            3. New-style hints

            Old-style hints did not overlap with server variable settings.

            New-style hints are more specific than server variable settings, so they override the server variable settings.

            Should new-style hints override old-style hints? TODO.

            Hints are "narrowly interpreted" and "best effort" - if a hint dictates to do something, like
            {code:sql}
            SELECT /*+ MRR(t1 t1_index1) */ ... FROM t1 ...
            {code}
            that means:
            {quote}
            When considering a query plan that involves using t1_index1 in a way that one can use MRR, use MRR.
            {quote}
            if the query planning is such that use of {{t1_index1}} doesn't allow to use MRR, it won't be used.
            The optimizer may also consider using {{t1_index2}} and pick that over using {{t1_index1}}.
            In such cases the hint is effectively ignored and no warning is given.

            h2. 5. List of hints

            h2. 5.1 NO_RANGE_OPTIMIZATION hint

            It's an index-level hint that disables range optimization for certain index(es):
            {code:sql}
            SELECT /*+ NO_RANGE_OPTIMIZATION(tbl index1 index2) */ * FROM tbl ...
            {code}

            h2. 5.2 NO_ICP hint
            It's an index-level hint that disables Index Condition Pushdown for the indexes. ICP+BKA is disabled as well.
            {code:sql}
            SELECT /*+ NO_ICP(tbl index1 index2) */ * FROM tbl ...
            {code}

            h3. MRR and NO_MRR hints
            .
            This is a self-contained description of Optimizer Hints in MariaDB, whatever is already implemented in the current patch.

            h1. Optimizer hints in MariaDB

            h2. 1. Hint syntax
            Hints are placed after the main statement verb

            {code:sql}
            UPDATE /*+ hints */ table ...;
            DELETE /*+ hints */ FROM table... ;
            SELECT /*+ hints */ ...
            {code}

            or after the SELECT keyword in any subquery:
            {code:sql}
            SELECT * FROM t1 WHERE a IN (SELECT /*+ hints */ ...)
            {code}

            There can be one or more hints separated with space
            {code}
              hints: hint hint ...
            {code}

            Each individual hint is hint name and arguments. In case there are no arguments,
            the () brackets are still present:

            {code}
            hint: hint_name([arguments])
            {code}

            Incorrect hints produce warnings. (TODO any thing else?)
            Hints that are not ignored are kept in the query text (you can see them in SHOW PROCESSLIST, Slow Query Log, EXPLAIN EXTENDED)
            Hints that were incorrect and were ignored are removed from there.

            h2. 2. Hint hierarchy

            h3. 2.1 Index-level hints
            Index-level hints apply to index(es).
            The syntax is
            {code}
            hint_name(table_name [index_name [, index_name] ...])
            {code}

            where table_name may be query_block@table_name.

            (TODO: MySQL also supports hint_name(@query_block_name tbl_name) ? But we don't? )
             
            h2. 3. Query block naming: QB_NAME hint

            QB_NAME hint is used to assign a name to the query block the hint is in. The Query Block is either a SELECT or a top-level construct of UPDATE or DELETE statement.

            {code:sql}
            SELECT /*+ QB_NAME(foo) */ select_list FROM ...
            {code}

            The name can later be used
            * to refer to a query block, where required
            * to refer to a table as {{table_name@query_block_name}}.

            Hints inside VIEWs are not supported, yet.

            Besides the given name, any query block is given a name {{select#n}}, so one can refer to it like so:
            {code:sql}
            SELECT /*+ BKA(tbl1@`select#1`) */ 1 FROM tbl1 ...;
            {code}
            (TODO: can one control SELECTs inside VIEWs that way? No?)
            (TODO: QB_NAME in CTEs that are used in multiple places?)

            h2. 4. Effect of optimizer hints

            Optimizer can be controlled by
            1. Server variables - optimizer_switch, join_cache_level, etc, etc
            2. Old-style hints
            3. New-style hints

            Old-style hints did not overlap with server variable settings.

            New-style hints are more specific than server variable settings, so they override the server variable settings.

            Should new-style hints override old-style hints? TODO.

            Hints are "narrowly interpreted" and "best effort" - if a hint dictates to do something, like
            {code:sql}
            SELECT /*+ MRR(t1 t1_index1) */ ... FROM t1 ...
            {code}
            that means:
            {quote}
            When considering a query plan that involves using t1_index1 in a way that one can use MRR, use MRR.
            {quote}
            if the query planning is such that use of {{t1_index1}} doesn't allow to use MRR, it won't be used.
            The optimizer may also consider using {{t1_index2}} and pick that over using {{t1_index1}}.
            In such cases the hint is effectively ignored and no warning is given.
            Examples: [^mdev35483-mrr-is-narrow.sql]

            h2. 5. List of hints

            h2. 5.1 NO_RANGE_OPTIMIZATION hint

            It's an index-level hint that disables range optimization for certain index(es):
            {code:sql}
            SELECT /*+ NO_RANGE_OPTIMIZATION(tbl index1 index2) */ * FROM tbl ...
            {code}

            h2. 5.2 NO_ICP hint
            It's an index-level hint that disables Index Condition Pushdown for the indexes. ICP+BKA is disabled as well.
            {code:sql}
            SELECT /*+ NO_ICP(tbl index1 index2) */ * FROM tbl ...
            {code}

            h3. MRR and NO_MRR hints
            .
            psergei Sergei Petrunia made changes -
            Description This is a self-contained description of Optimizer Hints in MariaDB, whatever is already implemented in the current patch.

            h1. Optimizer hints in MariaDB

            h2. 1. Hint syntax
            Hints are placed after the main statement verb

            {code:sql}
            UPDATE /*+ hints */ table ...;
            DELETE /*+ hints */ FROM table... ;
            SELECT /*+ hints */ ...
            {code}

            or after the SELECT keyword in any subquery:
            {code:sql}
            SELECT * FROM t1 WHERE a IN (SELECT /*+ hints */ ...)
            {code}

            There can be one or more hints separated with space
            {code}
              hints: hint hint ...
            {code}

            Each individual hint is hint name and arguments. In case there are no arguments,
            the () brackets are still present:

            {code}
            hint: hint_name([arguments])
            {code}

            Incorrect hints produce warnings. (TODO any thing else?)
            Hints that are not ignored are kept in the query text (you can see them in SHOW PROCESSLIST, Slow Query Log, EXPLAIN EXTENDED)
            Hints that were incorrect and were ignored are removed from there.

            h2. 2. Hint hierarchy

            h3. 2.1 Index-level hints
            Index-level hints apply to index(es).
            The syntax is
            {code}
            hint_name(table_name [index_name [, index_name] ...])
            {code}

            where table_name may be query_block@table_name.

            (TODO: MySQL also supports hint_name(@query_block_name tbl_name) ? But we don't? )
             
            h2. 3. Query block naming: QB_NAME hint

            QB_NAME hint is used to assign a name to the query block the hint is in. The Query Block is either a SELECT or a top-level construct of UPDATE or DELETE statement.

            {code:sql}
            SELECT /*+ QB_NAME(foo) */ select_list FROM ...
            {code}

            The name can later be used
            * to refer to a query block, where required
            * to refer to a table as {{table_name@query_block_name}}.

            Hints inside VIEWs are not supported, yet.

            Besides the given name, any query block is given a name {{select#n}}, so one can refer to it like so:
            {code:sql}
            SELECT /*+ BKA(tbl1@`select#1`) */ 1 FROM tbl1 ...;
            {code}
            (TODO: can one control SELECTs inside VIEWs that way? No?)
            (TODO: QB_NAME in CTEs that are used in multiple places?)

            h2. 4. Effect of optimizer hints

            Optimizer can be controlled by
            1. Server variables - optimizer_switch, join_cache_level, etc, etc
            2. Old-style hints
            3. New-style hints

            Old-style hints did not overlap with server variable settings.

            New-style hints are more specific than server variable settings, so they override the server variable settings.

            Should new-style hints override old-style hints? TODO.

            Hints are "narrowly interpreted" and "best effort" - if a hint dictates to do something, like
            {code:sql}
            SELECT /*+ MRR(t1 t1_index1) */ ... FROM t1 ...
            {code}
            that means:
            {quote}
            When considering a query plan that involves using t1_index1 in a way that one can use MRR, use MRR.
            {quote}
            if the query planning is such that use of {{t1_index1}} doesn't allow to use MRR, it won't be used.
            The optimizer may also consider using {{t1_index2}} and pick that over using {{t1_index1}}.
            In such cases the hint is effectively ignored and no warning is given.
            Examples: [^mdev35483-mrr-is-narrow.sql]

            h2. 5. List of hints

            h2. 5.1 NO_RANGE_OPTIMIZATION hint

            It's an index-level hint that disables range optimization for certain index(es):
            {code:sql}
            SELECT /*+ NO_RANGE_OPTIMIZATION(tbl index1 index2) */ * FROM tbl ...
            {code}

            h2. 5.2 NO_ICP hint
            It's an index-level hint that disables Index Condition Pushdown for the indexes. ICP+BKA is disabled as well.
            {code:sql}
            SELECT /*+ NO_ICP(tbl index1 index2) */ * FROM tbl ...
            {code}

            h3. MRR and NO_MRR hints
            .
            This is a self-contained description of Optimizer Hints in MariaDB, whatever is already implemented in the current patch.

            h1. Optimizer hints in MariaDB

            h2. 1. Hint syntax
            Hints are placed after the main statement verb

            {code:sql}
            UPDATE /*+ hints */ table ...;
            DELETE /*+ hints */ FROM table... ;
            SELECT /*+ hints */ ...
            {code}

            or after the SELECT keyword in any subquery:
            {code:sql}
            SELECT * FROM t1 WHERE a IN (SELECT /*+ hints */ ...)
            {code}

            There can be one or more hints separated with space
            {code}
              hints: hint hint ...
            {code}

            Each individual hint is hint name and arguments. In case there are no arguments,
            the () brackets are still present:

            {code}
            hint: hint_name([arguments])
            {code}

            Incorrect hints produce warnings. (TODO any thing else?)
            Hints that are not ignored are kept in the query text (you can see them in SHOW PROCESSLIST, Slow Query Log, EXPLAIN EXTENDED)
            Hints that were incorrect and were ignored are removed from there.

            h2. 2. Hint hierarchy

            h3. 2.1 Index-level hints
            Index-level hints apply to index(es).
            The syntax is
            {code}
            hint_name(table_name [index_name [, index_name] ...])
            {code}

            where table_name may be query_block@table_name.

            (TODO: MySQL also supports hint_name(@query_block_name tbl_name) ? But we don't? )
             
            h2. 3. Query block naming: QB_NAME hint

            QB_NAME hint is used to assign a name to the query block the hint is in. The Query Block is either a SELECT or a top-level construct of UPDATE or DELETE statement.

            {code:sql}
            SELECT /*+ QB_NAME(foo) */ select_list FROM ...
            {code}

            The name can later be used
            * to refer to a query block, where required
            * to refer to a table as {{table_name@query_block_name}}.

            Hints inside VIEWs are not supported, yet.

            Besides the given name, any query block is given a name {{select#n}}, so one can refer to it like so:
            {code:sql}
            SELECT /*+ BKA(tbl1@`select#1`) */ 1 FROM tbl1 ...;
            {code}
            (TODO: can one control SELECTs inside VIEWs that way? No?)
            (TODO: QB_NAME in CTEs that are used in multiple places?)

            h2. 4. Effect of optimizer hints

            Optimizer can be controlled by
            1. Server variables - optimizer_switch, join_cache_level, etc, etc
            2. Old-style hints
            3. New-style hints

            Old-style hints did not overlap with server variable settings.

            New-style hints are more specific than server variable settings, so they override the server variable settings.

            Should new-style hints override old-style hints? TODO.

            Hints are "narrowly interpreted" and "best effort" - if a hint dictates to do something, like
            {code:sql}
            SELECT /*+ MRR(t1 t1_index1) */ ... FROM t1 ...
            {code}
            that means:
            {quote}
            When considering a query plan that involves using t1_index1 in a way that one can use MRR, use MRR.
            {quote}
            if the query planning is such that use of {{t1_index1}} doesn't allow to use MRR, it won't be used.
            The optimizer may also consider using {{t1_index2}} and pick that over using {{t1_index1}}.
            In such cases the hint is effectively ignored and no warning is given.
            Examples: [^mdev35483-mrr-is-narrow.sql]

            h2. 5. List of hints

            h2. 5.1 NO_RANGE_OPTIMIZATION hint

            It's an index-level hint that disables range optimization for certain index(es):
            {code:sql}
            SELECT /*+ NO_RANGE_OPTIMIZATION(tbl index1 index2) */ * FROM tbl ...
            {code}

            h2. 5.2 NO_ICP hint
            It's an index-level hint that disables Index Condition Pushdown for the indexes. ICP+BKA is disabled as well.
            {code:sql}
            SELECT /*+ NO_ICP(tbl index1 index2) */ * FROM tbl ...
            {code}

            h3. MRR and NO_MRR hints

            {code:sql}
            SELECT /*+ MRR(tbl index1 index2) */ * FROM tbl ...
            SELECT /*+ NO_MRR(tbl index1 index2) */ * FROM tbl ...
            {code}


            psergei Sergei Petrunia made changes -
            Description This is a self-contained description of Optimizer Hints in MariaDB, whatever is already implemented in the current patch.

            h1. Optimizer hints in MariaDB

            h2. 1. Hint syntax
            Hints are placed after the main statement verb

            {code:sql}
            UPDATE /*+ hints */ table ...;
            DELETE /*+ hints */ FROM table... ;
            SELECT /*+ hints */ ...
            {code}

            or after the SELECT keyword in any subquery:
            {code:sql}
            SELECT * FROM t1 WHERE a IN (SELECT /*+ hints */ ...)
            {code}

            There can be one or more hints separated with space
            {code}
              hints: hint hint ...
            {code}

            Each individual hint is hint name and arguments. In case there are no arguments,
            the () brackets are still present:

            {code}
            hint: hint_name([arguments])
            {code}

            Incorrect hints produce warnings. (TODO any thing else?)
            Hints that are not ignored are kept in the query text (you can see them in SHOW PROCESSLIST, Slow Query Log, EXPLAIN EXTENDED)
            Hints that were incorrect and were ignored are removed from there.

            h2. 2. Hint hierarchy

            h3. 2.1 Index-level hints
            Index-level hints apply to index(es).
            The syntax is
            {code}
            hint_name(table_name [index_name [, index_name] ...])
            {code}

            where table_name may be query_block@table_name.

            (TODO: MySQL also supports hint_name(@query_block_name tbl_name) ? But we don't? )
             
            h2. 3. Query block naming: QB_NAME hint

            QB_NAME hint is used to assign a name to the query block the hint is in. The Query Block is either a SELECT or a top-level construct of UPDATE or DELETE statement.

            {code:sql}
            SELECT /*+ QB_NAME(foo) */ select_list FROM ...
            {code}

            The name can later be used
            * to refer to a query block, where required
            * to refer to a table as {{table_name@query_block_name}}.

            Hints inside VIEWs are not supported, yet.

            Besides the given name, any query block is given a name {{select#n}}, so one can refer to it like so:
            {code:sql}
            SELECT /*+ BKA(tbl1@`select#1`) */ 1 FROM tbl1 ...;
            {code}
            (TODO: can one control SELECTs inside VIEWs that way? No?)
            (TODO: QB_NAME in CTEs that are used in multiple places?)

            h2. 4. Effect of optimizer hints

            Optimizer can be controlled by
            1. Server variables - optimizer_switch, join_cache_level, etc, etc
            2. Old-style hints
            3. New-style hints

            Old-style hints did not overlap with server variable settings.

            New-style hints are more specific than server variable settings, so they override the server variable settings.

            Should new-style hints override old-style hints? TODO.

            Hints are "narrowly interpreted" and "best effort" - if a hint dictates to do something, like
            {code:sql}
            SELECT /*+ MRR(t1 t1_index1) */ ... FROM t1 ...
            {code}
            that means:
            {quote}
            When considering a query plan that involves using t1_index1 in a way that one can use MRR, use MRR.
            {quote}
            if the query planning is such that use of {{t1_index1}} doesn't allow to use MRR, it won't be used.
            The optimizer may also consider using {{t1_index2}} and pick that over using {{t1_index1}}.
            In such cases the hint is effectively ignored and no warning is given.
            Examples: [^mdev35483-mrr-is-narrow.sql]

            h2. 5. List of hints

            h2. 5.1 NO_RANGE_OPTIMIZATION hint

            It's an index-level hint that disables range optimization for certain index(es):
            {code:sql}
            SELECT /*+ NO_RANGE_OPTIMIZATION(tbl index1 index2) */ * FROM tbl ...
            {code}

            h2. 5.2 NO_ICP hint
            It's an index-level hint that disables Index Condition Pushdown for the indexes. ICP+BKA is disabled as well.
            {code:sql}
            SELECT /*+ NO_ICP(tbl index1 index2) */ * FROM tbl ...
            {code}

            h3. MRR and NO_MRR hints

            {code:sql}
            SELECT /*+ MRR(tbl index1 index2) */ * FROM tbl ...
            SELECT /*+ NO_MRR(tbl index1 index2) */ * FROM tbl ...
            {code}


            This is a self-contained description of Optimizer Hints in MariaDB, whatever is already implemented in the current patch.

            h1. Optimizer hints in MariaDB

            h2. 1. Hint syntax
            Hints are placed after the main statement verb

            {code:sql}
            UPDATE /*+ hints */ table ...;
            DELETE /*+ hints */ FROM table... ;
            SELECT /*+ hints */ ...
            {code}

            or after the SELECT keyword in any subquery:
            {code:sql}
            SELECT * FROM t1 WHERE a IN (SELECT /*+ hints */ ...)
            {code}

            There can be one or more hints separated with space
            {code}
              hints: hint hint ...
            {code}

            Each individual hint is hint name and arguments. In case there are no arguments,
            the () brackets are still present:

            {code}
            hint: hint_name([arguments])
            {code}

            Incorrect hints produce warnings. (TODO any thing else?)
            Hints that are not ignored are kept in the query text (you can see them in SHOW PROCESSLIST, Slow Query Log, EXPLAIN EXTENDED)
            Hints that were incorrect and were ignored are removed from there.

            h2. 2. Hint hierarchy

            h3. 2.1 Index-level hints
            Index-level hints apply to index(es).
            The syntax is
            {code}
            hint_name(table_name [index_name [, index_name] ...])
            {code}

            where table_name may be query_block@table_name.

            (TODO: MySQL also supports hint_name(@query_block_name tbl_name) ? But we don't? )
             
            h2. 3. Query block naming: QB_NAME hint

            QB_NAME hint is used to assign a name to the query block the hint is in. The Query Block is either a SELECT or a top-level construct of UPDATE or DELETE statement.

            {code:sql}
            SELECT /*+ QB_NAME(foo) */ select_list FROM ...
            {code}

            The name can later be used
            * to refer to a query block, where required
            * to refer to a table as {{table_name@query_block_name}}.

            Hints inside VIEWs are not supported, yet.

            Besides the given name, any query block is given a name {{select#n}}, so one can refer to it like so:
            {code:sql}
            SELECT /*+ BKA(tbl1@`select#1`) */ 1 FROM tbl1 ...;
            {code}
            (TODO: can one control SELECTs inside VIEWs that way? No?)
            (TODO: QB_NAME in CTEs that are used in multiple places?)

            h2. 4. Effect of optimizer hints

            Optimizer can be controlled by
            1. Server variables - optimizer_switch, join_cache_level, etc, etc
            2. Old-style hints
            3. New-style hints

            Old-style hints did not overlap with server variable settings.

            New-style hints are more specific than server variable settings, so they override the server variable settings.

            Should new-style hints override old-style hints? TODO.

            Hints are "narrowly interpreted" and "best effort" - if a hint dictates to do something, like
            {code:sql}
            SELECT /*+ MRR(t1 t1_index1) */ ... FROM t1 ...
            {code}
            that means:
            {quote}
            When considering a query plan that involves using t1_index1 in a way that one can use MRR, use MRR.
            {quote}
            if the query planning is such that use of {{t1_index1}} doesn't allow to use MRR, it won't be used.
            The optimizer may also consider using {{t1_index2}} and pick that over using {{t1_index1}}.
            In such cases the hint is effectively ignored and no warning is given.
            Examples: [^mdev35483-mrr-is-narrow.sql]

            h2. 5. List of hints

            h2. 5.1 NO_RANGE_OPTIMIZATION hint

            It's an index-level hint that disables range optimization for certain index(es):
            {code:sql}
            SELECT /*+ NO_RANGE_OPTIMIZATION(tbl index1 index2) */ * FROM tbl ...
            {code}

            h2. 5.2 NO_ICP hint
            It's an index-level hint that disables Index Condition Pushdown for the indexes. ICP+BKA is disabled as well.
            {code:sql}
            SELECT /*+ NO_ICP(tbl index1 index2) */ * FROM tbl ...
            {code}

            h3. MRR and NO_MRR hints

            Index-level hint to force or disable use of MRR.

            {code:sql}
            SELECT /*+ MRR(tbl index1 index2) */ * FROM tbl ...
            SELECT /*+ NO_MRR(tbl index1 index2) */ * FROM tbl ...
            {code}


            psergei Sergei Petrunia made changes -
            Description This is a self-contained description of Optimizer Hints in MariaDB, whatever is already implemented in the current patch.

            h1. Optimizer hints in MariaDB

            h2. 1. Hint syntax
            Hints are placed after the main statement verb

            {code:sql}
            UPDATE /*+ hints */ table ...;
            DELETE /*+ hints */ FROM table... ;
            SELECT /*+ hints */ ...
            {code}

            or after the SELECT keyword in any subquery:
            {code:sql}
            SELECT * FROM t1 WHERE a IN (SELECT /*+ hints */ ...)
            {code}

            There can be one or more hints separated with space
            {code}
              hints: hint hint ...
            {code}

            Each individual hint is hint name and arguments. In case there are no arguments,
            the () brackets are still present:

            {code}
            hint: hint_name([arguments])
            {code}

            Incorrect hints produce warnings. (TODO any thing else?)
            Hints that are not ignored are kept in the query text (you can see them in SHOW PROCESSLIST, Slow Query Log, EXPLAIN EXTENDED)
            Hints that were incorrect and were ignored are removed from there.

            h2. 2. Hint hierarchy

            h3. 2.1 Index-level hints
            Index-level hints apply to index(es).
            The syntax is
            {code}
            hint_name(table_name [index_name [, index_name] ...])
            {code}

            where table_name may be query_block@table_name.

            (TODO: MySQL also supports hint_name(@query_block_name tbl_name) ? But we don't? )
             
            h2. 3. Query block naming: QB_NAME hint

            QB_NAME hint is used to assign a name to the query block the hint is in. The Query Block is either a SELECT or a top-level construct of UPDATE or DELETE statement.

            {code:sql}
            SELECT /*+ QB_NAME(foo) */ select_list FROM ...
            {code}

            The name can later be used
            * to refer to a query block, where required
            * to refer to a table as {{table_name@query_block_name}}.

            Hints inside VIEWs are not supported, yet.

            Besides the given name, any query block is given a name {{select#n}}, so one can refer to it like so:
            {code:sql}
            SELECT /*+ BKA(tbl1@`select#1`) */ 1 FROM tbl1 ...;
            {code}
            (TODO: can one control SELECTs inside VIEWs that way? No?)
            (TODO: QB_NAME in CTEs that are used in multiple places?)

            h2. 4. Effect of optimizer hints

            Optimizer can be controlled by
            1. Server variables - optimizer_switch, join_cache_level, etc, etc
            2. Old-style hints
            3. New-style hints

            Old-style hints did not overlap with server variable settings.

            New-style hints are more specific than server variable settings, so they override the server variable settings.

            Should new-style hints override old-style hints? TODO.

            Hints are "narrowly interpreted" and "best effort" - if a hint dictates to do something, like
            {code:sql}
            SELECT /*+ MRR(t1 t1_index1) */ ... FROM t1 ...
            {code}
            that means:
            {quote}
            When considering a query plan that involves using t1_index1 in a way that one can use MRR, use MRR.
            {quote}
            if the query planning is such that use of {{t1_index1}} doesn't allow to use MRR, it won't be used.
            The optimizer may also consider using {{t1_index2}} and pick that over using {{t1_index1}}.
            In such cases the hint is effectively ignored and no warning is given.
            Examples: [^mdev35483-mrr-is-narrow.sql]

            h2. 5. List of hints

            h2. 5.1 NO_RANGE_OPTIMIZATION hint

            It's an index-level hint that disables range optimization for certain index(es):
            {code:sql}
            SELECT /*+ NO_RANGE_OPTIMIZATION(tbl index1 index2) */ * FROM tbl ...
            {code}

            h2. 5.2 NO_ICP hint
            It's an index-level hint that disables Index Condition Pushdown for the indexes. ICP+BKA is disabled as well.
            {code:sql}
            SELECT /*+ NO_ICP(tbl index1 index2) */ * FROM tbl ...
            {code}

            h3. MRR and NO_MRR hints

            Index-level hint to force or disable use of MRR.

            {code:sql}
            SELECT /*+ MRR(tbl index1 index2) */ * FROM tbl ...
            SELECT /*+ NO_MRR(tbl index1 index2) */ * FROM tbl ...
            {code}


            This is a self-contained description of Optimizer Hints in MariaDB, whatever is already implemented in the current patch.

            h1. Optimizer hints in MariaDB

            h2. 1. Hint syntax
            Hints are placed after the main statement verb

            {code:sql}
            UPDATE /*+ hints */ table ...;
            DELETE /*+ hints */ FROM table... ;
            SELECT /*+ hints */ ...
            {code}

            or after the SELECT keyword in any subquery:
            {code:sql}
            SELECT * FROM t1 WHERE a IN (SELECT /*+ hints */ ...)
            {code}

            There can be one or more hints separated with space
            {code}
              hints: hint hint ...
            {code}

            Each individual hint is hint name and arguments. In case there are no arguments,
            the () brackets are still present:

            {code}
            hint: hint_name([arguments])
            {code}

            Incorrect hints produce warnings. (TODO any thing else?)
            Hints that are not ignored are kept in the query text (you can see them in SHOW PROCESSLIST, Slow Query Log, EXPLAIN EXTENDED)
            Hints that were incorrect and were ignored are removed from there.

            h2. 2. Hint hierarchy

            h3. 2.1 Index-level hints
            Index-level hints apply to index(es).
            The syntax is
            {code}
            hint_name(table_name [index_name [, index_name] ...])
            {code}

            where table_name may be query_block@table_name.

            (TODO: MySQL also supports hint_name(@query_block_name tbl_name) ? But we don't? )
             
            h2. 3. Query block naming: QB_NAME hint

            QB_NAME hint is used to assign a name to the query block the hint is in. The Query Block is either a SELECT or a top-level construct of UPDATE or DELETE statement.

            {code:sql}
            SELECT /*+ QB_NAME(foo) */ select_list FROM ...
            {code}

            The name can later be used
            * to refer to a query block, where required
            * to refer to a table as {{table_name@query_block_name}}.

            Hints inside VIEWs are not supported, yet.

            Besides the given name, any query block is given a name {{select#n}}, so one can refer to it like so:
            {code:sql}
            SELECT /*+ BKA(tbl1@`select#1`) */ 1 FROM tbl1 ...;
            {code}
            (TODO: can one control SELECTs inside VIEWs that way? No?)
            (TODO: QB_NAME in CTEs that are used in multiple places?)

            h2. 4. Effect of optimizer hints

            Optimizer can be controlled by
            1. Server variables - optimizer_switch, join_cache_level, etc, etc
            2. Old-style hints
            3. New-style hints

            Old-style hints did not overlap with server variable settings.

            New-style hints are more specific than server variable settings, so they override the server variable settings.

            Should new-style hints override old-style hints? TODO.

            Hints are "narrowly interpreted" and "best effort" - if a hint dictates to do something, like
            {code:sql}
            SELECT /*+ MRR(t1 t1_index1) */ ... FROM t1 ...
            {code}
            that means:
            {quote}
            When considering a query plan that involves using t1_index1 in a way that one can use MRR, use MRR.
            {quote}
            if the query planning is such that use of {{t1_index1}} doesn't allow to use MRR, it won't be used.
            The optimizer may also consider using {{t1_index2}} and pick that over using {{t1_index1}}.
            In such cases the hint is effectively ignored and no warning is given.
            Examples: [^mdev35483-mrr-is-narrow.sql]

            h2. 5. List of hints

            h2. 5.1 NO_RANGE_OPTIMIZATION hint

            It's an index-level hint that disables range optimization for certain index(es):
            {code:sql}
            SELECT /*+ NO_RANGE_OPTIMIZATION(tbl index1 index2) */ * FROM tbl ...
            {code}

            h2. 5.2 NO_ICP hint
            It's an index-level hint that disables Index Condition Pushdown for the indexes. ICP+BKA is disabled as well.
            {code:sql}
            SELECT /*+ NO_ICP(tbl index1 index2) */ * FROM tbl ...
            {code}

            h3. MRR and NO_MRR hints

            Index-level hint to force or disable use of MRR.

            {code:sql}
            SELECT /*+ MRR(tbl index1 index2) */ * FROM tbl ...
            SELECT /*+ NO_MRR(tbl index1 index2) */ * FROM tbl ...
            {code}
            This controls MRR optimization for range access ( [^mdev35483-mrr-is-narrow.sql]

            psergei Sergei Petrunia made changes -
            Description This is a self-contained description of Optimizer Hints in MariaDB, whatever is already implemented in the current patch.

            h1. Optimizer hints in MariaDB

            h2. 1. Hint syntax
            Hints are placed after the main statement verb

            {code:sql}
            UPDATE /*+ hints */ table ...;
            DELETE /*+ hints */ FROM table... ;
            SELECT /*+ hints */ ...
            {code}

            or after the SELECT keyword in any subquery:
            {code:sql}
            SELECT * FROM t1 WHERE a IN (SELECT /*+ hints */ ...)
            {code}

            There can be one or more hints separated with space
            {code}
              hints: hint hint ...
            {code}

            Each individual hint is hint name and arguments. In case there are no arguments,
            the () brackets are still present:

            {code}
            hint: hint_name([arguments])
            {code}

            Incorrect hints produce warnings. (TODO any thing else?)
            Hints that are not ignored are kept in the query text (you can see them in SHOW PROCESSLIST, Slow Query Log, EXPLAIN EXTENDED)
            Hints that were incorrect and were ignored are removed from there.

            h2. 2. Hint hierarchy

            h3. 2.1 Index-level hints
            Index-level hints apply to index(es).
            The syntax is
            {code}
            hint_name(table_name [index_name [, index_name] ...])
            {code}

            where table_name may be query_block@table_name.

            (TODO: MySQL also supports hint_name(@query_block_name tbl_name) ? But we don't? )
             
            h2. 3. Query block naming: QB_NAME hint

            QB_NAME hint is used to assign a name to the query block the hint is in. The Query Block is either a SELECT or a top-level construct of UPDATE or DELETE statement.

            {code:sql}
            SELECT /*+ QB_NAME(foo) */ select_list FROM ...
            {code}

            The name can later be used
            * to refer to a query block, where required
            * to refer to a table as {{table_name@query_block_name}}.

            Hints inside VIEWs are not supported, yet.

            Besides the given name, any query block is given a name {{select#n}}, so one can refer to it like so:
            {code:sql}
            SELECT /*+ BKA(tbl1@`select#1`) */ 1 FROM tbl1 ...;
            {code}
            (TODO: can one control SELECTs inside VIEWs that way? No?)
            (TODO: QB_NAME in CTEs that are used in multiple places?)

            h2. 4. Effect of optimizer hints

            Optimizer can be controlled by
            1. Server variables - optimizer_switch, join_cache_level, etc, etc
            2. Old-style hints
            3. New-style hints

            Old-style hints did not overlap with server variable settings.

            New-style hints are more specific than server variable settings, so they override the server variable settings.

            Should new-style hints override old-style hints? TODO.

            Hints are "narrowly interpreted" and "best effort" - if a hint dictates to do something, like
            {code:sql}
            SELECT /*+ MRR(t1 t1_index1) */ ... FROM t1 ...
            {code}
            that means:
            {quote}
            When considering a query plan that involves using t1_index1 in a way that one can use MRR, use MRR.
            {quote}
            if the query planning is such that use of {{t1_index1}} doesn't allow to use MRR, it won't be used.
            The optimizer may also consider using {{t1_index2}} and pick that over using {{t1_index1}}.
            In such cases the hint is effectively ignored and no warning is given.
            Examples: [^mdev35483-mrr-is-narrow.sql]

            h2. 5. List of hints

            h2. 5.1 NO_RANGE_OPTIMIZATION hint

            It's an index-level hint that disables range optimization for certain index(es):
            {code:sql}
            SELECT /*+ NO_RANGE_OPTIMIZATION(tbl index1 index2) */ * FROM tbl ...
            {code}

            h2. 5.2 NO_ICP hint
            It's an index-level hint that disables Index Condition Pushdown for the indexes. ICP+BKA is disabled as well.
            {code:sql}
            SELECT /*+ NO_ICP(tbl index1 index2) */ * FROM tbl ...
            {code}

            h3. MRR and NO_MRR hints

            Index-level hint to force or disable use of MRR.

            {code:sql}
            SELECT /*+ MRR(tbl index1 index2) */ * FROM tbl ...
            SELECT /*+ NO_MRR(tbl index1 index2) */ * FROM tbl ...
            {code}
            This controls MRR optimization for range access ( [^mdev35483-mrr-is-narrow.sql]

            This is a self-contained description of Optimizer Hints in MariaDB, whatever is already implemented in the current patch.

            h1. Optimizer hints in MariaDB

            h2. 1. Hint syntax
            Hints are placed after the main statement verb

            {code:sql}
            UPDATE /*+ hints */ table ...;
            DELETE /*+ hints */ FROM table... ;
            SELECT /*+ hints */ ...
            {code}

            or after the SELECT keyword in any subquery:
            {code:sql}
            SELECT * FROM t1 WHERE a IN (SELECT /*+ hints */ ...)
            {code}

            There can be one or more hints separated with space
            {code}
              hints: hint hint ...
            {code}

            Each individual hint is hint name and arguments. In case there are no arguments,
            the () brackets are still present:

            {code}
            hint: hint_name([arguments])
            {code}

            Incorrect hints produce warnings. (TODO any thing else?)
            Hints that are not ignored are kept in the query text (you can see them in SHOW PROCESSLIST, Slow Query Log, EXPLAIN EXTENDED)
            Hints that were incorrect and were ignored are removed from there.

            h2. 2. Hint hierarchy

            h3. 2.1 Index-level hints
            Index-level hints apply to index(es).
            The syntax is
            {code}
            hint_name(table_name [index_name [, index_name] ...])
            {code}

            where table_name may be query_block@table_name.

            (TODO: MySQL also supports hint_name(@query_block_name tbl_name) ? But we don't? )
             
            h2. 3. Query block naming: QB_NAME hint

            QB_NAME hint is used to assign a name to the query block the hint is in. The Query Block is either a SELECT or a top-level construct of UPDATE or DELETE statement.

            {code:sql}
            SELECT /*+ QB_NAME(foo) */ select_list FROM ...
            {code}

            The name can later be used
            * to refer to a query block, where required
            * to refer to a table as {{table_name@query_block_name}}.

            Hints inside VIEWs are not supported, yet.

            Besides the given name, any query block is given a name {{select#n}}, so one can refer to it like so:
            {code:sql}
            SELECT /*+ BKA(tbl1@`select#1`) */ 1 FROM tbl1 ...;
            {code}
            (TODO: can one control SELECTs inside VIEWs that way? No?)
            (TODO: QB_NAME in CTEs that are used in multiple places?)

            h2. 4. Effect of optimizer hints

            Optimizer can be controlled by
            1. Server variables - optimizer_switch, join_cache_level, etc, etc
            2. Old-style hints
            3. New-style hints

            Old-style hints did not overlap with server variable settings.

            New-style hints are more specific than server variable settings, so they override the server variable settings.

            Should new-style hints override old-style hints? TODO.

            Hints are "narrowly interpreted" and "best effort" - if a hint dictates to do something, like
            {code:sql}
            SELECT /*+ MRR(t1 t1_index1) */ ... FROM t1 ...
            {code}
            that means:
            {quote}
            When considering a query plan that involves using t1_index1 in a way that one can use MRR, use MRR.
            {quote}
            if the query planning is such that use of {{t1_index1}} doesn't allow to use MRR, it won't be used.
            The optimizer may also consider using {{t1_index2}} and pick that over using {{t1_index1}}.
            In such cases the hint is effectively ignored and no warning is given.
            Examples: [^mdev35483-mrr-is-narrow.sql]

            h2. 5. List of hints

            h2. 5.1 NO_RANGE_OPTIMIZATION hint

            It's an index-level hint that disables range optimization for certain index(es):
            {code:sql}
            SELECT /*+ NO_RANGE_OPTIMIZATION(tbl index1 index2) */ * FROM tbl ...
            {code}

            h2. 5.2 NO_ICP hint
            It's an index-level hint that disables Index Condition Pushdown for the indexes. ICP+BKA is disabled as well.
            {code:sql}
            SELECT /*+ NO_ICP(tbl index1 index2) */ * FROM tbl ...
            {code}

            h3. MRR and NO_MRR hints

            Index-level hint to force or disable use of MRR.

            {code:sql}
            SELECT /*+ MRR(tbl index1 index2) */ * FROM tbl ...
            SELECT /*+ NO_MRR(tbl index1 index2) */ * FROM tbl ...
            {code}
            This controls
            * MRR optimization for range access ( [^mdev35483-mrr-is-narrow.sql] )
            * BKA

            psergei Sergei Petrunia made changes -
            psergei Sergei Petrunia made changes -
            Description This is a self-contained description of Optimizer Hints in MariaDB, whatever is already implemented in the current patch.

            h1. Optimizer hints in MariaDB

            h2. 1. Hint syntax
            Hints are placed after the main statement verb

            {code:sql}
            UPDATE /*+ hints */ table ...;
            DELETE /*+ hints */ FROM table... ;
            SELECT /*+ hints */ ...
            {code}

            or after the SELECT keyword in any subquery:
            {code:sql}
            SELECT * FROM t1 WHERE a IN (SELECT /*+ hints */ ...)
            {code}

            There can be one or more hints separated with space
            {code}
              hints: hint hint ...
            {code}

            Each individual hint is hint name and arguments. In case there are no arguments,
            the () brackets are still present:

            {code}
            hint: hint_name([arguments])
            {code}

            Incorrect hints produce warnings. (TODO any thing else?)
            Hints that are not ignored are kept in the query text (you can see them in SHOW PROCESSLIST, Slow Query Log, EXPLAIN EXTENDED)
            Hints that were incorrect and were ignored are removed from there.

            h2. 2. Hint hierarchy

            h3. 2.1 Index-level hints
            Index-level hints apply to index(es).
            The syntax is
            {code}
            hint_name(table_name [index_name [, index_name] ...])
            {code}

            where table_name may be query_block@table_name.

            (TODO: MySQL also supports hint_name(@query_block_name tbl_name) ? But we don't? )
             
            h2. 3. Query block naming: QB_NAME hint

            QB_NAME hint is used to assign a name to the query block the hint is in. The Query Block is either a SELECT or a top-level construct of UPDATE or DELETE statement.

            {code:sql}
            SELECT /*+ QB_NAME(foo) */ select_list FROM ...
            {code}

            The name can later be used
            * to refer to a query block, where required
            * to refer to a table as {{table_name@query_block_name}}.

            Hints inside VIEWs are not supported, yet.

            Besides the given name, any query block is given a name {{select#n}}, so one can refer to it like so:
            {code:sql}
            SELECT /*+ BKA(tbl1@`select#1`) */ 1 FROM tbl1 ...;
            {code}
            (TODO: can one control SELECTs inside VIEWs that way? No?)
            (TODO: QB_NAME in CTEs that are used in multiple places?)

            h2. 4. Effect of optimizer hints

            Optimizer can be controlled by
            1. Server variables - optimizer_switch, join_cache_level, etc, etc
            2. Old-style hints
            3. New-style hints

            Old-style hints did not overlap with server variable settings.

            New-style hints are more specific than server variable settings, so they override the server variable settings.

            Should new-style hints override old-style hints? TODO.

            Hints are "narrowly interpreted" and "best effort" - if a hint dictates to do something, like
            {code:sql}
            SELECT /*+ MRR(t1 t1_index1) */ ... FROM t1 ...
            {code}
            that means:
            {quote}
            When considering a query plan that involves using t1_index1 in a way that one can use MRR, use MRR.
            {quote}
            if the query planning is such that use of {{t1_index1}} doesn't allow to use MRR, it won't be used.
            The optimizer may also consider using {{t1_index2}} and pick that over using {{t1_index1}}.
            In such cases the hint is effectively ignored and no warning is given.
            Examples: [^mdev35483-mrr-is-narrow.sql]

            h2. 5. List of hints

            h2. 5.1 NO_RANGE_OPTIMIZATION hint

            It's an index-level hint that disables range optimization for certain index(es):
            {code:sql}
            SELECT /*+ NO_RANGE_OPTIMIZATION(tbl index1 index2) */ * FROM tbl ...
            {code}

            h2. 5.2 NO_ICP hint
            It's an index-level hint that disables Index Condition Pushdown for the indexes. ICP+BKA is disabled as well.
            {code:sql}
            SELECT /*+ NO_ICP(tbl index1 index2) */ * FROM tbl ...
            {code}

            h3. MRR and NO_MRR hints

            Index-level hint to force or disable use of MRR.

            {code:sql}
            SELECT /*+ MRR(tbl index1 index2) */ * FROM tbl ...
            SELECT /*+ NO_MRR(tbl index1 index2) */ * FROM tbl ...
            {code}
            This controls
            * MRR optimization for range access ( [^mdev35483-mrr-is-narrow.sql] )
            * BKA

            This is a self-contained description of Optimizer Hints in MariaDB, whatever is already implemented in the current patch.

            h1. Optimizer hints in MariaDB

            h2. 1. Hint syntax
            Hints are placed after the main statement verb

            {code:sql}
            UPDATE /*+ hints */ table ...;
            DELETE /*+ hints */ FROM table... ;
            SELECT /*+ hints */ ...
            {code}

            or after the SELECT keyword in any subquery:
            {code:sql}
            SELECT * FROM t1 WHERE a IN (SELECT /*+ hints */ ...)
            {code}

            There can be one or more hints separated with space
            {code}
              hints: hint hint ...
            {code}

            Each individual hint is hint name and arguments. In case there are no arguments,
            the () brackets are still present:

            {code}
            hint: hint_name([arguments])
            {code}

            Incorrect hints produce warnings. (TODO any thing else?)
            Hints that are not ignored are kept in the query text (you can see them in SHOW PROCESSLIST, Slow Query Log, EXPLAIN EXTENDED)
            Hints that were incorrect and were ignored are removed from there.

            h2. 2. Hint hierarchy

            h3. 2.1 Index-level hints
            Index-level hints apply to index(es).
            The syntax is
            {code}
            hint_name(table_name [index_name [, index_name] ...])
            {code}

            where table_name may be query_block@table_name.

            (TODO: MySQL also supports hint_name(@query_block_name tbl_name) ? But we don't? )
             
            h2. 3. Query block naming: QB_NAME hint

            QB_NAME hint is used to assign a name to the query block the hint is in. The Query Block is either a SELECT or a top-level construct of UPDATE or DELETE statement.

            {code:sql}
            SELECT /*+ QB_NAME(foo) */ select_list FROM ...
            {code}

            The name can later be used
            * to refer to a query block, where required
            * to refer to a table as {{table_name@query_block_name}}.

            Hints inside VIEWs are not supported, yet.

            Besides the given name, any query block is given a name {{select#n}}, so one can refer to it like so:
            {code:sql}
            SELECT /*+ BKA(tbl1@`select#1`) */ 1 FROM tbl1 ...;
            {code}
            (TODO: can one control SELECTs inside VIEWs that way? No?)
            (TODO: QB_NAME in CTEs that are used in multiple places?)

            h2. 4. Effect of optimizer hints

            Optimizer can be controlled by
            1. Server variables - optimizer_switch, join_cache_level, etc, etc
            2. Old-style hints
            3. New-style hints

            Old-style hints did not overlap with server variable settings.

            New-style hints are more specific than server variable settings, so they override the server variable settings.

            Should new-style hints override old-style hints? TODO.

            Hints are "narrowly interpreted" and "best effort" - if a hint dictates to do something, like
            {code:sql}
            SELECT /*+ MRR(t1 t1_index1) */ ... FROM t1 ...
            {code}
            that means:
            {quote}
            When considering a query plan that involves using t1_index1 in a way that one can use MRR, use MRR.
            {quote}
            if the query planning is such that use of {{t1_index1}} doesn't allow to use MRR, it won't be used.
            The optimizer may also consider using {{t1_index2}} and pick that over using {{t1_index1}}.
            In such cases the hint is effectively ignored and no warning is given.
            Examples: [^mdev35483-mrr-is-narrow.sql]

            h2. 5. List of hints

            h2. 5.1 NO_RANGE_OPTIMIZATION hint

            It's an index-level hint that disables range optimization for certain index(es):
            {code:sql}
            SELECT /*+ NO_RANGE_OPTIMIZATION(tbl index1 index2) */ * FROM tbl ...
            {code}

            h2. 5.2 NO_ICP hint
            It's an index-level hint that disables Index Condition Pushdown for the indexes. ICP+BKA is disabled as well.
            {code:sql}
            SELECT /*+ NO_ICP(tbl index1 index2) */ * FROM tbl ...
            {code}

            h3. MRR and NO_MRR hints

            Index-level hint to force or disable use of MRR.

            {code:sql}
            SELECT /*+ MRR(tbl index1 index2) */ * FROM tbl ...
            SELECT /*+ NO_MRR(tbl index1 index2) */ * FROM tbl ...
            {code}
            This controls
            * MRR optimization for range access ( [^mdev35483-mrr-is-narrow.sql] )
            * BKA [^mdev35483-mrr-controls-bka-partially.sql]

            psergei Sergei Petrunia made changes -
            Description This is a self-contained description of Optimizer Hints in MariaDB, whatever is already implemented in the current patch.

            h1. Optimizer hints in MariaDB

            h2. 1. Hint syntax
            Hints are placed after the main statement verb

            {code:sql}
            UPDATE /*+ hints */ table ...;
            DELETE /*+ hints */ FROM table... ;
            SELECT /*+ hints */ ...
            {code}

            or after the SELECT keyword in any subquery:
            {code:sql}
            SELECT * FROM t1 WHERE a IN (SELECT /*+ hints */ ...)
            {code}

            There can be one or more hints separated with space
            {code}
              hints: hint hint ...
            {code}

            Each individual hint is hint name and arguments. In case there are no arguments,
            the () brackets are still present:

            {code}
            hint: hint_name([arguments])
            {code}

            Incorrect hints produce warnings. (TODO any thing else?)
            Hints that are not ignored are kept in the query text (you can see them in SHOW PROCESSLIST, Slow Query Log, EXPLAIN EXTENDED)
            Hints that were incorrect and were ignored are removed from there.

            h2. 2. Hint hierarchy

            h3. 2.1 Index-level hints
            Index-level hints apply to index(es).
            The syntax is
            {code}
            hint_name(table_name [index_name [, index_name] ...])
            {code}

            where table_name may be query_block@table_name.

            (TODO: MySQL also supports hint_name(@query_block_name tbl_name) ? But we don't? )
             
            h2. 3. Query block naming: QB_NAME hint

            QB_NAME hint is used to assign a name to the query block the hint is in. The Query Block is either a SELECT or a top-level construct of UPDATE or DELETE statement.

            {code:sql}
            SELECT /*+ QB_NAME(foo) */ select_list FROM ...
            {code}

            The name can later be used
            * to refer to a query block, where required
            * to refer to a table as {{table_name@query_block_name}}.

            Hints inside VIEWs are not supported, yet.

            Besides the given name, any query block is given a name {{select#n}}, so one can refer to it like so:
            {code:sql}
            SELECT /*+ BKA(tbl1@`select#1`) */ 1 FROM tbl1 ...;
            {code}
            (TODO: can one control SELECTs inside VIEWs that way? No?)
            (TODO: QB_NAME in CTEs that are used in multiple places?)

            h2. 4. Effect of optimizer hints

            Optimizer can be controlled by
            1. Server variables - optimizer_switch, join_cache_level, etc, etc
            2. Old-style hints
            3. New-style hints

            Old-style hints did not overlap with server variable settings.

            New-style hints are more specific than server variable settings, so they override the server variable settings.

            Should new-style hints override old-style hints? TODO.

            Hints are "narrowly interpreted" and "best effort" - if a hint dictates to do something, like
            {code:sql}
            SELECT /*+ MRR(t1 t1_index1) */ ... FROM t1 ...
            {code}
            that means:
            {quote}
            When considering a query plan that involves using t1_index1 in a way that one can use MRR, use MRR.
            {quote}
            if the query planning is such that use of {{t1_index1}} doesn't allow to use MRR, it won't be used.
            The optimizer may also consider using {{t1_index2}} and pick that over using {{t1_index1}}.
            In such cases the hint is effectively ignored and no warning is given.
            Examples: [^mdev35483-mrr-is-narrow.sql]

            h2. 5. List of hints

            h2. 5.1 NO_RANGE_OPTIMIZATION hint

            It's an index-level hint that disables range optimization for certain index(es):
            {code:sql}
            SELECT /*+ NO_RANGE_OPTIMIZATION(tbl index1 index2) */ * FROM tbl ...
            {code}

            h2. 5.2 NO_ICP hint
            It's an index-level hint that disables Index Condition Pushdown for the indexes. ICP+BKA is disabled as well.
            {code:sql}
            SELECT /*+ NO_ICP(tbl index1 index2) */ * FROM tbl ...
            {code}

            h3. MRR and NO_MRR hints

            Index-level hint to force or disable use of MRR.

            {code:sql}
            SELECT /*+ MRR(tbl index1 index2) */ * FROM tbl ...
            SELECT /*+ NO_MRR(tbl index1 index2) */ * FROM tbl ...
            {code}
            This controls
            * MRR optimization for range access ( [^mdev35483-mrr-is-narrow.sql] )
            * BKA [^mdev35483-mrr-controls-bka-partially.sql]

            This is a self-contained description of Optimizer Hints in MariaDB, whatever is already implemented in the current patch.

            h1. Optimizer hints in MariaDB

            General idea is to be compatible with MySQL.
            MySQL hint docs: https://dev.mysql.com/doc/refman/8.4/en/optimizer-hints.html

            h2. 1. Hint syntax
            Hints are placed after the main statement verb

            {code:sql}
            UPDATE /*+ hints */ table ...;
            DELETE /*+ hints */ FROM table... ;
            SELECT /*+ hints */ ...
            {code}

            or after the SELECT keyword in any subquery:
            {code:sql}
            SELECT * FROM t1 WHERE a IN (SELECT /*+ hints */ ...)
            {code}

            There can be one or more hints separated with space
            {code}
              hints: hint hint ...
            {code}

            Each individual hint is hint name and arguments. In case there are no arguments,
            the () brackets are still present:

            {code}
            hint: hint_name([arguments])
            {code}

            Incorrect hints produce warnings. (TODO any thing else?)
            Hints that are not ignored are kept in the query text (you can see them in SHOW PROCESSLIST, Slow Query Log, EXPLAIN EXTENDED)
            Hints that were incorrect and were ignored are removed from there.

            h2. 2. Hint hierarchy

            h3. 2.1 Index-level hints
            Index-level hints apply to index(es).
            The syntax is
            {code}
            hint_name(table_name [index_name [, index_name] ...])
            {code}

            where table_name may be query_block@table_name.

            (TODO: MySQL also supports hint_name(@query_block_name tbl_name) ? But we don't? )
             
            h2. 3. Query block naming: QB_NAME hint

            QB_NAME hint is used to assign a name to the query block the hint is in. The Query Block is either a SELECT or a top-level construct of UPDATE or DELETE statement.

            {code:sql}
            SELECT /*+ QB_NAME(foo) */ select_list FROM ...
            {code}

            The name can later be used
            * to refer to a query block, where required
            * to refer to a table as {{table_name@query_block_name}}.

            Hints inside VIEWs are not supported, yet.

            Besides the given name, any query block is given a name {{select#n}}, so one can refer to it like so:
            {code:sql}
            SELECT /*+ BKA(tbl1@`select#1`) */ 1 FROM tbl1 ...;
            {code}
            (TODO: can one control SELECTs inside VIEWs that way? No?)
            (TODO: QB_NAME in CTEs that are used in multiple places?)

            h2. 4. Effect of optimizer hints

            Optimizer can be controlled by
            1. Server variables - optimizer_switch, join_cache_level, etc, etc
            2. Old-style hints
            3. New-style hints

            Old-style hints did not overlap with server variable settings.

            New-style hints are more specific than server variable settings, so they override the server variable settings.

            Should new-style hints override old-style hints? TODO.

            Hints are "narrowly interpreted" and "best effort" - if a hint dictates to do something, like
            {code:sql}
            SELECT /*+ MRR(t1 t1_index1) */ ... FROM t1 ...
            {code}
            that means:
            {quote}
            When considering a query plan that involves using t1_index1 in a way that one can use MRR, use MRR.
            {quote}
            if the query planning is such that use of {{t1_index1}} doesn't allow to use MRR, it won't be used.
            The optimizer may also consider using {{t1_index2}} and pick that over using {{t1_index1}}.
            In such cases the hint is effectively ignored and no warning is given.
            Examples: [^mdev35483-mrr-is-narrow.sql]

            h2. 5. List of hints

            h2. 5.1 NO_RANGE_OPTIMIZATION hint

            It's an index-level hint that disables range optimization for certain index(es):
            {code:sql}
            SELECT /*+ NO_RANGE_OPTIMIZATION(tbl index1 index2) */ * FROM tbl ...
            {code}

            h2. 5.2 NO_ICP hint
            It's an index-level hint that disables Index Condition Pushdown for the indexes. ICP+BKA is disabled as well.
            {code:sql}
            SELECT /*+ NO_ICP(tbl index1 index2) */ * FROM tbl ...
            {code}

            h3. MRR and NO_MRR hints

            Index-level hint to force or disable use of MRR.

            {code:sql}
            SELECT /*+ MRR(tbl index1 index2) */ * FROM tbl ...
            SELECT /*+ NO_MRR(tbl index1 index2) */ * FROM tbl ...
            {code}
            This controls
            * MRR optimization for range access ( [^mdev35483-mrr-is-narrow.sql] )
            * BKA [^mdev35483-mrr-controls-bka-partially.sql]

            psergei Sergei Petrunia made changes -
            Description This is a self-contained description of Optimizer Hints in MariaDB, whatever is already implemented in the current patch.

            h1. Optimizer hints in MariaDB

            General idea is to be compatible with MySQL.
            MySQL hint docs: https://dev.mysql.com/doc/refman/8.4/en/optimizer-hints.html

            h2. 1. Hint syntax
            Hints are placed after the main statement verb

            {code:sql}
            UPDATE /*+ hints */ table ...;
            DELETE /*+ hints */ FROM table... ;
            SELECT /*+ hints */ ...
            {code}

            or after the SELECT keyword in any subquery:
            {code:sql}
            SELECT * FROM t1 WHERE a IN (SELECT /*+ hints */ ...)
            {code}

            There can be one or more hints separated with space
            {code}
              hints: hint hint ...
            {code}

            Each individual hint is hint name and arguments. In case there are no arguments,
            the () brackets are still present:

            {code}
            hint: hint_name([arguments])
            {code}

            Incorrect hints produce warnings. (TODO any thing else?)
            Hints that are not ignored are kept in the query text (you can see them in SHOW PROCESSLIST, Slow Query Log, EXPLAIN EXTENDED)
            Hints that were incorrect and were ignored are removed from there.

            h2. 2. Hint hierarchy

            h3. 2.1 Index-level hints
            Index-level hints apply to index(es).
            The syntax is
            {code}
            hint_name(table_name [index_name [, index_name] ...])
            {code}

            where table_name may be query_block@table_name.

            (TODO: MySQL also supports hint_name(@query_block_name tbl_name) ? But we don't? )
             
            h2. 3. Query block naming: QB_NAME hint

            QB_NAME hint is used to assign a name to the query block the hint is in. The Query Block is either a SELECT or a top-level construct of UPDATE or DELETE statement.

            {code:sql}
            SELECT /*+ QB_NAME(foo) */ select_list FROM ...
            {code}

            The name can later be used
            * to refer to a query block, where required
            * to refer to a table as {{table_name@query_block_name}}.

            Hints inside VIEWs are not supported, yet.

            Besides the given name, any query block is given a name {{select#n}}, so one can refer to it like so:
            {code:sql}
            SELECT /*+ BKA(tbl1@`select#1`) */ 1 FROM tbl1 ...;
            {code}
            (TODO: can one control SELECTs inside VIEWs that way? No?)
            (TODO: QB_NAME in CTEs that are used in multiple places?)

            h2. 4. Effect of optimizer hints

            Optimizer can be controlled by
            1. Server variables - optimizer_switch, join_cache_level, etc, etc
            2. Old-style hints
            3. New-style hints

            Old-style hints did not overlap with server variable settings.

            New-style hints are more specific than server variable settings, so they override the server variable settings.

            Should new-style hints override old-style hints? TODO.

            Hints are "narrowly interpreted" and "best effort" - if a hint dictates to do something, like
            {code:sql}
            SELECT /*+ MRR(t1 t1_index1) */ ... FROM t1 ...
            {code}
            that means:
            {quote}
            When considering a query plan that involves using t1_index1 in a way that one can use MRR, use MRR.
            {quote}
            if the query planning is such that use of {{t1_index1}} doesn't allow to use MRR, it won't be used.
            The optimizer may also consider using {{t1_index2}} and pick that over using {{t1_index1}}.
            In such cases the hint is effectively ignored and no warning is given.
            Examples: [^mdev35483-mrr-is-narrow.sql]

            h2. 5. List of hints

            h2. 5.1 NO_RANGE_OPTIMIZATION hint

            It's an index-level hint that disables range optimization for certain index(es):
            {code:sql}
            SELECT /*+ NO_RANGE_OPTIMIZATION(tbl index1 index2) */ * FROM tbl ...
            {code}

            h2. 5.2 NO_ICP hint
            It's an index-level hint that disables Index Condition Pushdown for the indexes. ICP+BKA is disabled as well.
            {code:sql}
            SELECT /*+ NO_ICP(tbl index1 index2) */ * FROM tbl ...
            {code}

            h3. MRR and NO_MRR hints

            Index-level hint to force or disable use of MRR.

            {code:sql}
            SELECT /*+ MRR(tbl index1 index2) */ * FROM tbl ...
            SELECT /*+ NO_MRR(tbl index1 index2) */ * FROM tbl ...
            {code}
            This controls
            * MRR optimization for range access ( [^mdev35483-mrr-is-narrow.sql] )
            * BKA [^mdev35483-mrr-controls-bka-partially.sql]

            This is a self-contained description of Optimizer Hints in MariaDB, whatever is already implemented in the current patch.

            h1. Optimizer hints in MariaDB

            General idea is to be compatible with MySQL.
            MySQL hint docs: https://dev.mysql.com/doc/refman/8.4/en/optimizer-hints.html

            h2. 1. Hint syntax
            Hints are placed after the main statement verb

            {code:sql}
            UPDATE /*+ hints */ table ...;
            DELETE /*+ hints */ FROM table... ;
            SELECT /*+ hints */ ...
            {code}

            or after the SELECT keyword in any subquery:
            {code:sql}
            SELECT * FROM t1 WHERE a IN (SELECT /*+ hints */ ...)
            {code}

            There can be one or more hints separated with space
            {code}
              hints: hint hint ...
            {code}

            Each individual hint is hint name and arguments. In case there are no arguments,
            the () brackets are still present:

            {code}
            hint: hint_name([arguments])
            {code}

            Incorrect hints produce warnings. (TODO any thing else?)
            Hints that are not ignored are kept in the query text (you can see them in SHOW PROCESSLIST, Slow Query Log, EXPLAIN EXTENDED)
            Hints that were incorrect and were ignored are removed from there.

            h2. 2. Hint hierarchy

            h3. 2.1 Index-level hints
            Index-level hints apply to index(es).
            The syntax is
            {code}
            hint_name(table_name [index_name [, index_name] ...])
            {code}

            where table_name may be query_block@table_name.

            (TODO: MySQL also supports hint_name(@query_block_name tbl_name) ? But we don't? )
             
            h2. 3. Query block naming: QB_NAME hint

            QB_NAME hint is used to assign a name to the query block the hint is in. The Query Block is either a SELECT or a top-level construct of UPDATE or DELETE statement.

            {code:sql}
            SELECT /*+ QB_NAME(foo) */ select_list FROM ...
            {code}

            The name can later be used
            * to refer to a query block, where required
            * to refer to a table as {{table_name@query_block_name}}.

            Hints inside VIEWs are not supported, yet.

            Besides the given name, any query block is given a name {{select#n}}, so one can refer to it like so:
            {code:sql}
            SELECT /*+ BKA(tbl1@`select#1`) */ 1 FROM tbl1 ...;
            {code}
            (TODO: can one control SELECTs inside VIEWs that way? No?)
            (TODO: QB_NAME in CTEs that are used in multiple places?)

            h2. 4. Effect of optimizer hints

            Optimizer can be controlled by
            1. Server variables - optimizer_switch, join_cache_level, etc, etc
            2. Old-style hints
            3. New-style hints

            Old-style hints did not overlap with server variable settings.

            New-style hints are more specific than server variable settings, so they override the server variable settings.

            Should new-style hints override old-style hints? TODO.

            Hints are "narrowly interpreted" and "best effort" - if a hint dictates to do something, like
            {code:sql}
            SELECT /*+ MRR(t1 t1_index1) */ ... FROM t1 ...
            {code}
            that means:
            {quote}
            When considering a query plan that involves using t1_index1 in a way that one can use MRR, use MRR.
            {quote}
            if the query planning is such that use of {{t1_index1}} doesn't allow to use MRR, it won't be used.
            The optimizer may also consider using {{t1_index2}} and pick that over using {{t1_index1}}.
            In such cases the hint is effectively ignored and no warning is given.
            Examples: [^mdev35483-mrr-is-narrow.sql]

            h2. 5. List of hints

            h3. 5.1 NO_RANGE_OPTIMIZATION hint

            It's an index-level hint that disables range optimization for certain index(es):
            {code:sql}
            SELECT /*+ NO_RANGE_OPTIMIZATION(tbl index1 index2) */ * FROM tbl ...
            {code}

            h3. 5.2 NO_ICP hint
            It's an index-level hint that disables Index Condition Pushdown for the indexes. ICP+BKA is disabled as well.
            {code:sql}
            SELECT /*+ NO_ICP(tbl index1 index2) */ * FROM tbl ...
            {code}

            h3. MRR and NO_MRR hints

            Index-level hint to force or disable use of MRR.

            {code:sql}
            SELECT /*+ MRR(tbl index1 index2) */ * FROM tbl ...
            SELECT /*+ NO_MRR(tbl index1 index2) */ * FROM tbl ...
            {code}
            This controls
            * MRR optimization for range access ( [^mdev35483-mrr-is-narrow.sql] )
            * BKA [^mdev35483-mrr-controls-bka-partially.sql]

            psergei Sergei Petrunia made changes -
            Description This is a self-contained description of Optimizer Hints in MariaDB, whatever is already implemented in the current patch.

            h1. Optimizer hints in MariaDB

            General idea is to be compatible with MySQL.
            MySQL hint docs: https://dev.mysql.com/doc/refman/8.4/en/optimizer-hints.html

            h2. 1. Hint syntax
            Hints are placed after the main statement verb

            {code:sql}
            UPDATE /*+ hints */ table ...;
            DELETE /*+ hints */ FROM table... ;
            SELECT /*+ hints */ ...
            {code}

            or after the SELECT keyword in any subquery:
            {code:sql}
            SELECT * FROM t1 WHERE a IN (SELECT /*+ hints */ ...)
            {code}

            There can be one or more hints separated with space
            {code}
              hints: hint hint ...
            {code}

            Each individual hint is hint name and arguments. In case there are no arguments,
            the () brackets are still present:

            {code}
            hint: hint_name([arguments])
            {code}

            Incorrect hints produce warnings. (TODO any thing else?)
            Hints that are not ignored are kept in the query text (you can see them in SHOW PROCESSLIST, Slow Query Log, EXPLAIN EXTENDED)
            Hints that were incorrect and were ignored are removed from there.

            h2. 2. Hint hierarchy

            h3. 2.1 Index-level hints
            Index-level hints apply to index(es).
            The syntax is
            {code}
            hint_name(table_name [index_name [, index_name] ...])
            {code}

            where table_name may be query_block@table_name.

            (TODO: MySQL also supports hint_name(@query_block_name tbl_name) ? But we don't? )
             
            h2. 3. Query block naming: QB_NAME hint

            QB_NAME hint is used to assign a name to the query block the hint is in. The Query Block is either a SELECT or a top-level construct of UPDATE or DELETE statement.

            {code:sql}
            SELECT /*+ QB_NAME(foo) */ select_list FROM ...
            {code}

            The name can later be used
            * to refer to a query block, where required
            * to refer to a table as {{table_name@query_block_name}}.

            Hints inside VIEWs are not supported, yet.

            Besides the given name, any query block is given a name {{select#n}}, so one can refer to it like so:
            {code:sql}
            SELECT /*+ BKA(tbl1@`select#1`) */ 1 FROM tbl1 ...;
            {code}
            (TODO: can one control SELECTs inside VIEWs that way? No?)
            (TODO: QB_NAME in CTEs that are used in multiple places?)

            h2. 4. Effect of optimizer hints

            Optimizer can be controlled by
            1. Server variables - optimizer_switch, join_cache_level, etc, etc
            2. Old-style hints
            3. New-style hints

            Old-style hints did not overlap with server variable settings.

            New-style hints are more specific than server variable settings, so they override the server variable settings.

            Should new-style hints override old-style hints? TODO.

            Hints are "narrowly interpreted" and "best effort" - if a hint dictates to do something, like
            {code:sql}
            SELECT /*+ MRR(t1 t1_index1) */ ... FROM t1 ...
            {code}
            that means:
            {quote}
            When considering a query plan that involves using t1_index1 in a way that one can use MRR, use MRR.
            {quote}
            if the query planning is such that use of {{t1_index1}} doesn't allow to use MRR, it won't be used.
            The optimizer may also consider using {{t1_index2}} and pick that over using {{t1_index1}}.
            In such cases the hint is effectively ignored and no warning is given.
            Examples: [^mdev35483-mrr-is-narrow.sql]

            h2. 5. List of hints

            h3. 5.1 NO_RANGE_OPTIMIZATION hint

            It's an index-level hint that disables range optimization for certain index(es):
            {code:sql}
            SELECT /*+ NO_RANGE_OPTIMIZATION(tbl index1 index2) */ * FROM tbl ...
            {code}

            h3. 5.2 NO_ICP hint
            It's an index-level hint that disables Index Condition Pushdown for the indexes. ICP+BKA is disabled as well.
            {code:sql}
            SELECT /*+ NO_ICP(tbl index1 index2) */ * FROM tbl ...
            {code}

            h3. MRR and NO_MRR hints

            Index-level hint to force or disable use of MRR.

            {code:sql}
            SELECT /*+ MRR(tbl index1 index2) */ * FROM tbl ...
            SELECT /*+ NO_MRR(tbl index1 index2) */ * FROM tbl ...
            {code}
            This controls
            * MRR optimization for range access ( [^mdev35483-mrr-is-narrow.sql] )
            * BKA [^mdev35483-mrr-controls-bka-partially.sql]

            This is a self-contained description of Optimizer Hints in MariaDB, whatever is already implemented in the current patch.

            h1. Optimizer hints in MariaDB

            General idea is to be compatible with MySQL.
            MySQL hint docs: https://dev.mysql.com/doc/refman/8.4/en/optimizer-hints.html

            h2. 1. Hint syntax
            Hints are placed after the main statement verb

            {code:sql}
            UPDATE /*+ hints */ table ...;
            DELETE /*+ hints */ FROM table... ;
            SELECT /*+ hints */ ...
            {code}

            or after the SELECT keyword in any subquery:
            {code:sql}
            SELECT * FROM t1 WHERE a IN (SELECT /*+ hints */ ...)
            {code}

            There can be one or more hints separated with space
            {code}
              hints: hint hint ...
            {code}

            Each individual hint is hint name and arguments. In case there are no arguments,
            the () brackets are still present:

            {code}
            hint: hint_name([arguments])
            {code}

            Incorrect hints produce warnings. (TODO any thing else?)
            Hints that are not ignored are kept in the query text (you can see them in SHOW PROCESSLIST, Slow Query Log, EXPLAIN EXTENDED)
            Hints that were incorrect and were ignored are removed from there.

            h2. 2. Hint hierarchy

            h3. 2.1 Index-level hints
            Index-level hints apply to index(es).
            The syntax is
            {code}
            hint_name(table_name [index_name [, index_name] ...])
            {code}

            where table_name may be query_block@table_name.

            (TODO: MySQL also supports hint_name(@query_block_name tbl_name) ? But we don't? )
             
            h2. 3. Query block naming: QB_NAME hint

            QB_NAME hint is used to assign a name to the query block the hint is in. The Query Block is either a SELECT or a top-level construct of UPDATE or DELETE statement.

            {code:sql}
            SELECT /*+ QB_NAME(foo) */ select_list FROM ...
            {code}

            The name can later be used
            * to refer to a query block, where required
            * to refer to a table as {{table_name@query_block_name}}.

            Hints inside VIEWs are not supported, yet.

            Besides the given name, any query block is given a name {{select#n}}, so one can refer to it like so:
            {code:sql}
            SELECT /*+ BKA(tbl1@`select#1`) */ 1 FROM tbl1 ...;
            {code}
            (TODO: can one control SELECTs inside VIEWs that way? No?)
            (TODO: QB_NAME in CTEs that are used in multiple places?)

            h2. 4. Effect of optimizer hints

            Optimizer can be controlled by
            1. Server variables - optimizer_switch, join_cache_level, etc, etc
            2. Old-style hints
            3. New-style hints

            Old-style hints did not overlap with server variable settings.

            New-style hints are more specific than server variable settings, so they override the server variable settings.

            Should new-style hints override old-style hints? TODO.

            Hints are "narrowly interpreted" and "best effort" - if a hint dictates to do something, like
            {code:sql}
            SELECT /*+ MRR(t1 t1_index1) */ ... FROM t1 ...
            {code}
            that means:
            {quote}
            When considering a query plan that involves using t1_index1 in a way that one can use MRR, use MRR.
            {quote}
            if the query planning is such that use of {{t1_index1}} doesn't allow to use MRR, it won't be used.
            The optimizer may also consider using {{t1_index2}} and pick that over using {{t1_index1}}.
            In such cases the hint is effectively ignored and no warning is given.
            Examples: [^mdev35483-mrr-is-narrow.sql]

            h2. 5. List of hints

            h3. 5.1 NO_RANGE_OPTIMIZATION hint

            It's an index-level hint that disables range optimization for certain index(es):
            {code:sql}
            SELECT /*+ NO_RANGE_OPTIMIZATION(tbl index1 index2) */ * FROM tbl ...
            {code}

            h3. 5.2 NO_ICP hint
            It's an index-level hint that disables Index Condition Pushdown for the indexes. ICP+BKA is disabled as well.
            {code:sql}
            SELECT /*+ NO_ICP(tbl index1 index2) */ * FROM tbl ...
            {code}

            h3. 5.3 MRR and NO_MRR hints

            Index-level hint to force or disable use of MRR.

            {code:sql}
            SELECT /*+ MRR(tbl index1 index2) */ * FROM tbl ...
            SELECT /*+ NO_MRR(tbl index1 index2) */ * FROM tbl ...
            {code}
            This controls
            * MRR optimization for range access ( [^mdev35483-mrr-is-narrow.sql] )
            * BKA [^mdev35483-mrr-controls-bka-partially.sql]

            h3. 5.4 BKA() and NO_BKA() hints
            It's an index-level hint.

            h3. BNL() and NO_BNL() hints

            h3. MAX_EXECUTION_TIME() hint
            {code:sql}
            SELECT /*+ MAX_EXECUTION_TIME(milliseconds) */ ... FROM... ;
            {code}
            psergei Sergei Petrunia made changes -
            Description This is a self-contained description of Optimizer Hints in MariaDB, whatever is already implemented in the current patch.

            h1. Optimizer hints in MariaDB

            General idea is to be compatible with MySQL.
            MySQL hint docs: https://dev.mysql.com/doc/refman/8.4/en/optimizer-hints.html

            h2. 1. Hint syntax
            Hints are placed after the main statement verb

            {code:sql}
            UPDATE /*+ hints */ table ...;
            DELETE /*+ hints */ FROM table... ;
            SELECT /*+ hints */ ...
            {code}

            or after the SELECT keyword in any subquery:
            {code:sql}
            SELECT * FROM t1 WHERE a IN (SELECT /*+ hints */ ...)
            {code}

            There can be one or more hints separated with space
            {code}
              hints: hint hint ...
            {code}

            Each individual hint is hint name and arguments. In case there are no arguments,
            the () brackets are still present:

            {code}
            hint: hint_name([arguments])
            {code}

            Incorrect hints produce warnings. (TODO any thing else?)
            Hints that are not ignored are kept in the query text (you can see them in SHOW PROCESSLIST, Slow Query Log, EXPLAIN EXTENDED)
            Hints that were incorrect and were ignored are removed from there.

            h2. 2. Hint hierarchy

            h3. 2.1 Index-level hints
            Index-level hints apply to index(es).
            The syntax is
            {code}
            hint_name(table_name [index_name [, index_name] ...])
            {code}

            where table_name may be query_block@table_name.

            (TODO: MySQL also supports hint_name(@query_block_name tbl_name) ? But we don't? )
             
            h2. 3. Query block naming: QB_NAME hint

            QB_NAME hint is used to assign a name to the query block the hint is in. The Query Block is either a SELECT or a top-level construct of UPDATE or DELETE statement.

            {code:sql}
            SELECT /*+ QB_NAME(foo) */ select_list FROM ...
            {code}

            The name can later be used
            * to refer to a query block, where required
            * to refer to a table as {{table_name@query_block_name}}.

            Hints inside VIEWs are not supported, yet.

            Besides the given name, any query block is given a name {{select#n}}, so one can refer to it like so:
            {code:sql}
            SELECT /*+ BKA(tbl1@`select#1`) */ 1 FROM tbl1 ...;
            {code}
            (TODO: can one control SELECTs inside VIEWs that way? No?)
            (TODO: QB_NAME in CTEs that are used in multiple places?)

            h2. 4. Effect of optimizer hints

            Optimizer can be controlled by
            1. Server variables - optimizer_switch, join_cache_level, etc, etc
            2. Old-style hints
            3. New-style hints

            Old-style hints did not overlap with server variable settings.

            New-style hints are more specific than server variable settings, so they override the server variable settings.

            Should new-style hints override old-style hints? TODO.

            Hints are "narrowly interpreted" and "best effort" - if a hint dictates to do something, like
            {code:sql}
            SELECT /*+ MRR(t1 t1_index1) */ ... FROM t1 ...
            {code}
            that means:
            {quote}
            When considering a query plan that involves using t1_index1 in a way that one can use MRR, use MRR.
            {quote}
            if the query planning is such that use of {{t1_index1}} doesn't allow to use MRR, it won't be used.
            The optimizer may also consider using {{t1_index2}} and pick that over using {{t1_index1}}.
            In such cases the hint is effectively ignored and no warning is given.
            Examples: [^mdev35483-mrr-is-narrow.sql]

            h2. 5. List of hints

            h3. 5.1 NO_RANGE_OPTIMIZATION hint

            It's an index-level hint that disables range optimization for certain index(es):
            {code:sql}
            SELECT /*+ NO_RANGE_OPTIMIZATION(tbl index1 index2) */ * FROM tbl ...
            {code}

            h3. 5.2 NO_ICP hint
            It's an index-level hint that disables Index Condition Pushdown for the indexes. ICP+BKA is disabled as well.
            {code:sql}
            SELECT /*+ NO_ICP(tbl index1 index2) */ * FROM tbl ...
            {code}

            h3. 5.3 MRR and NO_MRR hints

            Index-level hint to force or disable use of MRR.

            {code:sql}
            SELECT /*+ MRR(tbl index1 index2) */ * FROM tbl ...
            SELECT /*+ NO_MRR(tbl index1 index2) */ * FROM tbl ...
            {code}
            This controls
            * MRR optimization for range access ( [^mdev35483-mrr-is-narrow.sql] )
            * BKA [^mdev35483-mrr-controls-bka-partially.sql]

            h3. 5.4 BKA() and NO_BKA() hints
            It's an index-level hint.

            h3. BNL() and NO_BNL() hints

            h3. MAX_EXECUTION_TIME() hint
            {code:sql}
            SELECT /*+ MAX_EXECUTION_TIME(milliseconds) */ ... FROM... ;
            {code}
            This is a self-contained description of Optimizer Hints in MariaDB, whatever is already implemented in the current patch.

            h1. Optimizer hints in MariaDB

            General idea is to be compatible with MySQL.
            MySQL hint docs: https://dev.mysql.com/doc/refman/8.4/en/optimizer-hints.html

            h2. 1. Hint syntax
            Hints are placed after the main statement verb

            {code:sql}
            UPDATE /*+ hints */ table ...;
            DELETE /*+ hints */ FROM table... ;
            SELECT /*+ hints */ ...
            {code}

            or after the SELECT keyword in any subquery:
            {code:sql}
            SELECT * FROM t1 WHERE a IN (SELECT /*+ hints */ ...)
            {code}

            There can be one or more hints separated with space
            {code}
              hints: hint hint ...
            {code}

            Each individual hint is hint name and arguments. In case there are no arguments,
            the () brackets are still present:

            {code}
            hint: hint_name([arguments])
            {code}

            Incorrect hints produce warnings. (TODO any thing else?)
            Hints that are not ignored are kept in the query text (you can see them in SHOW PROCESSLIST, Slow Query Log, EXPLAIN EXTENDED)
            Hints that were incorrect and were ignored are removed from there.

            h2. 2. Hint hierarchy

            h3. 2.1 Index-level hints
            Index-level hints apply to index(es).
            The syntax is
            {code}
            hint_name(table_name [index_name [, index_name] ...])
            {code}

            where table_name may be query_block@table_name.

            (TODO: MySQL also supports hint_name(@query_block_name tbl_name) ? But we don't? )
             
            h2. 3. Query block naming: QB_NAME hint

            QB_NAME hint is used to assign a name to the query block the hint is in. The Query Block is either a SELECT or a top-level construct of UPDATE or DELETE statement.

            {code:sql}
            SELECT /*+ QB_NAME(foo) */ select_list FROM ...
            {code}

            The name can later be used
            * to refer to a query block, where required
            * to refer to a table as {{table_name@query_block_name}}.

            Hints inside VIEWs are not supported, yet.

            Besides the given name, any query block is given a name {{select#n}}, so one can refer to it like so:
            {code:sql}
            SELECT /*+ BKA(tbl1@`select#1`) */ 1 FROM tbl1 ...;
            {code}
            (TODO: can one control SELECTs inside VIEWs that way? No?)
            (TODO: QB_NAME in CTEs that are used in multiple places?)

            h2. 4. Effect of optimizer hints

            Optimizer can be controlled by
            1. Server variables - optimizer_switch, join_cache_level, etc, etc
            2. Old-style hints
            3. New-style hints

            Old-style hints did not overlap with server variable settings.

            New-style hints are more specific than server variable settings, so they override the server variable settings.

            Should new-style hints override old-style hints? TODO.

            Hints are "narrowly interpreted" and "best effort" - if a hint dictates to do something, like
            {code:sql}
            SELECT /*+ MRR(t1 t1_index1) */ ... FROM t1 ...
            {code}
            that means:
            {quote}
            When considering a query plan that involves using t1_index1 in a way that one can use MRR, use MRR.
            {quote}
            if the query planning is such that use of {{t1_index1}} doesn't allow to use MRR, it won't be used.
            The optimizer may also consider using {{t1_index2}} and pick that over using {{t1_index1}}.
            In such cases the hint is effectively ignored and no warning is given.
            Examples: [^mdev35483-mrr-is-narrow.sql]

            h2. 5. List of hints

            h3. 5.1 NO_RANGE_OPTIMIZATION hint

            It's an index-level hint that disables range optimization for certain index(es):
            {code:sql}
            SELECT /*+ NO_RANGE_OPTIMIZATION(tbl index1 index2) */ * FROM tbl ...
            {code}

            h3. 5.2 NO_ICP hint
            It's an index-level hint that disables Index Condition Pushdown for the indexes. ICP+BKA is disabled as well.
            {code:sql}
            SELECT /*+ NO_ICP(tbl index1 index2) */ * FROM tbl ...
            {code}

            h3. 5.3 MRR and NO_MRR hints

            Index-level hint to force or disable use of MRR.

            {code:sql}
            SELECT /*+ MRR(tbl index1 index2) */ * FROM tbl ...
            SELECT /*+ NO_MRR(tbl index1 index2) */ * FROM tbl ...
            {code}
            This controls
            * MRR optimization for range access ( [^mdev35483-mrr-is-narrow.sql] )
            * BKA [^mdev35483-mrr-controls-bka-partially.sql]

            h3. 5.4 BKA() and NO_BKA() hints
            It's an index-level hint.

            h3. 5.5 BNL() and NO_BNL() hints

            h3. 5.6 MAX_EXECUTION_TIME() hint
            {code:sql}
            SELECT /*+ MAX_EXECUTION_TIME(milliseconds) */ ... FROM... ;
            {code}
            psergei Sergei Petrunia made changes -
            Description This is a self-contained description of Optimizer Hints in MariaDB, whatever is already implemented in the current patch.

            h1. Optimizer hints in MariaDB

            General idea is to be compatible with MySQL.
            MySQL hint docs: https://dev.mysql.com/doc/refman/8.4/en/optimizer-hints.html

            h2. 1. Hint syntax
            Hints are placed after the main statement verb

            {code:sql}
            UPDATE /*+ hints */ table ...;
            DELETE /*+ hints */ FROM table... ;
            SELECT /*+ hints */ ...
            {code}

            or after the SELECT keyword in any subquery:
            {code:sql}
            SELECT * FROM t1 WHERE a IN (SELECT /*+ hints */ ...)
            {code}

            There can be one or more hints separated with space
            {code}
              hints: hint hint ...
            {code}

            Each individual hint is hint name and arguments. In case there are no arguments,
            the () brackets are still present:

            {code}
            hint: hint_name([arguments])
            {code}

            Incorrect hints produce warnings. (TODO any thing else?)
            Hints that are not ignored are kept in the query text (you can see them in SHOW PROCESSLIST, Slow Query Log, EXPLAIN EXTENDED)
            Hints that were incorrect and were ignored are removed from there.

            h2. 2. Hint hierarchy

            h3. 2.1 Index-level hints
            Index-level hints apply to index(es).
            The syntax is
            {code}
            hint_name(table_name [index_name [, index_name] ...])
            {code}

            where table_name may be query_block@table_name.

            (TODO: MySQL also supports hint_name(@query_block_name tbl_name) ? But we don't? )
             
            h2. 3. Query block naming: QB_NAME hint

            QB_NAME hint is used to assign a name to the query block the hint is in. The Query Block is either a SELECT or a top-level construct of UPDATE or DELETE statement.

            {code:sql}
            SELECT /*+ QB_NAME(foo) */ select_list FROM ...
            {code}

            The name can later be used
            * to refer to a query block, where required
            * to refer to a table as {{table_name@query_block_name}}.

            Hints inside VIEWs are not supported, yet.

            Besides the given name, any query block is given a name {{select#n}}, so one can refer to it like so:
            {code:sql}
            SELECT /*+ BKA(tbl1@`select#1`) */ 1 FROM tbl1 ...;
            {code}
            (TODO: can one control SELECTs inside VIEWs that way? No?)
            (TODO: QB_NAME in CTEs that are used in multiple places?)

            h2. 4. Effect of optimizer hints

            Optimizer can be controlled by
            1. Server variables - optimizer_switch, join_cache_level, etc, etc
            2. Old-style hints
            3. New-style hints

            Old-style hints did not overlap with server variable settings.

            New-style hints are more specific than server variable settings, so they override the server variable settings.

            Should new-style hints override old-style hints? TODO.

            Hints are "narrowly interpreted" and "best effort" - if a hint dictates to do something, like
            {code:sql}
            SELECT /*+ MRR(t1 t1_index1) */ ... FROM t1 ...
            {code}
            that means:
            {quote}
            When considering a query plan that involves using t1_index1 in a way that one can use MRR, use MRR.
            {quote}
            if the query planning is such that use of {{t1_index1}} doesn't allow to use MRR, it won't be used.
            The optimizer may also consider using {{t1_index2}} and pick that over using {{t1_index1}}.
            In such cases the hint is effectively ignored and no warning is given.
            Examples: [^mdev35483-mrr-is-narrow.sql]

            h2. 5. List of hints

            h3. 5.1 NO_RANGE_OPTIMIZATION hint

            It's an index-level hint that disables range optimization for certain index(es):
            {code:sql}
            SELECT /*+ NO_RANGE_OPTIMIZATION(tbl index1 index2) */ * FROM tbl ...
            {code}

            h3. 5.2 NO_ICP hint
            It's an index-level hint that disables Index Condition Pushdown for the indexes. ICP+BKA is disabled as well.
            {code:sql}
            SELECT /*+ NO_ICP(tbl index1 index2) */ * FROM tbl ...
            {code}

            h3. 5.3 MRR and NO_MRR hints

            Index-level hint to force or disable use of MRR.

            {code:sql}
            SELECT /*+ MRR(tbl index1 index2) */ * FROM tbl ...
            SELECT /*+ NO_MRR(tbl index1 index2) */ * FROM tbl ...
            {code}
            This controls
            * MRR optimization for range access ( [^mdev35483-mrr-is-narrow.sql] )
            * BKA [^mdev35483-mrr-controls-bka-partially.sql]

            h3. 5.4 BKA() and NO_BKA() hints
            It's an index-level hint.

            h3. 5.5 BNL() and NO_BNL() hints

            h3. 5.6 MAX_EXECUTION_TIME() hint
            {code:sql}
            SELECT /*+ MAX_EXECUTION_TIME(milliseconds) */ ... FROM... ;
            {code}
            This is a self-contained description of Optimizer Hints in MariaDB, whatever is already implemented in the current patch.

            h1. Optimizer hints in MariaDB

            General idea is to be compatible with MySQL.
            MySQL hint docs: https://dev.mysql.com/doc/refman/8.4/en/optimizer-hints.html

            h2. 1. Hint syntax
            Hints are placed after the main statement verb

            {code:sql}
            UPDATE /*+ hints */ table ...;
            DELETE /*+ hints */ FROM table... ;
            SELECT /*+ hints */ ...
            {code}

            or after the SELECT keyword in any subquery:
            {code:sql}
            SELECT * FROM t1 WHERE a IN (SELECT /*+ hints */ ...)
            {code}

            There can be one or more hints separated with space
            {code}
              hints: hint hint ...
            {code}

            Each individual hint is hint name and arguments. In case there are no arguments,
            the () brackets are still present:

            {code}
            hint: hint_name([arguments])
            {code}

            Incorrect hints produce warnings. (TODO any thing else?)
            Hints that are not ignored are kept in the query text (you can see them in SHOW PROCESSLIST, Slow Query Log, EXPLAIN EXTENDED)
            Hints that were incorrect and were ignored are removed from there.

            h2. 2. Hint hierarchy

            h3. 2.1 Index-level hints
            Index-level hints apply to index(es).
            The syntax is
            {code}
            hint_name(table_name [index_name [, index_name] ...])
            {code}

            where table_name may be query_block@table_name.

            (TODO: MySQL also supports hint_name(@query_block_name tbl_name) ? But we don't? )
             
            h2. 3. Query block naming: QB_NAME hint

            QB_NAME hint is used to assign a name to the query block the hint is in. The Query Block is either a SELECT or a top-level construct of UPDATE or DELETE statement.

            {code:sql}
            SELECT /*+ QB_NAME(foo) */ select_list FROM ...
            {code}

            The name can later be used
            * to refer to a query block, where required
            * to refer to a table as {{table_name@query_block_name}}.

            Hints inside VIEWs are not supported, yet.

            Besides the given name, any query block is given a name {{select#n}}, so one can refer to it like so:
            {code:sql}
            SELECT /*+ BKA(tbl1@`select#1`) */ 1 FROM tbl1 ...;
            {code}
            (TODO: can one control SELECTs inside VIEWs that way? No?)
            (TODO: QB_NAME in CTEs that are used in multiple places?)

            h2. 4. Effect of optimizer hints

            Optimizer can be controlled by
            1. Server variables - optimizer_switch, join_cache_level, etc, etc
            2. Old-style hints
            3. New-style hints

            Old-style hints did not overlap with server variable settings.

            New-style hints are more specific than server variable settings, so they override the server variable settings.

            Should new-style hints override old-style hints? TODO.

            Hints are "narrowly interpreted" and "best effort" - if a hint dictates to do something, like
            {code:sql}
            SELECT /*+ MRR(t1 t1_index1) */ ... FROM t1 ...
            {code}
            that means:
            {quote}
            When considering a query plan that involves using t1_index1 in a way that one can use MRR, use MRR.
            {quote}
            if the query planning is such that use of {{t1_index1}} doesn't allow to use MRR, it won't be used.
            The optimizer may also consider using {{t1_index2}} and pick that over using {{t1_index1}}.
            In such cases the hint is effectively ignored and no warning is given.
            Examples: [^mdev35483-mrr-is-narrow.sql]

            h2. 5. List of hints

            h3. 5.1 NO_RANGE_OPTIMIZATION hint

            It's an index-level hint that disables range optimization for certain index(es):
            {code:sql}
            SELECT /*+ NO_RANGE_OPTIMIZATION(tbl index1 index2) */ * FROM tbl ...
            {code}

            h3. 5.2 NO_ICP hint
            It's an index-level hint that disables Index Condition Pushdown for the indexes. ICP+BKA is disabled as well.
            {code:sql}
            SELECT /*+ NO_ICP(tbl index1 index2) */ * FROM tbl ...
            {code}

            h3. 5.3 MRR and NO_MRR hints

            Index-level hint to force or disable use of MRR.

            {code:sql}
            SELECT /*+ MRR(tbl index1 index2) */ * FROM tbl ...
            SELECT /*+ NO_MRR(tbl index1 index2) */ * FROM tbl ...
            {code}
            This controls
            * MRR optimization for range access ( [^mdev35483-mrr-is-narrow.sql] )
            * BKA [^mdev35483-mrr-controls-bka-partially.sql]

            h3. 5.4 BKA() and NO_BKA() hints
            It's a query block or table-level hint.

            This hint also enables MRR to make BKA possible. (This is different from session variables, where one needs to enable MRR separately).

            This also enables BKAH. TODO what was the reason for this?

            h3. 5.5 BNL() and NO_BNL() hints

            h3. 5.6 MAX_EXECUTION_TIME() hint
            {code:sql}
            SELECT /*+ MAX_EXECUTION_TIME(milliseconds) */ ... FROM... ;
            {code}
            psergei Sergei Petrunia made changes -
            Description This is a self-contained description of Optimizer Hints in MariaDB, whatever is already implemented in the current patch.

            h1. Optimizer hints in MariaDB

            General idea is to be compatible with MySQL.
            MySQL hint docs: https://dev.mysql.com/doc/refman/8.4/en/optimizer-hints.html

            h2. 1. Hint syntax
            Hints are placed after the main statement verb

            {code:sql}
            UPDATE /*+ hints */ table ...;
            DELETE /*+ hints */ FROM table... ;
            SELECT /*+ hints */ ...
            {code}

            or after the SELECT keyword in any subquery:
            {code:sql}
            SELECT * FROM t1 WHERE a IN (SELECT /*+ hints */ ...)
            {code}

            There can be one or more hints separated with space
            {code}
              hints: hint hint ...
            {code}

            Each individual hint is hint name and arguments. In case there are no arguments,
            the () brackets are still present:

            {code}
            hint: hint_name([arguments])
            {code}

            Incorrect hints produce warnings. (TODO any thing else?)
            Hints that are not ignored are kept in the query text (you can see them in SHOW PROCESSLIST, Slow Query Log, EXPLAIN EXTENDED)
            Hints that were incorrect and were ignored are removed from there.

            h2. 2. Hint hierarchy

            h3. 2.1 Index-level hints
            Index-level hints apply to index(es).
            The syntax is
            {code}
            hint_name(table_name [index_name [, index_name] ...])
            {code}

            where table_name may be query_block@table_name.

            (TODO: MySQL also supports hint_name(@query_block_name tbl_name) ? But we don't? )
             
            h2. 3. Query block naming: QB_NAME hint

            QB_NAME hint is used to assign a name to the query block the hint is in. The Query Block is either a SELECT or a top-level construct of UPDATE or DELETE statement.

            {code:sql}
            SELECT /*+ QB_NAME(foo) */ select_list FROM ...
            {code}

            The name can later be used
            * to refer to a query block, where required
            * to refer to a table as {{table_name@query_block_name}}.

            Hints inside VIEWs are not supported, yet.

            Besides the given name, any query block is given a name {{select#n}}, so one can refer to it like so:
            {code:sql}
            SELECT /*+ BKA(tbl1@`select#1`) */ 1 FROM tbl1 ...;
            {code}
            (TODO: can one control SELECTs inside VIEWs that way? No?)
            (TODO: QB_NAME in CTEs that are used in multiple places?)

            h2. 4. Effect of optimizer hints

            Optimizer can be controlled by
            1. Server variables - optimizer_switch, join_cache_level, etc, etc
            2. Old-style hints
            3. New-style hints

            Old-style hints did not overlap with server variable settings.

            New-style hints are more specific than server variable settings, so they override the server variable settings.

            Should new-style hints override old-style hints? TODO.

            Hints are "narrowly interpreted" and "best effort" - if a hint dictates to do something, like
            {code:sql}
            SELECT /*+ MRR(t1 t1_index1) */ ... FROM t1 ...
            {code}
            that means:
            {quote}
            When considering a query plan that involves using t1_index1 in a way that one can use MRR, use MRR.
            {quote}
            if the query planning is such that use of {{t1_index1}} doesn't allow to use MRR, it won't be used.
            The optimizer may also consider using {{t1_index2}} and pick that over using {{t1_index1}}.
            In such cases the hint is effectively ignored and no warning is given.
            Examples: [^mdev35483-mrr-is-narrow.sql]

            h2. 5. List of hints

            h3. 5.1 NO_RANGE_OPTIMIZATION hint

            It's an index-level hint that disables range optimization for certain index(es):
            {code:sql}
            SELECT /*+ NO_RANGE_OPTIMIZATION(tbl index1 index2) */ * FROM tbl ...
            {code}

            h3. 5.2 NO_ICP hint
            It's an index-level hint that disables Index Condition Pushdown for the indexes. ICP+BKA is disabled as well.
            {code:sql}
            SELECT /*+ NO_ICP(tbl index1 index2) */ * FROM tbl ...
            {code}

            h3. 5.3 MRR and NO_MRR hints

            Index-level hint to force or disable use of MRR.

            {code:sql}
            SELECT /*+ MRR(tbl index1 index2) */ * FROM tbl ...
            SELECT /*+ NO_MRR(tbl index1 index2) */ * FROM tbl ...
            {code}
            This controls
            * MRR optimization for range access ( [^mdev35483-mrr-is-narrow.sql] )
            * BKA [^mdev35483-mrr-controls-bka-partially.sql]

            h3. 5.4 BKA() and NO_BKA() hints
            It's a query block or table-level hint.

            This hint also enables MRR to make BKA possible. (This is different from session variables, where one needs to enable MRR separately).

            This also enables BKAH. TODO what was the reason for this?

            h3. 5.5 BNL() and NO_BNL() hints

            h3. 5.6 MAX_EXECUTION_TIME() hint
            {code:sql}
            SELECT /*+ MAX_EXECUTION_TIME(milliseconds) */ ... FROM... ;
            {code}
            This is a self-contained description of Optimizer Hints in MariaDB, whatever is already implemented in the current patch.

            h1. Optimizer hints in MariaDB

            General idea is to be compatible with MySQL.
            MySQL hint docs: https://dev.mysql.com/doc/refman/8.4/en/optimizer-hints.html

            h2. 1. Hint syntax
            Hints are placed after the main statement verb

            {code:sql}
            UPDATE /*+ hints */ table ...;
            DELETE /*+ hints */ FROM table... ;
            SELECT /*+ hints */ ...
            {code}

            or after the SELECT keyword in any subquery:
            {code:sql}
            SELECT * FROM t1 WHERE a IN (SELECT /*+ hints */ ...)
            {code}

            There can be one or more hints separated with space
            {code}
              hints: hint hint ...
            {code}

            Each individual hint is hint name and arguments. In case there are no arguments,
            the () brackets are still present:

            {code}
            hint: hint_name([arguments])
            {code}

            Incorrect hints produce warnings. (TODO any thing else?)
            Hints that are not ignored are kept in the query text (you can see them in SHOW PROCESSLIST, Slow Query Log, EXPLAIN EXTENDED)
            Hints that were incorrect and were ignored are removed from there.

            h2. 2. Hint hierarchy

            h3. 2.1 Index-level hints
            Index-level hints apply to index(es).
            The syntax is
            {code}
            hint_name(table_name [index_name [, index_name] ...])
            {code}

            where table_name may be query_block@table_name.

            (TODO: MySQL also supports hint_name(@query_block_name tbl_name) ? But we don't? )
             
            h2. 3. Query block naming: QB_NAME hint

            QB_NAME hint is used to assign a name to the query block the hint is in. The Query Block is either a SELECT or a top-level construct of UPDATE or DELETE statement.

            {code:sql}
            SELECT /*+ QB_NAME(foo) */ select_list FROM ...
            {code}

            The name can later be used
            * to refer to a query block, where required
            * to refer to a table as {{table_name@query_block_name}}.

            Hints inside VIEWs are not supported, yet.

            Besides the given name, any query block is given a name {{select#n}}, so one can refer to it like so:
            {code:sql}
            SELECT /*+ BKA(tbl1@`select#1`) */ 1 FROM tbl1 ...;
            {code}
            (TODO: can one control SELECTs inside VIEWs that way? No?)
            (TODO: QB_NAME in CTEs that are used in multiple places?)

            h2. 4. Effect of optimizer hints

            Optimizer can be controlled by
            1. Server variables - optimizer_switch, join_cache_level, etc, etc
            2. Old-style hints
            3. New-style hints

            Old-style hints did not overlap with server variable settings.

            New-style hints are more specific than server variable settings, so they override the server variable settings.

            Should new-style hints override old-style hints? TODO.

            Hints are "narrowly interpreted" and "best effort" - if a hint dictates to do something, like
            {code:sql}
            SELECT /*+ MRR(t1 t1_index1) */ ... FROM t1 ...
            {code}
            that means:
            {quote}
            When considering a query plan that involves using t1_index1 in a way that one can use MRR, use MRR.
            {quote}
            if the query planning is such that use of {{t1_index1}} doesn't allow to use MRR, it won't be used.
            The optimizer may also consider using {{t1_index2}} and pick that over using {{t1_index1}}.
            In such cases the hint is effectively ignored and no warning is given.
            Examples: [^mdev35483-mrr-is-narrow.sql]

            h2. 5. List of hints

            h3. 5.1 NO_RANGE_OPTIMIZATION hint

            It's an index-level hint that disables range optimization for certain index(es):
            {code:sql}
            SELECT /*+ NO_RANGE_OPTIMIZATION(tbl index1 index2) */ * FROM tbl ...
            {code}

            h3. 5.2 NO_ICP hint
            It's an index-level hint that disables Index Condition Pushdown for the indexes. ICP+BKA is disabled as well.
            {code:sql}
            SELECT /*+ NO_ICP(tbl index1 index2) */ * FROM tbl ...
            {code}

            h3. 5.3 MRR and NO_MRR hints

            Index-level hint to force or disable use of MRR.

            {code:sql}
            SELECT /*+ MRR(tbl index1 index2) */ * FROM tbl ...
            SELECT /*+ NO_MRR(tbl index1 index2) */ * FROM tbl ...
            {code}
            This controls
            * MRR optimization for range access ( [^mdev35483-mrr-is-narrow.sql] )
            * BKA [^mdev35483-mrr-controls-bka-partially.sql]

            h3. 5.4 BKA() and NO_BKA() hints
            It's a query block or table-level hint.

            BKA() also enables MRR to make BKA possible. (This is different from session variables, where one needs to enable MRR separately).

            This also enables BKAH. TODO what was the reason for this?

            NO_BKA() seems to enable hash index??

            h3. 5.5 BNL() and NO_BNL() hints

            h3. 5.6 MAX_EXECUTION_TIME() hint
            {code:sql}
            SELECT /*+ MAX_EXECUTION_TIME(milliseconds) */ ... FROM... ;
            {code}
            psergei Sergei Petrunia made changes -
            Attachment mdev35483-no-bka-enables-hash-join.txt [ 74272 ]
            psergei Sergei Petrunia made changes -
            Description This is a self-contained description of Optimizer Hints in MariaDB, whatever is already implemented in the current patch.

            h1. Optimizer hints in MariaDB

            General idea is to be compatible with MySQL.
            MySQL hint docs: https://dev.mysql.com/doc/refman/8.4/en/optimizer-hints.html

            h2. 1. Hint syntax
            Hints are placed after the main statement verb

            {code:sql}
            UPDATE /*+ hints */ table ...;
            DELETE /*+ hints */ FROM table... ;
            SELECT /*+ hints */ ...
            {code}

            or after the SELECT keyword in any subquery:
            {code:sql}
            SELECT * FROM t1 WHERE a IN (SELECT /*+ hints */ ...)
            {code}

            There can be one or more hints separated with space
            {code}
              hints: hint hint ...
            {code}

            Each individual hint is hint name and arguments. In case there are no arguments,
            the () brackets are still present:

            {code}
            hint: hint_name([arguments])
            {code}

            Incorrect hints produce warnings. (TODO any thing else?)
            Hints that are not ignored are kept in the query text (you can see them in SHOW PROCESSLIST, Slow Query Log, EXPLAIN EXTENDED)
            Hints that were incorrect and were ignored are removed from there.

            h2. 2. Hint hierarchy

            h3. 2.1 Index-level hints
            Index-level hints apply to index(es).
            The syntax is
            {code}
            hint_name(table_name [index_name [, index_name] ...])
            {code}

            where table_name may be query_block@table_name.

            (TODO: MySQL also supports hint_name(@query_block_name tbl_name) ? But we don't? )
             
            h2. 3. Query block naming: QB_NAME hint

            QB_NAME hint is used to assign a name to the query block the hint is in. The Query Block is either a SELECT or a top-level construct of UPDATE or DELETE statement.

            {code:sql}
            SELECT /*+ QB_NAME(foo) */ select_list FROM ...
            {code}

            The name can later be used
            * to refer to a query block, where required
            * to refer to a table as {{table_name@query_block_name}}.

            Hints inside VIEWs are not supported, yet.

            Besides the given name, any query block is given a name {{select#n}}, so one can refer to it like so:
            {code:sql}
            SELECT /*+ BKA(tbl1@`select#1`) */ 1 FROM tbl1 ...;
            {code}
            (TODO: can one control SELECTs inside VIEWs that way? No?)
            (TODO: QB_NAME in CTEs that are used in multiple places?)

            h2. 4. Effect of optimizer hints

            Optimizer can be controlled by
            1. Server variables - optimizer_switch, join_cache_level, etc, etc
            2. Old-style hints
            3. New-style hints

            Old-style hints did not overlap with server variable settings.

            New-style hints are more specific than server variable settings, so they override the server variable settings.

            Should new-style hints override old-style hints? TODO.

            Hints are "narrowly interpreted" and "best effort" - if a hint dictates to do something, like
            {code:sql}
            SELECT /*+ MRR(t1 t1_index1) */ ... FROM t1 ...
            {code}
            that means:
            {quote}
            When considering a query plan that involves using t1_index1 in a way that one can use MRR, use MRR.
            {quote}
            if the query planning is such that use of {{t1_index1}} doesn't allow to use MRR, it won't be used.
            The optimizer may also consider using {{t1_index2}} and pick that over using {{t1_index1}}.
            In such cases the hint is effectively ignored and no warning is given.
            Examples: [^mdev35483-mrr-is-narrow.sql]

            h2. 5. List of hints

            h3. 5.1 NO_RANGE_OPTIMIZATION hint

            It's an index-level hint that disables range optimization for certain index(es):
            {code:sql}
            SELECT /*+ NO_RANGE_OPTIMIZATION(tbl index1 index2) */ * FROM tbl ...
            {code}

            h3. 5.2 NO_ICP hint
            It's an index-level hint that disables Index Condition Pushdown for the indexes. ICP+BKA is disabled as well.
            {code:sql}
            SELECT /*+ NO_ICP(tbl index1 index2) */ * FROM tbl ...
            {code}

            h3. 5.3 MRR and NO_MRR hints

            Index-level hint to force or disable use of MRR.

            {code:sql}
            SELECT /*+ MRR(tbl index1 index2) */ * FROM tbl ...
            SELECT /*+ NO_MRR(tbl index1 index2) */ * FROM tbl ...
            {code}
            This controls
            * MRR optimization for range access ( [^mdev35483-mrr-is-narrow.sql] )
            * BKA [^mdev35483-mrr-controls-bka-partially.sql]

            h3. 5.4 BKA() and NO_BKA() hints
            It's a query block or table-level hint.

            BKA() also enables MRR to make BKA possible. (This is different from session variables, where one needs to enable MRR separately).

            This also enables BKAH. TODO what was the reason for this?

            NO_BKA() seems to enable hash index??

            h3. 5.5 BNL() and NO_BNL() hints

            h3. 5.6 MAX_EXECUTION_TIME() hint
            {code:sql}
            SELECT /*+ MAX_EXECUTION_TIME(milliseconds) */ ... FROM... ;
            {code}
            This is a self-contained description of Optimizer Hints in MariaDB, whatever is already implemented in the current patch.

            h1. Optimizer hints in MariaDB

            General idea is to be compatible with MySQL.
            MySQL hint docs: https://dev.mysql.com/doc/refman/8.4/en/optimizer-hints.html

            h2. 1. Hint syntax
            Hints are placed after the main statement verb

            {code:sql}
            UPDATE /*+ hints */ table ...;
            DELETE /*+ hints */ FROM table... ;
            SELECT /*+ hints */ ...
            {code}

            or after the SELECT keyword in any subquery:
            {code:sql}
            SELECT * FROM t1 WHERE a IN (SELECT /*+ hints */ ...)
            {code}

            There can be one or more hints separated with space
            {code}
              hints: hint hint ...
            {code}

            Each individual hint is hint name and arguments. In case there are no arguments,
            the () brackets are still present:

            {code}
            hint: hint_name([arguments])
            {code}

            Incorrect hints produce warnings. (TODO any thing else?)
            Hints that are not ignored are kept in the query text (you can see them in SHOW PROCESSLIST, Slow Query Log, EXPLAIN EXTENDED)
            Hints that were incorrect and were ignored are removed from there.

            h2. 2. Hint hierarchy

            h3. 2.1 Index-level hints
            Index-level hints apply to index(es).
            The syntax is
            {code}
            hint_name(table_name [index_name [, index_name] ...])
            {code}

            where table_name may be query_block@table_name.

            (TODO: MySQL also supports hint_name(@query_block_name tbl_name) ? But we don't? )
             
            h2. 3. Query block naming: QB_NAME hint

            QB_NAME hint is used to assign a name to the query block the hint is in. The Query Block is either a SELECT or a top-level construct of UPDATE or DELETE statement.

            {code:sql}
            SELECT /*+ QB_NAME(foo) */ select_list FROM ...
            {code}

            The name can later be used
            * to refer to a query block, where required
            * to refer to a table as {{table_name@query_block_name}}.

            Hints inside VIEWs are not supported, yet.

            Besides the given name, any query block is given a name {{select#n}}, so one can refer to it like so:
            {code:sql}
            SELECT /*+ BKA(tbl1@`select#1`) */ 1 FROM tbl1 ...;
            {code}
            (TODO: can one control SELECTs inside VIEWs that way? No?)
            (TODO: QB_NAME in CTEs that are used in multiple places?)

            h2. 4. Effect of optimizer hints

            Optimizer can be controlled by
            1. Server variables - optimizer_switch, join_cache_level, etc, etc
            2. Old-style hints
            3. New-style hints

            Old-style hints did not overlap with server variable settings.

            New-style hints are more specific than server variable settings, so they override the server variable settings.

            Should new-style hints override old-style hints? TODO.

            Hints are "narrowly interpreted" and "best effort" - if a hint dictates to do something, like
            {code:sql}
            SELECT /*+ MRR(t1 t1_index1) */ ... FROM t1 ...
            {code}
            that means:
            {quote}
            When considering a query plan that involves using t1_index1 in a way that one can use MRR, use MRR.
            {quote}
            if the query planning is such that use of {{t1_index1}} doesn't allow to use MRR, it won't be used.
            The optimizer may also consider using {{t1_index2}} and pick that over using {{t1_index1}}.
            In such cases the hint is effectively ignored and no warning is given.
            Examples: [^mdev35483-mrr-is-narrow.sql]

            h2. 5. List of hints

            h3. 5.1 NO_RANGE_OPTIMIZATION hint

            It's an index-level hint that disables range optimization for certain index(es):
            {code:sql}
            SELECT /*+ NO_RANGE_OPTIMIZATION(tbl index1 index2) */ * FROM tbl ...
            {code}

            h3. 5.2 NO_ICP hint
            It's an index-level hint that disables Index Condition Pushdown for the indexes. ICP+BKA is disabled as well.
            {code:sql}
            SELECT /*+ NO_ICP(tbl index1 index2) */ * FROM tbl ...
            {code}

            h3. 5.3 MRR and NO_MRR hints

            Index-level hint to force or disable use of MRR.

            {code:sql}
            SELECT /*+ MRR(tbl index1 index2) */ * FROM tbl ...
            SELECT /*+ NO_MRR(tbl index1 index2) */ * FROM tbl ...
            {code}
            This controls
            * MRR optimization for range access ( [^mdev35483-mrr-is-narrow.sql] )
            * BKA [^mdev35483-mrr-controls-bka-partially.sql]

            h3. 5.4 BKA() and NO_BKA() hints
            It's a query block or table-level hint.

            BKA() also enables MRR to make BKA possible. (This is different from session variables, where one needs to enable MRR separately).

            This also enables BKAH. TODO what was the reason for this?

            NO_BKA() seems to enable hash index?? [^mdev35483-no-bka-enables-hash-join.txt]

            h3. 5.5 BNL() and NO_BNL() hints

            h3. 5.6 MAX_EXECUTION_TIME() hint
            {code:sql}
            SELECT /*+ MAX_EXECUTION_TIME(milliseconds) */ ... FROM... ;
            {code}
            psergei Sergei Petrunia made changes -
            Description This is a self-contained description of Optimizer Hints in MariaDB, whatever is already implemented in the current patch.

            h1. Optimizer hints in MariaDB

            General idea is to be compatible with MySQL.
            MySQL hint docs: https://dev.mysql.com/doc/refman/8.4/en/optimizer-hints.html

            h2. 1. Hint syntax
            Hints are placed after the main statement verb

            {code:sql}
            UPDATE /*+ hints */ table ...;
            DELETE /*+ hints */ FROM table... ;
            SELECT /*+ hints */ ...
            {code}

            or after the SELECT keyword in any subquery:
            {code:sql}
            SELECT * FROM t1 WHERE a IN (SELECT /*+ hints */ ...)
            {code}

            There can be one or more hints separated with space
            {code}
              hints: hint hint ...
            {code}

            Each individual hint is hint name and arguments. In case there are no arguments,
            the () brackets are still present:

            {code}
            hint: hint_name([arguments])
            {code}

            Incorrect hints produce warnings. (TODO any thing else?)
            Hints that are not ignored are kept in the query text (you can see them in SHOW PROCESSLIST, Slow Query Log, EXPLAIN EXTENDED)
            Hints that were incorrect and were ignored are removed from there.

            h2. 2. Hint hierarchy

            h3. 2.1 Index-level hints
            Index-level hints apply to index(es).
            The syntax is
            {code}
            hint_name(table_name [index_name [, index_name] ...])
            {code}

            where table_name may be query_block@table_name.

            (TODO: MySQL also supports hint_name(@query_block_name tbl_name) ? But we don't? )
             
            h2. 3. Query block naming: QB_NAME hint

            QB_NAME hint is used to assign a name to the query block the hint is in. The Query Block is either a SELECT or a top-level construct of UPDATE or DELETE statement.

            {code:sql}
            SELECT /*+ QB_NAME(foo) */ select_list FROM ...
            {code}

            The name can later be used
            * to refer to a query block, where required
            * to refer to a table as {{table_name@query_block_name}}.

            Hints inside VIEWs are not supported, yet.

            Besides the given name, any query block is given a name {{select#n}}, so one can refer to it like so:
            {code:sql}
            SELECT /*+ BKA(tbl1@`select#1`) */ 1 FROM tbl1 ...;
            {code}
            (TODO: can one control SELECTs inside VIEWs that way? No?)
            (TODO: QB_NAME in CTEs that are used in multiple places?)

            h2. 4. Effect of optimizer hints

            Optimizer can be controlled by
            1. Server variables - optimizer_switch, join_cache_level, etc, etc
            2. Old-style hints
            3. New-style hints

            Old-style hints did not overlap with server variable settings.

            New-style hints are more specific than server variable settings, so they override the server variable settings.

            Should new-style hints override old-style hints? TODO.

            Hints are "narrowly interpreted" and "best effort" - if a hint dictates to do something, like
            {code:sql}
            SELECT /*+ MRR(t1 t1_index1) */ ... FROM t1 ...
            {code}
            that means:
            {quote}
            When considering a query plan that involves using t1_index1 in a way that one can use MRR, use MRR.
            {quote}
            if the query planning is such that use of {{t1_index1}} doesn't allow to use MRR, it won't be used.
            The optimizer may also consider using {{t1_index2}} and pick that over using {{t1_index1}}.
            In such cases the hint is effectively ignored and no warning is given.
            Examples: [^mdev35483-mrr-is-narrow.sql]

            h2. 5. List of hints

            h3. 5.1 NO_RANGE_OPTIMIZATION hint

            It's an index-level hint that disables range optimization for certain index(es):
            {code:sql}
            SELECT /*+ NO_RANGE_OPTIMIZATION(tbl index1 index2) */ * FROM tbl ...
            {code}

            h3. 5.2 NO_ICP hint
            It's an index-level hint that disables Index Condition Pushdown for the indexes. ICP+BKA is disabled as well.
            {code:sql}
            SELECT /*+ NO_ICP(tbl index1 index2) */ * FROM tbl ...
            {code}

            h3. 5.3 MRR and NO_MRR hints

            Index-level hint to force or disable use of MRR.

            {code:sql}
            SELECT /*+ MRR(tbl index1 index2) */ * FROM tbl ...
            SELECT /*+ NO_MRR(tbl index1 index2) */ * FROM tbl ...
            {code}
            This controls
            * MRR optimization for range access ( [^mdev35483-mrr-is-narrow.sql] )
            * BKA [^mdev35483-mrr-controls-bka-partially.sql]

            h3. 5.4 BKA() and NO_BKA() hints
            It's a query block or table-level hint.

            BKA() also enables MRR to make BKA possible. (This is different from session variables, where one needs to enable MRR separately).

            This also enables BKAH. TODO what was the reason for this?

            NO_BKA() seems to enable hash index?? [^mdev35483-no-bka-enables-hash-join.txt]

            h3. 5.5 BNL() and NO_BNL() hints

            h3. 5.6 MAX_EXECUTION_TIME() hint
            {code:sql}
            SELECT /*+ MAX_EXECUTION_TIME(milliseconds) */ ... FROM... ;
            {code}
            This is a self-contained description of Optimizer Hints in MariaDB, whatever is already implemented in the current patch.

            h1. Optimizer hints in MariaDB

            General idea is to be compatible with MySQL.
            MySQL hint docs: https://dev.mysql.com/doc/refman/8.4/en/optimizer-hints.html

            h2. 1. Hint syntax
            Hints are placed after the main statement verb

            {code:sql}
            UPDATE /*+ hints */ table ...;
            DELETE /*+ hints */ FROM table... ;
            SELECT /*+ hints */ ...
            {code}

            or after the SELECT keyword in any subquery:
            {code:sql}
            SELECT * FROM t1 WHERE a IN (SELECT /*+ hints */ ...)
            {code}

            There can be one or more hints separated with space
            {code}
              hints: hint hint ...
            {code}

            Each individual hint is hint name and arguments. In case there are no arguments,
            the () brackets are still present:

            {code}
            hint: hint_name([arguments])
            {code}

            Incorrect hints produce warnings. (TODO any thing else?)
            Hints that are not ignored are kept in the query text (you can see them in SHOW PROCESSLIST, Slow Query Log, EXPLAIN EXTENDED)
            Hints that were incorrect and were ignored are removed from there.

            h2. 2. Hint hierarchy

            h3. 2.1 Index-level hints
            Index-level hints apply to index(es).
            The syntax is
            {code}
            hint_name(table_name [index_name [, index_name] ...])
            {code}

            where table_name may be query_block@table_name.

            (TODO: MySQL also supports hint_name(@query_block_name tbl_name) ? But we don't? )
             
            h2. 3. Query block naming: QB_NAME hint

            QB_NAME hint is used to assign a name to the query block the hint is in. The Query Block is either a SELECT or a top-level construct of UPDATE or DELETE statement.

            {code:sql}
            SELECT /*+ QB_NAME(foo) */ select_list FROM ...
            {code}

            The name can later be used
            * to refer to a query block, where required
            * to refer to a table as {{table_name@query_block_name}}.

            Hints inside VIEWs are not supported, yet.

            Besides the given name, any query block is given a name {{select#n}}, so one can refer to it like so:
            {code:sql}
            SELECT /*+ BKA(tbl1@`select#1`) */ 1 FROM tbl1 ...;
            {code}
            (TODO: can one control SELECTs inside VIEWs that way? No?)
            (TODO: QB_NAME in CTEs that are used in multiple places?)

            h2. 4. Effect of optimizer hints

            Optimizer can be controlled by
            1. Server variables - optimizer_switch, join_cache_level, etc, etc
            2. Old-style hints
            3. New-style hints

            Old-style hints did not overlap with server variable settings.

            New-style hints are more specific than server variable settings, so they override the server variable settings.

            Should new-style hints override old-style hints? TODO.

            Hints are "narrowly interpreted" and "best effort" - if a hint dictates to do something, like
            {code:sql}
            SELECT /*+ MRR(t1 t1_index1) */ ... FROM t1 ...
            {code}
            that means:
            {quote}
            When considering a query plan that involves using t1_index1 in a way that one can use MRR, use MRR.
            {quote}
            if the query planning is such that use of {{t1_index1}} doesn't allow to use MRR, it won't be used.
            The optimizer may also consider using {{t1_index2}} and pick that over using {{t1_index1}}.
            In such cases the hint is effectively ignored and no warning is given.
            Examples: [^mdev35483-mrr-is-narrow.sql]

            h2. 5. List of hints

            h3. 5.1 NO_RANGE_OPTIMIZATION hint

            It's an index-level hint that disables range optimization for certain index(es):
            {code:sql}
            SELECT /*+ NO_RANGE_OPTIMIZATION(tbl index1 index2) */ * FROM tbl ...
            {code}

            h3. 5.2 NO_ICP hint
            It's an index-level hint that disables Index Condition Pushdown for the indexes. ICP+BKA is disabled as well.
            {code:sql}
            SELECT /*+ NO_ICP(tbl index1 index2) */ * FROM tbl ...
            {code}

            h3. 5.3 MRR and NO_MRR hints

            Index-level hint to force or disable use of MRR.

            {code:sql}
            SELECT /*+ MRR(tbl index1 index2) */ * FROM tbl ...
            SELECT /*+ NO_MRR(tbl index1 index2) */ * FROM tbl ...
            {code}
            This controls
            * MRR optimization for range access ( [^mdev35483-mrr-is-narrow.sql] )
            * BKA [^mdev35483-mrr-controls-bka-partially.sql]

            h3. 5.4 BKA() and NO_BKA() hints
            It's a query block or table-level hint.

            BKA() also enables MRR to make BKA possible. (This is different from session variables, where one needs to enable MRR separately).

            This also enables BKAH. TODO what was the reason for this?

            NO_BKA() seems to enable hash index?? [^mdev35483-no-bka-enables-hash-join.txt]

            h3. 5.5 BNL() and NO_BNL() hints

            h3. 5.6 MAX_EXECUTION_TIME() hint

            This is a global hint. It limits query execution time. A query that doesn't finish in the time specified will be aborted with an error.

            {code:sql}
            SELECT /*+ MAX_EXECUTION_TIME(milliseconds) */ ... FROM... ;
            {code}
            Note: if the {{@@max_statement_time}} is set, the hint will be ignored and warning produced.
            TODO: This contradicts with the stated principle that "New-style hints are more specific than server variable settings, so they override the server variable settings".
            psergei Sergei Petrunia made changes -
            Description This is a self-contained description of Optimizer Hints in MariaDB, whatever is already implemented in the current patch.

            h1. Optimizer hints in MariaDB

            General idea is to be compatible with MySQL.
            MySQL hint docs: https://dev.mysql.com/doc/refman/8.4/en/optimizer-hints.html

            h2. 1. Hint syntax
            Hints are placed after the main statement verb

            {code:sql}
            UPDATE /*+ hints */ table ...;
            DELETE /*+ hints */ FROM table... ;
            SELECT /*+ hints */ ...
            {code}

            or after the SELECT keyword in any subquery:
            {code:sql}
            SELECT * FROM t1 WHERE a IN (SELECT /*+ hints */ ...)
            {code}

            There can be one or more hints separated with space
            {code}
              hints: hint hint ...
            {code}

            Each individual hint is hint name and arguments. In case there are no arguments,
            the () brackets are still present:

            {code}
            hint: hint_name([arguments])
            {code}

            Incorrect hints produce warnings. (TODO any thing else?)
            Hints that are not ignored are kept in the query text (you can see them in SHOW PROCESSLIST, Slow Query Log, EXPLAIN EXTENDED)
            Hints that were incorrect and were ignored are removed from there.

            h2. 2. Hint hierarchy

            h3. 2.1 Index-level hints
            Index-level hints apply to index(es).
            The syntax is
            {code}
            hint_name(table_name [index_name [, index_name] ...])
            {code}

            where table_name may be query_block@table_name.

            (TODO: MySQL also supports hint_name(@query_block_name tbl_name) ? But we don't? )
             
            h2. 3. Query block naming: QB_NAME hint

            QB_NAME hint is used to assign a name to the query block the hint is in. The Query Block is either a SELECT or a top-level construct of UPDATE or DELETE statement.

            {code:sql}
            SELECT /*+ QB_NAME(foo) */ select_list FROM ...
            {code}

            The name can later be used
            * to refer to a query block, where required
            * to refer to a table as {{table_name@query_block_name}}.

            Hints inside VIEWs are not supported, yet.

            Besides the given name, any query block is given a name {{select#n}}, so one can refer to it like so:
            {code:sql}
            SELECT /*+ BKA(tbl1@`select#1`) */ 1 FROM tbl1 ...;
            {code}
            (TODO: can one control SELECTs inside VIEWs that way? No?)
            (TODO: QB_NAME in CTEs that are used in multiple places?)

            h2. 4. Effect of optimizer hints

            Optimizer can be controlled by
            1. Server variables - optimizer_switch, join_cache_level, etc, etc
            2. Old-style hints
            3. New-style hints

            Old-style hints did not overlap with server variable settings.

            New-style hints are more specific than server variable settings, so they override the server variable settings.

            Should new-style hints override old-style hints? TODO.

            Hints are "narrowly interpreted" and "best effort" - if a hint dictates to do something, like
            {code:sql}
            SELECT /*+ MRR(t1 t1_index1) */ ... FROM t1 ...
            {code}
            that means:
            {quote}
            When considering a query plan that involves using t1_index1 in a way that one can use MRR, use MRR.
            {quote}
            if the query planning is such that use of {{t1_index1}} doesn't allow to use MRR, it won't be used.
            The optimizer may also consider using {{t1_index2}} and pick that over using {{t1_index1}}.
            In such cases the hint is effectively ignored and no warning is given.
            Examples: [^mdev35483-mrr-is-narrow.sql]

            h2. 5. List of hints

            h3. 5.1 NO_RANGE_OPTIMIZATION hint

            It's an index-level hint that disables range optimization for certain index(es):
            {code:sql}
            SELECT /*+ NO_RANGE_OPTIMIZATION(tbl index1 index2) */ * FROM tbl ...
            {code}

            h3. 5.2 NO_ICP hint
            It's an index-level hint that disables Index Condition Pushdown for the indexes. ICP+BKA is disabled as well.
            {code:sql}
            SELECT /*+ NO_ICP(tbl index1 index2) */ * FROM tbl ...
            {code}

            h3. 5.3 MRR and NO_MRR hints

            Index-level hint to force or disable use of MRR.

            {code:sql}
            SELECT /*+ MRR(tbl index1 index2) */ * FROM tbl ...
            SELECT /*+ NO_MRR(tbl index1 index2) */ * FROM tbl ...
            {code}
            This controls
            * MRR optimization for range access ( [^mdev35483-mrr-is-narrow.sql] )
            * BKA [^mdev35483-mrr-controls-bka-partially.sql]

            h3. 5.4 BKA() and NO_BKA() hints
            It's a query block or table-level hint.

            BKA() also enables MRR to make BKA possible. (This is different from session variables, where one needs to enable MRR separately).

            This also enables BKAH. TODO what was the reason for this?

            NO_BKA() seems to enable hash index?? [^mdev35483-no-bka-enables-hash-join.txt]

            h3. 5.5 BNL() and NO_BNL() hints

            h3. 5.6 MAX_EXECUTION_TIME() hint

            This is a global hint. It limits query execution time. A query that doesn't finish in the time specified will be aborted with an error.

            {code:sql}
            SELECT /*+ MAX_EXECUTION_TIME(milliseconds) */ ... FROM... ;
            {code}
            Note: if the {{@@max_statement_time}} is set, the hint will be ignored and warning produced.
            TODO: This contradicts with the stated principle that "New-style hints are more specific than server variable settings, so they override the server variable settings".
            This is a self-contained description of Optimizer Hints in MariaDB, whatever is already implemented in the current patch.

            h1. Optimizer hints in MariaDB

            General idea is to be compatible with MySQL.
            MySQL hint docs: https://dev.mysql.com/doc/refman/8.4/en/optimizer-hints.html

            h2. 1. Hint syntax
            Hints are placed after the main statement verb

            {code:sql}
            UPDATE /*+ hints */ table ...;
            DELETE /*+ hints */ FROM table... ;
            SELECT /*+ hints */ ...
            {code}

            or after the SELECT keyword in any subquery:
            {code:sql}
            SELECT * FROM t1 WHERE a IN (SELECT /*+ hints */ ...)
            {code}

            There can be one or more hints separated with space
            {code}
              hints: hint hint ...
            {code}

            Each individual hint is hint name and arguments. In case there are no arguments,
            the () brackets are still present:

            {code}
            hint: hint_name([arguments])
            {code}

            Incorrect hints produce warnings. (TODO any thing else?)
            Hints that are not ignored are kept in the query text (you can see them in SHOW PROCESSLIST, Slow Query Log, EXPLAIN EXTENDED)
            Hints that were incorrect and were ignored are removed from there.

            h2. 2. Hint hierarchy

            h3. 2.1 Index-level hints
            Index-level hints apply to index(es).
            The syntax is
            {code}
            hint_name(table_name [index_name [, index_name] ...])
            {code}

            where table_name may be query_block@table_name.

            (TODO: MySQL also supports hint_name(@query_block_name tbl_name) ? But we don't? )
             
            h2. 3. Query block naming: QB_NAME hint

            QB_NAME hint is used to assign a name to the query block the hint is in. The Query Block is either a SELECT or a top-level construct of UPDATE or DELETE statement.

            {code:sql}
            SELECT /*+ QB_NAME(foo) */ select_list FROM ...
            {code}

            The name can later be used
            * to refer to a query block, where required
            * to refer to a table as {{table_name@query_block_name}}.

            Hints inside VIEWs are not supported, yet.

            Besides the given name, any query block is given a name {{select#n}}, so one can refer to it like so:
            {code:sql}
            SELECT /*+ BKA(tbl1@`select#1`) */ 1 FROM tbl1 ...;
            {code}
            (TODO: can one control SELECTs inside VIEWs that way? No?)
            (TODO: QB_NAME in CTEs that are used in multiple places?)

            h2. 4. Effect of optimizer hints

            Optimizer can be controlled by
            1. Server variables - optimizer_switch, join_cache_level, etc, etc
            2. Old-style hints
            3. New-style hints

            Old-style hints did not overlap with server variable settings.

            New-style hints are more specific than server variable settings, so they override the server variable settings.

            Should new-style hints override old-style hints? TODO.

            Hints are "narrowly interpreted" and "best effort" - if a hint dictates to do something, like
            {code:sql}
            SELECT /*+ MRR(t1 t1_index1) */ ... FROM t1 ...
            {code}
            that means:
            {quote}
            When considering a query plan that involves using t1_index1 in a way that one can use MRR, use MRR.
            {quote}
            if the query planning is such that use of {{t1_index1}} doesn't allow to use MRR, it won't be used.
            The optimizer may also consider using {{t1_index2}} and pick that over using {{t1_index1}}.
            In such cases the hint is effectively ignored and no warning is given.
            Examples: [^mdev35483-mrr-is-narrow.sql]

            h2. 5. List of hints

            h3. 5.1 NO_RANGE_OPTIMIZATION hint

            It's an index-level hint that disables range optimization for certain index(es):
            {code:sql}
            SELECT /*+ NO_RANGE_OPTIMIZATION(tbl index1 index2) */ * FROM tbl ...
            {code}

            h3. 5.2 NO_ICP hint
            It's an index-level hint that disables Index Condition Pushdown for the indexes. ICP+BKA is disabled as well.
            {code:sql}
            SELECT /*+ NO_ICP(tbl index1 index2) */ * FROM tbl ...
            {code}

            h3. 5.3 MRR and NO_MRR hints

            Index-level hint to force or disable use of MRR.

            {code:sql}
            SELECT /*+ MRR(tbl index1 index2) */ * FROM tbl ...
            SELECT /*+ NO_MRR(tbl index1 index2) */ * FROM tbl ...
            {code}
            This controls
            * MRR optimization for range access ( [^mdev35483-mrr-is-narrow.sql] )
            * BKA [^mdev35483-mrr-controls-bka-partially.sql]

            h3. 5.4 BKA() and NO_BKA() hints
            It's a query block or table-level hint.

            BKA() also enables MRR to make BKA possible. (This is different from session variables, where one needs to enable MRR separately).

            This also enables BKAH. TODO what was the reason for this?

            NO_BKA() seems to enable hash index?? [^mdev35483-no-bka-enables-hash-join.txt]

            h3. 5.5 BNL() and NO_BNL() hints

            h3. 5.6 MAX_EXECUTION_TIME() hint
            Example:
            {code:sql}
            SELECT /*+ MAX_EXECUTION_TIME(milliseconds) */ ... ;
            {code}

            This is a global hint. It limits query execution time. A query that doesn't finish in the time specified will be aborted with an error.

            Note: if the {{@@max_statement_time}} is set, the hint will be ignored and warning produced.
            TODO: This contradicts with the stated principle that "New-style hints are more specific than server variable settings, so they override the server variable settings".
            psergei Sergei Petrunia made changes -
            Description This is a self-contained description of Optimizer Hints in MariaDB, whatever is already implemented in the current patch.

            h1. Optimizer hints in MariaDB

            General idea is to be compatible with MySQL.
            MySQL hint docs: https://dev.mysql.com/doc/refman/8.4/en/optimizer-hints.html

            h2. 1. Hint syntax
            Hints are placed after the main statement verb

            {code:sql}
            UPDATE /*+ hints */ table ...;
            DELETE /*+ hints */ FROM table... ;
            SELECT /*+ hints */ ...
            {code}

            or after the SELECT keyword in any subquery:
            {code:sql}
            SELECT * FROM t1 WHERE a IN (SELECT /*+ hints */ ...)
            {code}

            There can be one or more hints separated with space
            {code}
              hints: hint hint ...
            {code}

            Each individual hint is hint name and arguments. In case there are no arguments,
            the () brackets are still present:

            {code}
            hint: hint_name([arguments])
            {code}

            Incorrect hints produce warnings. (TODO any thing else?)
            Hints that are not ignored are kept in the query text (you can see them in SHOW PROCESSLIST, Slow Query Log, EXPLAIN EXTENDED)
            Hints that were incorrect and were ignored are removed from there.

            h2. 2. Hint hierarchy

            h3. 2.1 Index-level hints
            Index-level hints apply to index(es).
            The syntax is
            {code}
            hint_name(table_name [index_name [, index_name] ...])
            {code}

            where table_name may be query_block@table_name.

            (TODO: MySQL also supports hint_name(@query_block_name tbl_name) ? But we don't? )
             
            h2. 3. Query block naming: QB_NAME hint

            QB_NAME hint is used to assign a name to the query block the hint is in. The Query Block is either a SELECT or a top-level construct of UPDATE or DELETE statement.

            {code:sql}
            SELECT /*+ QB_NAME(foo) */ select_list FROM ...
            {code}

            The name can later be used
            * to refer to a query block, where required
            * to refer to a table as {{table_name@query_block_name}}.

            Hints inside VIEWs are not supported, yet.

            Besides the given name, any query block is given a name {{select#n}}, so one can refer to it like so:
            {code:sql}
            SELECT /*+ BKA(tbl1@`select#1`) */ 1 FROM tbl1 ...;
            {code}
            (TODO: can one control SELECTs inside VIEWs that way? No?)
            (TODO: QB_NAME in CTEs that are used in multiple places?)

            h2. 4. Effect of optimizer hints

            Optimizer can be controlled by
            1. Server variables - optimizer_switch, join_cache_level, etc, etc
            2. Old-style hints
            3. New-style hints

            Old-style hints did not overlap with server variable settings.

            New-style hints are more specific than server variable settings, so they override the server variable settings.

            Should new-style hints override old-style hints? TODO.

            Hints are "narrowly interpreted" and "best effort" - if a hint dictates to do something, like
            {code:sql}
            SELECT /*+ MRR(t1 t1_index1) */ ... FROM t1 ...
            {code}
            that means:
            {quote}
            When considering a query plan that involves using t1_index1 in a way that one can use MRR, use MRR.
            {quote}
            if the query planning is such that use of {{t1_index1}} doesn't allow to use MRR, it won't be used.
            The optimizer may also consider using {{t1_index2}} and pick that over using {{t1_index1}}.
            In such cases the hint is effectively ignored and no warning is given.
            Examples: [^mdev35483-mrr-is-narrow.sql]

            h2. 5. List of hints

            h3. 5.1 NO_RANGE_OPTIMIZATION hint

            It's an index-level hint that disables range optimization for certain index(es):
            {code:sql}
            SELECT /*+ NO_RANGE_OPTIMIZATION(tbl index1 index2) */ * FROM tbl ...
            {code}

            h3. 5.2 NO_ICP hint
            It's an index-level hint that disables Index Condition Pushdown for the indexes. ICP+BKA is disabled as well.
            {code:sql}
            SELECT /*+ NO_ICP(tbl index1 index2) */ * FROM tbl ...
            {code}

            h3. 5.3 MRR and NO_MRR hints

            Index-level hint to force or disable use of MRR.

            {code:sql}
            SELECT /*+ MRR(tbl index1 index2) */ * FROM tbl ...
            SELECT /*+ NO_MRR(tbl index1 index2) */ * FROM tbl ...
            {code}
            This controls
            * MRR optimization for range access ( [^mdev35483-mrr-is-narrow.sql] )
            * BKA [^mdev35483-mrr-controls-bka-partially.sql]

            h3. 5.4 BKA() and NO_BKA() hints
            It's a query block or table-level hint.

            BKA() also enables MRR to make BKA possible. (This is different from session variables, where one needs to enable MRR separately).

            This also enables BKAH. TODO what was the reason for this?

            NO_BKA() seems to enable hash index?? [^mdev35483-no-bka-enables-hash-join.txt]

            h3. 5.5 BNL() and NO_BNL() hints

            h3. 5.6 MAX_EXECUTION_TIME() hint
            Example:
            {code:sql}
            SELECT /*+ MAX_EXECUTION_TIME(milliseconds) */ ... ;
            {code}

            This is a global hint. It limits query execution time. A query that doesn't finish in the time specified will be aborted with an error.

            Note: if the {{@@max_statement_time}} is set, the hint will be ignored and warning produced.
            TODO: This contradicts with the stated principle that "New-style hints are more specific than server variable settings, so they override the server variable settings".
            This is a self-contained description of Optimizer Hints in MariaDB, whatever is already implemented in the current patch.

            h1. Optimizer hints in MariaDB

            General idea is to be compatible with MySQL.
            MySQL hint docs: https://dev.mysql.com/doc/refman/8.4/en/optimizer-hints.html

            h2. 1. Hint syntax
            Hints are placed after the main statement verb

            {code:sql}
            UPDATE /*+ hints */ table ...;
            DELETE /*+ hints */ FROM table... ;
            SELECT /*+ hints */ ...
            {code}

            or after the SELECT keyword in any subquery:
            {code:sql}
            SELECT * FROM t1 WHERE a IN (SELECT /*+ hints */ ...)
            {code}

            There can be one or more hints separated with space
            {code}
              hints: hint hint ...
            {code}

            Each individual hint is hint name and arguments. In case there are no arguments,
            the () brackets are still present:

            {code}
            hint: hint_name([arguments])
            {code}

            Incorrect hints produce warnings. (TODO any thing else?)
            Hints that are not ignored are kept in the query text (you can see them in SHOW PROCESSLIST, Slow Query Log, EXPLAIN EXTENDED)
            Hints that were incorrect and were ignored are removed from there.

            h2. 2. Hint hierarchy

            h3. 2.1 Index-level hints
            Index-level hints apply to index(es).
            The syntax is
            {code}
            hint_name(table_name [index_name [, index_name] ...])
            {code}

            where table_name may be query_block@table_name.

            (TODO: MySQL also supports hint_name(@query_block_name tbl_name) ? But we don't? )
             
            h2. 3. Query block naming: QB_NAME hint

            QB_NAME hint is used to assign a name to the query block the hint is in. The Query Block is either a SELECT or a top-level construct of UPDATE or DELETE statement.

            {code:sql}
            SELECT /*+ QB_NAME(foo) */ select_list FROM ...
            {code}

            The name can later be used
            * to refer to a query block, where required
            * to refer to a table as {{table_name@query_block_name}}.

            Hints inside VIEWs are not supported, yet.

            Besides the given name, any query block is given a name {{select#n}}, so one can refer to it like so:
            {code:sql}
            SELECT /*+ BKA(tbl1@`select#1`) */ 1 FROM tbl1 ...;
            {code}
            (TODO: can one control SELECTs inside VIEWs that way? No?)
            (TODO: QB_NAME in CTEs that are used in multiple places?)

            h2. 4. Effect of optimizer hints

            Optimizer can be controlled by
            1. Server variables - optimizer_switch, join_cache_level, etc, etc
            2. Old-style hints
            3. New-style hints

            Old-style hints did not overlap with server variable settings.

            New-style hints are more specific than server variable settings, so they override the server variable settings.

            Should new-style hints override old-style hints? TODO.

            Hints are "narrowly interpreted" and "best effort" - if a hint dictates to do something, like
            {code:sql}
            SELECT /*+ MRR(t1 t1_index1) */ ... FROM t1 ...
            {code}
            that means:
            {quote}
            When considering a query plan that involves using t1_index1 in a way that one can use MRR, use MRR.
            {quote}
            if the query planning is such that use of {{t1_index1}} doesn't allow to use MRR, it won't be used.
            The optimizer may also consider using {{t1_index2}} and pick that over using {{t1_index1}}.
            In such cases the hint is effectively ignored and no warning is given.
            Examples: [^mdev35483-mrr-is-narrow.sql]

            h2. 5. List of hints

            h3. 5.1 NO_RANGE_OPTIMIZATION hint

            It's an index-level hint that disables range optimization for certain index(es):
            {code:sql}
            SELECT /*+ NO_RANGE_OPTIMIZATION(tbl index1 index2) */ * FROM tbl ...
            {code}

            h3. 5.2 NO_ICP hint
            It's an index-level hint that disables Index Condition Pushdown for the indexes. ICP+BKA is disabled as well.
            {code:sql}
            SELECT /*+ NO_ICP(tbl index1 index2) */ * FROM tbl ...
            {code}

            h3. 5.3 MRR and NO_MRR hints

            Index-level hint to force or disable use of MRR.

            {code:sql}
            SELECT /*+ MRR(tbl index1 index2) */ * FROM tbl ...
            SELECT /*+ NO_MRR(tbl index1 index2) */ * FROM tbl ...
            {code}
            This controls
            * MRR optimization for range access ( [^mdev35483-mrr-is-narrow.sql] )
            * BKA [^mdev35483-mrr-controls-bka-partially.sql]

            h3. 5.4 BKA() and NO_BKA() hints
            It's a query block or table-level hint.

            BKA() also enables MRR to make BKA possible. (This is different from session variables, where one needs to enable MRR separately).

            This also enables BKAH. TODO what was the reason for this?

            NO_BKA() seems to enable BNL-H: [^mdev35483-no-bka-enables-hash-join.txt] ?

            h3. 5.5 BNL() and NO_BNL() hints

            In MySQL this controls hash join, so in MariaDB it controls BNL-H.

            h3. 5.6 MAX_EXECUTION_TIME() hint
            Example:
            {code:sql}
            SELECT /*+ MAX_EXECUTION_TIME(milliseconds) */ ... ;
            {code}

            This is a global hint. It limits query execution time. A query that doesn't finish in the time specified will be aborted with an error.

            Note: if the {{@@max_statement_time}} is set, the hint will be ignored and warning produced.
            TODO: This contradicts with the stated principle that "New-style hints are more specific than server variable settings, so they override the server variable settings".
            psergei Sergei Petrunia made changes -
            Description This is a self-contained description of Optimizer Hints in MariaDB, whatever is already implemented in the current patch.

            h1. Optimizer hints in MariaDB

            General idea is to be compatible with MySQL.
            MySQL hint docs: https://dev.mysql.com/doc/refman/8.4/en/optimizer-hints.html

            h2. 1. Hint syntax
            Hints are placed after the main statement verb

            {code:sql}
            UPDATE /*+ hints */ table ...;
            DELETE /*+ hints */ FROM table... ;
            SELECT /*+ hints */ ...
            {code}

            or after the SELECT keyword in any subquery:
            {code:sql}
            SELECT * FROM t1 WHERE a IN (SELECT /*+ hints */ ...)
            {code}

            There can be one or more hints separated with space
            {code}
              hints: hint hint ...
            {code}

            Each individual hint is hint name and arguments. In case there are no arguments,
            the () brackets are still present:

            {code}
            hint: hint_name([arguments])
            {code}

            Incorrect hints produce warnings. (TODO any thing else?)
            Hints that are not ignored are kept in the query text (you can see them in SHOW PROCESSLIST, Slow Query Log, EXPLAIN EXTENDED)
            Hints that were incorrect and were ignored are removed from there.

            h2. 2. Hint hierarchy

            h3. 2.1 Index-level hints
            Index-level hints apply to index(es).
            The syntax is
            {code}
            hint_name(table_name [index_name [, index_name] ...])
            {code}

            where table_name may be query_block@table_name.

            (TODO: MySQL also supports hint_name(@query_block_name tbl_name) ? But we don't? )
             
            h2. 3. Query block naming: QB_NAME hint

            QB_NAME hint is used to assign a name to the query block the hint is in. The Query Block is either a SELECT or a top-level construct of UPDATE or DELETE statement.

            {code:sql}
            SELECT /*+ QB_NAME(foo) */ select_list FROM ...
            {code}

            The name can later be used
            * to refer to a query block, where required
            * to refer to a table as {{table_name@query_block_name}}.

            Hints inside VIEWs are not supported, yet.

            Besides the given name, any query block is given a name {{select#n}}, so one can refer to it like so:
            {code:sql}
            SELECT /*+ BKA(tbl1@`select#1`) */ 1 FROM tbl1 ...;
            {code}
            (TODO: can one control SELECTs inside VIEWs that way? No?)
            (TODO: QB_NAME in CTEs that are used in multiple places?)

            h2. 4. Effect of optimizer hints

            Optimizer can be controlled by
            1. Server variables - optimizer_switch, join_cache_level, etc, etc
            2. Old-style hints
            3. New-style hints

            Old-style hints did not overlap with server variable settings.

            New-style hints are more specific than server variable settings, so they override the server variable settings.

            Should new-style hints override old-style hints? TODO.

            Hints are "narrowly interpreted" and "best effort" - if a hint dictates to do something, like
            {code:sql}
            SELECT /*+ MRR(t1 t1_index1) */ ... FROM t1 ...
            {code}
            that means:
            {quote}
            When considering a query plan that involves using t1_index1 in a way that one can use MRR, use MRR.
            {quote}
            if the query planning is such that use of {{t1_index1}} doesn't allow to use MRR, it won't be used.
            The optimizer may also consider using {{t1_index2}} and pick that over using {{t1_index1}}.
            In such cases the hint is effectively ignored and no warning is given.
            Examples: [^mdev35483-mrr-is-narrow.sql]

            h2. 5. List of hints

            h3. 5.1 NO_RANGE_OPTIMIZATION hint

            It's an index-level hint that disables range optimization for certain index(es):
            {code:sql}
            SELECT /*+ NO_RANGE_OPTIMIZATION(tbl index1 index2) */ * FROM tbl ...
            {code}

            h3. 5.2 NO_ICP hint
            It's an index-level hint that disables Index Condition Pushdown for the indexes. ICP+BKA is disabled as well.
            {code:sql}
            SELECT /*+ NO_ICP(tbl index1 index2) */ * FROM tbl ...
            {code}

            h3. 5.3 MRR and NO_MRR hints

            Index-level hint to force or disable use of MRR.

            {code:sql}
            SELECT /*+ MRR(tbl index1 index2) */ * FROM tbl ...
            SELECT /*+ NO_MRR(tbl index1 index2) */ * FROM tbl ...
            {code}
            This controls
            * MRR optimization for range access ( [^mdev35483-mrr-is-narrow.sql] )
            * BKA [^mdev35483-mrr-controls-bka-partially.sql]

            h3. 5.4 BKA() and NO_BKA() hints
            It's a query block or table-level hint.

            BKA() also enables MRR to make BKA possible. (This is different from session variables, where one needs to enable MRR separately).

            This also enables BKAH. TODO what was the reason for this?

            NO_BKA() seems to enable BNL-H: [^mdev35483-no-bka-enables-hash-join.txt] ?

            h3. 5.5 BNL() and NO_BNL() hints

            In MySQL this controls hash join, so in MariaDB it controls BNL-H.

            h3. 5.6 MAX_EXECUTION_TIME() hint
            Example:
            {code:sql}
            SELECT /*+ MAX_EXECUTION_TIME(milliseconds) */ ... ;
            {code}

            This is a global hint. It limits query execution time. A query that doesn't finish in the time specified will be aborted with an error.

            Note: if the {{@@max_statement_time}} is set, the hint will be ignored and warning produced.
            TODO: This contradicts with the stated principle that "New-style hints are more specific than server variable settings, so they override the server variable settings".
            This is a self-contained description of Optimizer Hints in MariaDB, whatever is already implemented in the current patch.

            h1. Optimizer hints in MariaDB

            General idea is to be compatible with MySQL.
            MySQL hint docs: https://dev.mysql.com/doc/refman/8.4/en/optimizer-hints.html

            h2. 1. Hint syntax
            Hints are placed after the main statement verb

            {code:sql}
            UPDATE /*+ hints */ table ...;
            DELETE /*+ hints */ FROM table... ;
            SELECT /*+ hints */ ...
            {code}

            or after the SELECT keyword in any subquery:
            {code:sql}
            SELECT * FROM t1 WHERE a IN (SELECT /*+ hints */ ...)
            {code}

            There can be one or more hints separated with space
            {code}
              hints: hint hint ...
            {code}

            Each individual hint is hint name and arguments. In case there are no arguments,
            the () brackets are still present:

            {code}
            hint: hint_name([arguments])
            {code}

            Incorrect hints produce warnings. (TODO anything else?)
            Hints that are not ignored are kept in the query text (you can see them in SHOW PROCESSLIST, Slow Query Log, EXPLAIN EXTENDED)
            Hints that were incorrect and were ignored are removed from there.

            h2. 2. Hint hierarchy

            h3. 2.1 Index-level hints
            Index-level hints apply to index(es).
            The syntax is
            {code}
            hint_name(table_name [index_name [, index_name] ...])
            {code}

            where table_name may be query_block@table_name.

            (TODO: MySQL also supports hint_name(@query_block_name tbl_name) ? But we don't? )
             
            h2. 3. Query block naming: QB_NAME hint

            QB_NAME hint is used to assign a name to the query block the hint is in. The Query Block is either a SELECT or a top-level construct of UPDATE or DELETE statement.

            {code:sql}
            SELECT /*+ QB_NAME(foo) */ select_list FROM ...
            {code}

            The name can later be used
            * to refer to a query block, where required
            * to refer to a table as {{table_name@query_block_name}}.

            Hints inside VIEWs are not supported, yet. One can neither use hints in VIEW definitions, nor control query plans inside non-merged VIEWs (This is because QB_NAME binding is done "early", before we know that some tables are VIEWs)

            Besides the given name, any query block is given a name {{select#n}}, so one can refer to it like so:
            {code:sql}
            SELECT /*+ BKA(tbl1@`select#1`) */ 1 FROM tbl1 ...;
            {code}
            (TODO: QB_NAME in CTEs that are used in multiple places?)

            h2. 4. Effect of optimizer hints

            Optimizer can be controlled by
            1. Server variables - optimizer_switch, join_cache_level, etc, etc
            2. Old-style hints
            3. New-style hints

            Old-style hints did not overlap with server variable settings.

            New-style hints are more specific than server variable settings, so they override the server variable settings.

            Should new-style hints override old-style hints? TODO.

            Hints are "narrowly interpreted" and "best effort" - if a hint dictates to do something, like
            {code:sql}
            SELECT /*+ MRR(t1 t1_index1) */ ... FROM t1 ...
            {code}
            that means:
            {quote}
            When considering a query plan that involves using t1_index1 in a way that one can use MRR, use MRR.
            {quote}
            if the query planning is such that use of {{t1_index1}} doesn't allow to use MRR, it won't be used.
            The optimizer may also consider using {{t1_index2}} and pick that over using {{t1_index1}}.
            In such cases the hint is effectively ignored and no warning is given.
            Examples: [^mdev35483-mrr-is-narrow.sql]

            h2. 5. List of hints

            h3. 5.1 NO_RANGE_OPTIMIZATION hint

            It's an index-level hint that disables range optimization for certain index(es):
            {code:sql}
            SELECT /*+ NO_RANGE_OPTIMIZATION(tbl index1 index2) */ * FROM tbl ...
            {code}

            h3. 5.2 NO_ICP hint
            It's an index-level hint that disables Index Condition Pushdown for the indexes. ICP+BKA is disabled as well.
            {code:sql}
            SELECT /*+ NO_ICP(tbl index1 index2) */ * FROM tbl ...
            {code}

            h3. 5.3 MRR and NO_MRR hints

            Index-level hint to force or disable use of MRR.

            {code:sql}
            SELECT /*+ MRR(tbl index1 index2) */ * FROM tbl ...
            SELECT /*+ NO_MRR(tbl index1 index2) */ * FROM tbl ...
            {code}
            This controls
            * MRR optimization for range access ( [^mdev35483-mrr-is-narrow.sql] )
            * BKA [^mdev35483-mrr-controls-bka-partially.sql]

            h3. 5.4 BKA() and NO_BKA() hints
            It's a query block or table-level hint.

            BKA() also enables MRR to make BKA possible. (This is different from session variables, where one needs to enable MRR separately).

            This also enables BKAH. TODO what was the reason for this?

            NO_BKA() seems to enable BNL-H: [^mdev35483-no-bka-enables-hash-join.txt] ?

            h3. 5.5 BNL() and NO_BNL() hints

            In MySQL this controls hash join, so in MariaDB it controls BNL-H.

            TODO: this seems to fail a fairly trivial example:

            h3. 5.6 MAX_EXECUTION_TIME() hint
            Example:
            {code:sql}
            SELECT /*+ MAX_EXECUTION_TIME(milliseconds) */ ... ;
            {code}

            This is a global hint. It limits query execution time. A query that doesn't finish in the time specified will be aborted with an error.

            Note: if the {{@@max_statement_time}} is set, the hint will be ignored and warning produced.
            TODO: This contradicts with the stated principle that "New-style hints are more specific than server variable settings, so they override the server variable settings".
            psergei Sergei Petrunia made changes -
            Attachment mdev35483-bnl-fails-why.txt [ 74273 ]
            psergei Sergei Petrunia made changes -
            Description This is a self-contained description of Optimizer Hints in MariaDB, whatever is already implemented in the current patch.

            h1. Optimizer hints in MariaDB

            General idea is to be compatible with MySQL.
            MySQL hint docs: https://dev.mysql.com/doc/refman/8.4/en/optimizer-hints.html

            h2. 1. Hint syntax
            Hints are placed after the main statement verb

            {code:sql}
            UPDATE /*+ hints */ table ...;
            DELETE /*+ hints */ FROM table... ;
            SELECT /*+ hints */ ...
            {code}

            or after the SELECT keyword in any subquery:
            {code:sql}
            SELECT * FROM t1 WHERE a IN (SELECT /*+ hints */ ...)
            {code}

            There can be one or more hints separated with space
            {code}
              hints: hint hint ...
            {code}

            Each individual hint is hint name and arguments. In case there are no arguments,
            the () brackets are still present:

            {code}
            hint: hint_name([arguments])
            {code}

            Incorrect hints produce warnings. (TODO anything else?)
            Hints that are not ignored are kept in the query text (you can see them in SHOW PROCESSLIST, Slow Query Log, EXPLAIN EXTENDED)
            Hints that were incorrect and were ignored are removed from there.

            h2. 2. Hint hierarchy

            h3. 2.1 Index-level hints
            Index-level hints apply to index(es).
            The syntax is
            {code}
            hint_name(table_name [index_name [, index_name] ...])
            {code}

            where table_name may be query_block@table_name.

            (TODO: MySQL also supports hint_name(@query_block_name tbl_name) ? But we don't? )
             
            h2. 3. Query block naming: QB_NAME hint

            QB_NAME hint is used to assign a name to the query block the hint is in. The Query Block is either a SELECT or a top-level construct of UPDATE or DELETE statement.

            {code:sql}
            SELECT /*+ QB_NAME(foo) */ select_list FROM ...
            {code}

            The name can later be used
            * to refer to a query block, where required
            * to refer to a table as {{table_name@query_block_name}}.

            Hints inside VIEWs are not supported, yet. One can neither use hints in VIEW definitions, nor control query plans inside non-merged VIEWs (This is because QB_NAME binding is done "early", before we know that some tables are VIEWs)

            Besides the given name, any query block is given a name {{select#n}}, so one can refer to it like so:
            {code:sql}
            SELECT /*+ BKA(tbl1@`select#1`) */ 1 FROM tbl1 ...;
            {code}
            (TODO: QB_NAME in CTEs that are used in multiple places?)

            h2. 4. Effect of optimizer hints

            Optimizer can be controlled by
            1. Server variables - optimizer_switch, join_cache_level, etc, etc
            2. Old-style hints
            3. New-style hints

            Old-style hints did not overlap with server variable settings.

            New-style hints are more specific than server variable settings, so they override the server variable settings.

            Should new-style hints override old-style hints? TODO.

            Hints are "narrowly interpreted" and "best effort" - if a hint dictates to do something, like
            {code:sql}
            SELECT /*+ MRR(t1 t1_index1) */ ... FROM t1 ...
            {code}
            that means:
            {quote}
            When considering a query plan that involves using t1_index1 in a way that one can use MRR, use MRR.
            {quote}
            if the query planning is such that use of {{t1_index1}} doesn't allow to use MRR, it won't be used.
            The optimizer may also consider using {{t1_index2}} and pick that over using {{t1_index1}}.
            In such cases the hint is effectively ignored and no warning is given.
            Examples: [^mdev35483-mrr-is-narrow.sql]

            h2. 5. List of hints

            h3. 5.1 NO_RANGE_OPTIMIZATION hint

            It's an index-level hint that disables range optimization for certain index(es):
            {code:sql}
            SELECT /*+ NO_RANGE_OPTIMIZATION(tbl index1 index2) */ * FROM tbl ...
            {code}

            h3. 5.2 NO_ICP hint
            It's an index-level hint that disables Index Condition Pushdown for the indexes. ICP+BKA is disabled as well.
            {code:sql}
            SELECT /*+ NO_ICP(tbl index1 index2) */ * FROM tbl ...
            {code}

            h3. 5.3 MRR and NO_MRR hints

            Index-level hint to force or disable use of MRR.

            {code:sql}
            SELECT /*+ MRR(tbl index1 index2) */ * FROM tbl ...
            SELECT /*+ NO_MRR(tbl index1 index2) */ * FROM tbl ...
            {code}
            This controls
            * MRR optimization for range access ( [^mdev35483-mrr-is-narrow.sql] )
            * BKA [^mdev35483-mrr-controls-bka-partially.sql]

            h3. 5.4 BKA() and NO_BKA() hints
            It's a query block or table-level hint.

            BKA() also enables MRR to make BKA possible. (This is different from session variables, where one needs to enable MRR separately).

            This also enables BKAH. TODO what was the reason for this?

            NO_BKA() seems to enable BNL-H: [^mdev35483-no-bka-enables-hash-join.txt] ?

            h3. 5.5 BNL() and NO_BNL() hints

            In MySQL this controls hash join, so in MariaDB it controls BNL-H.

            TODO: this seems to fail a fairly trivial example:

            h3. 5.6 MAX_EXECUTION_TIME() hint
            Example:
            {code:sql}
            SELECT /*+ MAX_EXECUTION_TIME(milliseconds) */ ... ;
            {code}

            This is a global hint. It limits query execution time. A query that doesn't finish in the time specified will be aborted with an error.

            Note: if the {{@@max_statement_time}} is set, the hint will be ignored and warning produced.
            TODO: This contradicts with the stated principle that "New-style hints are more specific than server variable settings, so they override the server variable settings".
            This is a self-contained description of Optimizer Hints in MariaDB, whatever is already implemented in the current patch.

            h1. Optimizer hints in MariaDB

            General idea is to be compatible with MySQL.
            MySQL hint docs: https://dev.mysql.com/doc/refman/8.4/en/optimizer-hints.html

            h2. 1. Hint syntax
            Hints are placed after the main statement verb

            {code:sql}
            UPDATE /*+ hints */ table ...;
            DELETE /*+ hints */ FROM table... ;
            SELECT /*+ hints */ ...
            {code}

            or after the SELECT keyword in any subquery:
            {code:sql}
            SELECT * FROM t1 WHERE a IN (SELECT /*+ hints */ ...)
            {code}

            There can be one or more hints separated with space
            {code}
              hints: hint hint ...
            {code}

            Each individual hint is hint name and arguments. In case there are no arguments,
            the () brackets are still present:

            {code}
            hint: hint_name([arguments])
            {code}

            Incorrect hints produce warnings. (TODO anything else?)
            Hints that are not ignored are kept in the query text (you can see them in SHOW PROCESSLIST, Slow Query Log, EXPLAIN EXTENDED)
            Hints that were incorrect and were ignored are removed from there.

            h2. 2. Hint hierarchy

            h3. 2.1 Index-level hints
            Index-level hints apply to index(es).
            The syntax is
            {code}
            hint_name(table_name [index_name [, index_name] ...])
            {code}

            where table_name may be query_block@table_name.

            (TODO: MySQL also supports hint_name(@query_block_name tbl_name) ? But we don't? )
             
            h2. 3. Query block naming: QB_NAME hint

            QB_NAME hint is used to assign a name to the query block the hint is in. The Query Block is either a SELECT or a top-level construct of UPDATE or DELETE statement.

            {code:sql}
            SELECT /*+ QB_NAME(foo) */ select_list FROM ...
            {code}

            The name can later be used
            * to refer to a query block, where required
            * to refer to a table as {{table_name@query_block_name}}.

            Hints inside VIEWs are not supported, yet. One can neither use hints in VIEW definitions, nor control query plans inside non-merged VIEWs (This is because QB_NAME binding is done "early", before we know that some tables are VIEWs)

            Besides the given name, any query block is given a name {{select#n}}, so one can refer to it like so:
            {code:sql}
            SELECT /*+ BKA(tbl1@`select#1`) */ 1 FROM tbl1 ...;
            {code}
            (TODO: QB_NAME in CTEs that are used in multiple places?)

            h2. 4. Effect of optimizer hints

            Optimizer can be controlled by
            1. Server variables - optimizer_switch, join_cache_level, etc, etc
            2. Old-style hints
            3. New-style hints

            Old-style hints did not overlap with server variable settings.

            New-style hints are more specific than server variable settings, so they override the server variable settings.

            Should new-style hints override old-style hints? TODO.

            Hints are "narrowly interpreted" and "best effort" - if a hint dictates to do something, like
            {code:sql}
            SELECT /*+ MRR(t1 t1_index1) */ ... FROM t1 ...
            {code}
            that means:
            {quote}
            When considering a query plan that involves using t1_index1 in a way that one can use MRR, use MRR.
            {quote}
            if the query planning is such that use of {{t1_index1}} doesn't allow to use MRR, it won't be used.
            The optimizer may also consider using {{t1_index2}} and pick that over using {{t1_index1}}.
            In such cases the hint is effectively ignored and no warning is given.
            Examples: [^mdev35483-mrr-is-narrow.sql]

            h2. 5. List of hints

            h3. 5.1 NO_RANGE_OPTIMIZATION hint

            It's an index-level hint that disables range optimization for certain index(es):
            {code:sql}
            SELECT /*+ NO_RANGE_OPTIMIZATION(tbl index1 index2) */ * FROM tbl ...
            {code}

            h3. 5.2 NO_ICP hint
            It's an index-level hint that disables Index Condition Pushdown for the indexes. ICP+BKA is disabled as well.
            {code:sql}
            SELECT /*+ NO_ICP(tbl index1 index2) */ * FROM tbl ...
            {code}

            h3. 5.3 MRR and NO_MRR hints

            Index-level hint to force or disable use of MRR.

            {code:sql}
            SELECT /*+ MRR(tbl index1 index2) */ * FROM tbl ...
            SELECT /*+ NO_MRR(tbl index1 index2) */ * FROM tbl ...
            {code}
            This controls
            * MRR optimization for range access ( [^mdev35483-mrr-is-narrow.sql] )
            * BKA [^mdev35483-mrr-controls-bka-partially.sql]

            h3. 5.4 BKA() and NO_BKA() hints
            It's a query block or table-level hint.

            BKA() also enables MRR to make BKA possible. (This is different from session variables, where one needs to enable MRR separately).

            This also enables BKAH. TODO what was the reason for this?

            NO_BKA() seems to enable BNL-H: [^mdev35483-no-bka-enables-hash-join.txt] ?

            h3. 5.5 BNL() and NO_BNL() hints

            In MySQL this controls hash join, so in MariaDB it controls BNL-H.

            TODO: this seems to fail a fairly trivial example: [^mdev35483-bnl-fails-why.txt]

            h3. 5.6 MAX_EXECUTION_TIME() hint
            Example:
            {code:sql}
            SELECT /*+ MAX_EXECUTION_TIME(milliseconds) */ ... ;
            {code}

            This is a global hint. It limits query execution time. A query that doesn't finish in the time specified will be aborted with an error.

            Note: if the {{@@max_statement_time}} is set, the hint will be ignored and warning produced.
            TODO: This contradicts with the stated principle that "New-style hints are more specific than server variable settings, so they override the server variable settings".
            psergei Sergei Petrunia made changes -
            Description This is a self-contained description of Optimizer Hints in MariaDB, whatever is already implemented in the current patch.

            h1. Optimizer hints in MariaDB

            General idea is to be compatible with MySQL.
            MySQL hint docs: https://dev.mysql.com/doc/refman/8.4/en/optimizer-hints.html

            h2. 1. Hint syntax
            Hints are placed after the main statement verb

            {code:sql}
            UPDATE /*+ hints */ table ...;
            DELETE /*+ hints */ FROM table... ;
            SELECT /*+ hints */ ...
            {code}

            or after the SELECT keyword in any subquery:
            {code:sql}
            SELECT * FROM t1 WHERE a IN (SELECT /*+ hints */ ...)
            {code}

            There can be one or more hints separated with space
            {code}
              hints: hint hint ...
            {code}

            Each individual hint is hint name and arguments. In case there are no arguments,
            the () brackets are still present:

            {code}
            hint: hint_name([arguments])
            {code}

            Incorrect hints produce warnings. (TODO anything else?)
            Hints that are not ignored are kept in the query text (you can see them in SHOW PROCESSLIST, Slow Query Log, EXPLAIN EXTENDED)
            Hints that were incorrect and were ignored are removed from there.

            h2. 2. Hint hierarchy

            h3. 2.1 Index-level hints
            Index-level hints apply to index(es).
            The syntax is
            {code}
            hint_name(table_name [index_name [, index_name] ...])
            {code}

            where table_name may be query_block@table_name.

            (TODO: MySQL also supports hint_name(@query_block_name tbl_name) ? But we don't? )
             
            h2. 3. Query block naming: QB_NAME hint

            QB_NAME hint is used to assign a name to the query block the hint is in. The Query Block is either a SELECT or a top-level construct of UPDATE or DELETE statement.

            {code:sql}
            SELECT /*+ QB_NAME(foo) */ select_list FROM ...
            {code}

            The name can later be used
            * to refer to a query block, where required
            * to refer to a table as {{table_name@query_block_name}}.

            Hints inside VIEWs are not supported, yet. One can neither use hints in VIEW definitions, nor control query plans inside non-merged VIEWs (This is because QB_NAME binding is done "early", before we know that some tables are VIEWs)

            Besides the given name, any query block is given a name {{select#n}}, so one can refer to it like so:
            {code:sql}
            SELECT /*+ BKA(tbl1@`select#1`) */ 1 FROM tbl1 ...;
            {code}
            (TODO: QB_NAME in CTEs that are used in multiple places?)

            h2. 4. Effect of optimizer hints

            Optimizer can be controlled by
            1. Server variables - optimizer_switch, join_cache_level, etc, etc
            2. Old-style hints
            3. New-style hints

            Old-style hints did not overlap with server variable settings.

            New-style hints are more specific than server variable settings, so they override the server variable settings.

            Should new-style hints override old-style hints? TODO.

            Hints are "narrowly interpreted" and "best effort" - if a hint dictates to do something, like
            {code:sql}
            SELECT /*+ MRR(t1 t1_index1) */ ... FROM t1 ...
            {code}
            that means:
            {quote}
            When considering a query plan that involves using t1_index1 in a way that one can use MRR, use MRR.
            {quote}
            if the query planning is such that use of {{t1_index1}} doesn't allow to use MRR, it won't be used.
            The optimizer may also consider using {{t1_index2}} and pick that over using {{t1_index1}}.
            In such cases the hint is effectively ignored and no warning is given.
            Examples: [^mdev35483-mrr-is-narrow.sql]

            h2. 5. List of hints

            h3. 5.1 NO_RANGE_OPTIMIZATION hint

            It's an index-level hint that disables range optimization for certain index(es):
            {code:sql}
            SELECT /*+ NO_RANGE_OPTIMIZATION(tbl index1 index2) */ * FROM tbl ...
            {code}

            h3. 5.2 NO_ICP hint
            It's an index-level hint that disables Index Condition Pushdown for the indexes. ICP+BKA is disabled as well.
            {code:sql}
            SELECT /*+ NO_ICP(tbl index1 index2) */ * FROM tbl ...
            {code}

            h3. 5.3 MRR and NO_MRR hints

            Index-level hint to force or disable use of MRR.

            {code:sql}
            SELECT /*+ MRR(tbl index1 index2) */ * FROM tbl ...
            SELECT /*+ NO_MRR(tbl index1 index2) */ * FROM tbl ...
            {code}
            This controls
            * MRR optimization for range access ( [^mdev35483-mrr-is-narrow.sql] )
            * BKA [^mdev35483-mrr-controls-bka-partially.sql]

            h3. 5.4 BKA() and NO_BKA() hints
            It's a query block or table-level hint.

            BKA() also enables MRR to make BKA possible. (This is different from session variables, where one needs to enable MRR separately).

            This also enables BKAH. TODO what was the reason for this?

            NO_BKA() seems to enable BNL-H: [^mdev35483-no-bka-enables-hash-join.txt] ?

            h3. 5.5 BNL() and NO_BNL() hints

            In MySQL this controls hash join, so in MariaDB it controls BNL-H.

            TODO: this seems to fail a fairly trivial example: [^mdev35483-bnl-fails-why.txt]

            h3. 5.6 MAX_EXECUTION_TIME() hint
            Example:
            {code:sql}
            SELECT /*+ MAX_EXECUTION_TIME(milliseconds) */ ... ;
            {code}

            This is a global hint. It limits query execution time. A query that doesn't finish in the time specified will be aborted with an error.

            Note: if the {{@@max_statement_time}} is set, the hint will be ignored and warning produced.
            TODO: This contradicts with the stated principle that "New-style hints are more specific than server variable settings, so they override the server variable settings".
            This is a self-contained description of Optimizer Hints in MariaDB, whatever is already implemented in the current patch.

            h1. Optimizer hints in MariaDB

            General idea is to be compatible with MySQL.
            MySQL hint docs: https://dev.mysql.com/doc/refman/8.4/en/optimizer-hints.html

            h2. 1. Hint syntax
            Hints are placed after the main statement verb

            {code:sql}
            UPDATE /*+ hints */ table ...;
            DELETE /*+ hints */ FROM table... ;
            SELECT /*+ hints */ ...
            {code}

            or after the SELECT keyword in any subquery:
            {code:sql}
            SELECT * FROM t1 WHERE a IN (SELECT /*+ hints */ ...)
            {code}

            There can be one or more hints separated with space
            {code}
              hints: hint hint ...
            {code}

            Each individual hint is hint name and arguments. In case there are no arguments,
            the () brackets are still present:

            {code}
            hint: hint_name([arguments])
            {code}

            Incorrect hints produce warnings. (TODO anything else?)
            Hints that are not ignored are kept in the query text (you can see them in SHOW PROCESSLIST, Slow Query Log, EXPLAIN EXTENDED)
            Hints that were incorrect and were ignored are removed from there.

            h2. 2. Hint hierarchy

            h3. 2.1 Index-level hints
            Index-level hints apply to index(es).
            The syntax is
            {code}
            hint_name(table_name [index_name [, index_name] ...])
            {code}

            where table_name may be query_block@table_name.

            (TODO: MySQL also supports hint_name(@query_block_name tbl_name) ? But we don't? )
             
            h2. 3. Query block naming: QB_NAME hint

            QB_NAME hint is used to assign a name to the query block the hint is in. The Query Block is either a SELECT or a top-level construct of UPDATE or DELETE statement.

            {code:sql}
            SELECT /*+ QB_NAME(foo) */ select_list FROM ...
            {code}

            The name can later be used
            * to refer to a query block, where required
            * to refer to a table as {{table_name@query_block_name}}.

            Hints inside VIEWs are not supported, yet. One can neither use hints in VIEW definitions, nor control query plans inside non-merged VIEWs (This is because QB_NAME binding is done "early", before we know that some tables are VIEWs)

            Besides the given name, any query block is given a name {{select#n}}, so one can refer to it like so:
            {code:sql}
            SELECT /*+ BKA(tbl1@`select#1`) */ 1 FROM tbl1 ...;
            {code}
            (TODO: QB_NAME in CTEs that are used in multiple places?)

            h2. 4. Effect of optimizer hints

            Optimizer can be controlled by
            1. Server variables - optimizer_switch, join_cache_level, etc, etc
            2. Old-style hints
            3. New-style hints

            Old-style hints did not overlap with server variable settings.

            New-style hints are more specific than server variable settings, so they override the server variable settings.

            Should new-style hints override old-style hints? TODO.

            Hints are "narrowly interpreted" and "best effort" - if a hint dictates to do something, like
            {code:sql}
            SELECT /*+ MRR(t1 t1_index1) */ ... FROM t1 ...
            {code}
            that means:
            {quote}
            When considering a query plan that involves using t1_index1 in a way that one can use MRR, use MRR.
            {quote}
            if the query planning is such that use of {{t1_index1}} doesn't allow to use MRR, it won't be used.
            The optimizer may also consider using {{t1_index2}} and pick that over using {{t1_index1}}.
            In such cases the hint is effectively ignored and no warning is given.
            Examples: [^mdev35483-mrr-is-narrow.sql]

            h2. 5. List of hints

            h3. 5.1 NO_RANGE_OPTIMIZATION hint

            It's an index-level hint that disables range optimization for certain index(es):
            {code:sql}
            SELECT /*+ NO_RANGE_OPTIMIZATION(tbl index1 index2) */ * FROM tbl ...
            {code}

            h3. 5.2 NO_ICP hint
            It's an index-level hint that disables Index Condition Pushdown for the indexes. ICP+BKA is disabled as well.
            {code:sql}
            SELECT /*+ NO_ICP(tbl index1 index2) */ * FROM tbl ...
            {code}

            h3. 5.3 MRR and NO_MRR hints

            Index-level hint to force or disable use of MRR.

            {code:sql}
            SELECT /*+ MRR(tbl index1 index2) */ * FROM tbl ...
            SELECT /*+ NO_MRR(tbl index1 index2) */ * FROM tbl ...
            {code}
            This controls
            * MRR optimization for range access ( [^mdev35483-mrr-is-narrow.sql] )
            * BKA [^mdev35483-mrr-controls-bka-partially.sql]

            h3. 5.4 BKA() and NO_BKA() hints
            It's a query block or table-level hint.

            BKA() also enables MRR to make BKA possible. (This is different from session variables, where one needs to enable MRR separately).

            This also enables BKAH. TODO what was the reason for this?

            TODO: NO_BKA() seems to lso enable BNL-H: [^mdev35483-no-bka-enables-hash-join.txt] ?

            h3. 5.5 BNL() and NO_BNL() hints

            In MySQL this controls hash join, so in MariaDB it controls BNL-H.

            The implementation is "BNL() hint effectively increases join_cache_level up to 4 "
            TODO: this seems to fail a fairly trivial example: [^mdev35483-bnl-fails-why.txt] ?

            h3. 5.6 MAX_EXECUTION_TIME() hint
            Example:
            {code:sql}
            SELECT /*+ MAX_EXECUTION_TIME(milliseconds) */ ... ;
            {code}

            This is a global hint. It limits query execution time. A query that doesn't finish in the time specified will be aborted with an error.

            Note: if the {{@@max_statement_time}} is set, the hint will be ignored and warning produced.
            TODO: This contradicts with the stated principle that "New-style hints are more specific than server variable settings, so they override the server variable settings".
            psergei Sergei Petrunia made changes -
            Description This is a self-contained description of Optimizer Hints in MariaDB, whatever is already implemented in the current patch.

            h1. Optimizer hints in MariaDB

            General idea is to be compatible with MySQL.
            MySQL hint docs: https://dev.mysql.com/doc/refman/8.4/en/optimizer-hints.html

            h2. 1. Hint syntax
            Hints are placed after the main statement verb

            {code:sql}
            UPDATE /*+ hints */ table ...;
            DELETE /*+ hints */ FROM table... ;
            SELECT /*+ hints */ ...
            {code}

            or after the SELECT keyword in any subquery:
            {code:sql}
            SELECT * FROM t1 WHERE a IN (SELECT /*+ hints */ ...)
            {code}

            There can be one or more hints separated with space
            {code}
              hints: hint hint ...
            {code}

            Each individual hint is hint name and arguments. In case there are no arguments,
            the () brackets are still present:

            {code}
            hint: hint_name([arguments])
            {code}

            Incorrect hints produce warnings. (TODO anything else?)
            Hints that are not ignored are kept in the query text (you can see them in SHOW PROCESSLIST, Slow Query Log, EXPLAIN EXTENDED)
            Hints that were incorrect and were ignored are removed from there.

            h2. 2. Hint hierarchy

            h3. 2.1 Index-level hints
            Index-level hints apply to index(es).
            The syntax is
            {code}
            hint_name(table_name [index_name [, index_name] ...])
            {code}

            where table_name may be query_block@table_name.

            (TODO: MySQL also supports hint_name(@query_block_name tbl_name) ? But we don't? )
             
            h2. 3. Query block naming: QB_NAME hint

            QB_NAME hint is used to assign a name to the query block the hint is in. The Query Block is either a SELECT or a top-level construct of UPDATE or DELETE statement.

            {code:sql}
            SELECT /*+ QB_NAME(foo) */ select_list FROM ...
            {code}

            The name can later be used
            * to refer to a query block, where required
            * to refer to a table as {{table_name@query_block_name}}.

            Hints inside VIEWs are not supported, yet. One can neither use hints in VIEW definitions, nor control query plans inside non-merged VIEWs (This is because QB_NAME binding is done "early", before we know that some tables are VIEWs)

            Besides the given name, any query block is given a name {{select#n}}, so one can refer to it like so:
            {code:sql}
            SELECT /*+ BKA(tbl1@`select#1`) */ 1 FROM tbl1 ...;
            {code}
            (TODO: QB_NAME in CTEs that are used in multiple places?)

            h2. 4. Effect of optimizer hints

            Optimizer can be controlled by
            1. Server variables - optimizer_switch, join_cache_level, etc, etc
            2. Old-style hints
            3. New-style hints

            Old-style hints did not overlap with server variable settings.

            New-style hints are more specific than server variable settings, so they override the server variable settings.

            Should new-style hints override old-style hints? TODO.

            Hints are "narrowly interpreted" and "best effort" - if a hint dictates to do something, like
            {code:sql}
            SELECT /*+ MRR(t1 t1_index1) */ ... FROM t1 ...
            {code}
            that means:
            {quote}
            When considering a query plan that involves using t1_index1 in a way that one can use MRR, use MRR.
            {quote}
            if the query planning is such that use of {{t1_index1}} doesn't allow to use MRR, it won't be used.
            The optimizer may also consider using {{t1_index2}} and pick that over using {{t1_index1}}.
            In such cases the hint is effectively ignored and no warning is given.
            Examples: [^mdev35483-mrr-is-narrow.sql]

            h2. 5. List of hints

            h3. 5.1 NO_RANGE_OPTIMIZATION hint

            It's an index-level hint that disables range optimization for certain index(es):
            {code:sql}
            SELECT /*+ NO_RANGE_OPTIMIZATION(tbl index1 index2) */ * FROM tbl ...
            {code}

            h3. 5.2 NO_ICP hint
            It's an index-level hint that disables Index Condition Pushdown for the indexes. ICP+BKA is disabled as well.
            {code:sql}
            SELECT /*+ NO_ICP(tbl index1 index2) */ * FROM tbl ...
            {code}

            h3. 5.3 MRR and NO_MRR hints

            Index-level hint to force or disable use of MRR.

            {code:sql}
            SELECT /*+ MRR(tbl index1 index2) */ * FROM tbl ...
            SELECT /*+ NO_MRR(tbl index1 index2) */ * FROM tbl ...
            {code}
            This controls
            * MRR optimization for range access ( [^mdev35483-mrr-is-narrow.sql] )
            * BKA [^mdev35483-mrr-controls-bka-partially.sql]

            h3. 5.4 BKA() and NO_BKA() hints
            It's a query block or table-level hint.

            BKA() also enables MRR to make BKA possible. (This is different from session variables, where one needs to enable MRR separately).

            This also enables BKAH. TODO what was the reason for this?

            TODO: NO_BKA() seems to lso enable BNL-H: [^mdev35483-no-bka-enables-hash-join.txt] ?

            h3. 5.5 BNL() and NO_BNL() hints

            In MySQL this controls hash join, so in MariaDB it controls BNL-H.

            The implementation is "BNL() hint effectively increases join_cache_level up to 4 "
            TODO: this seems to fail a fairly trivial example: [^mdev35483-bnl-fails-why.txt] ?

            h3. 5.6 MAX_EXECUTION_TIME() hint
            Example:
            {code:sql}
            SELECT /*+ MAX_EXECUTION_TIME(milliseconds) */ ... ;
            {code}

            This is a global hint. It limits query execution time. A query that doesn't finish in the time specified will be aborted with an error.

            Note: if the {{@@max_statement_time}} is set, the hint will be ignored and warning produced.
            TODO: This contradicts with the stated principle that "New-style hints are more specific than server variable settings, so they override the server variable settings".
            This is a self-contained description of Optimizer Hints in MariaDB, whatever is already implemented in the current patch.

            h1. Optimizer hints in MariaDB

            General idea is to be compatible with MySQL.
            MySQL hint docs: https://dev.mysql.com/doc/refman/8.4/en/optimizer-hints.html

            h2. 1. Hint syntax
            Hints are placed after the main statement verb

            {code:sql}
            UPDATE /*+ hints */ table ...;
            DELETE /*+ hints */ FROM table... ;
            SELECT /*+ hints */ ...
            {code}

            or after the SELECT keyword in any subquery:
            {code:sql}
            SELECT * FROM t1 WHERE a IN (SELECT /*+ hints */ ...)
            {code}

            There can be one or more hints separated with space
            {code}
              hints: hint hint ...
            {code}

            Each individual hint is hint name and arguments. In case there are no arguments,
            the () brackets are still present:

            {code}
            hint: hint_name([arguments])
            {code}

            Incorrect hints produce warnings. (TODO anything else?)
            Hints that are not ignored are kept in the query text (you can see them in SHOW PROCESSLIST, Slow Query Log, EXPLAIN EXTENDED)
            Hints that were incorrect and were ignored are removed from there.

            h2. 2. Hint hierarchy

            h3. 2.1 Index-level hints
            Index-level hints apply to index(es).
            The syntax is
            {code}
            hint_name(table_name [index_name [, index_name] ...])
            {code}

            where table_name may be query_block@table_name.

            (TODO: MySQL also supports hint_name(@query_block_name tbl_name) ? But we don't? )
             
            h2. 3. Query block naming: QB_NAME hint

            QB_NAME hint is used to assign a name to the query block the hint is in. The Query Block is either a SELECT or a top-level construct of UPDATE or DELETE statement.

            {code:sql}
            SELECT /*+ QB_NAME(foo) */ select_list FROM ...
            {code}

            The name can later be used
            * to refer to a query block, where required
            * to refer to a table as {{table_name@query_block_name}}.

            Hints inside VIEWs are not supported, yet. One can neither use hints in VIEW definitions, nor control query plans inside non-merged VIEWs (This is because QB_NAME binding is done "early", before we know that some tables are VIEWs)

            Besides the given name, any query block is given a name {{select#n}}, so one can refer to it like so:
            {code:sql}
            SELECT /*+ BKA(tbl1@`select#1`) */ 1 FROM tbl1 ...;
            {code}
            (TODO: QB_NAME in CTEs that are used in multiple places?)

            h2. 4. Effect of optimizer hints

            Optimizer can be controlled by
            1. Server variables - optimizer_switch, join_cache_level, etc, etc
            2. Old-style hints
            3. New-style hints

            Old-style hints did not overlap with server variable settings.

            New-style hints are more specific than server variable settings, so they override the server variable settings.

            Should new-style hints override old-style hints? TODO.

            Hints are "narrowly interpreted" and "best effort" - if a hint dictates to do something, like
            {code:sql}
            SELECT /*+ MRR(t1 t1_index1) */ ... FROM t1 ...
            {code}
            that means:
            {quote}
            When considering a query plan that involves using t1_index1 in a way that one can use MRR, use MRR.
            {quote}
            if the query planning is such that use of {{t1_index1}} doesn't allow to use MRR, it won't be used.
            The optimizer may also consider using {{t1_index2}} and pick that over using {{t1_index1}}.
            In such cases the hint is effectively ignored and no warning is given.
            Examples: [^mdev35483-mrr-is-narrow.sql]

            h2. 5. List of hints

            h3. 5.1 NO_RANGE_OPTIMIZATION hint

            It's an index-level hint that disables range optimization for certain index(es):
            {code:sql}
            SELECT /*+ NO_RANGE_OPTIMIZATION(tbl index1 index2) */ * FROM tbl ...
            {code}

            h3. 5.2 NO_ICP hint
            It's an index-level hint that disables Index Condition Pushdown for the indexes. ICP+BKA is disabled as well.
            {code:sql}
            SELECT /*+ NO_ICP(tbl index1 index2) */ * FROM tbl ...
            {code}

            h3. 5.3 MRR and NO_MRR hints

            Index-level hint to force or disable use of MRR.

            {code:sql}
            SELECT /*+ MRR(tbl index1 index2) */ * FROM tbl ...
            SELECT /*+ NO_MRR(tbl index1 index2) */ * FROM tbl ...
            {code}
            This controls
            * MRR optimization for range access ( [^mdev35483-mrr-is-narrow.sql] )
            * BKA [^mdev35483-mrr-controls-bka-partially.sql]

            h3. 5.4 BKA() and NO_BKA() hints
            It's a query block or table-level hint.

            BKA() also enables MRR to make BKA possible. (This is different from session variables, where one needs to enable MRR separately).

            This also enables BKAH. TODO what was the reason for this?

            TODO: NO_BKA() seems to lso enable BNL-H: [^mdev35483-no-bka-enables-hash-join.txt] ?

            h3. 5.5 BNL() and NO_BNL() hints

            In MySQL this controls hash join, so in MariaDB it controls BNL-H.

            The implementation is "BNL() hint effectively increases join_cache_level up to 4 "
            TODO: this seems to fail a fairly trivial example: [^mdev35483-bnl-fails-why.txt] ?

            h3. 5.6 MAX_EXECUTION_TIME() hint
            Example:
            {code:sql}
            SELECT /*+ MAX_EXECUTION_TIME(milliseconds) */ ... ;
            {code}

            This is a global hint. It limits query execution time. A query that doesn't finish in the time specified will be aborted with an error.

            Note: if the {{@@max_statement_time}} is set, the hint will be ignored and warning produced.
            TODO: This contradicts with the stated principle that "New-style hints are more specific than server variable settings, so they override the server variable settings".

            h2. 6. Subquery hints

            h3. 6.1. SUBQUERY hint

            {code}
            SUBQUERY([@query_block_name] MATERIALIZATION)
            SUBQUERY([@query_block_name] INTOEXISTS)
            {code}

            This controls non-semi-join subqueries. It controls choice of one of the two possible strategies.

            h3. 6.2 SEMIJOIN, NO_SEMIJOIN

            This controls conversion of subquery to semi-join and which semi-join strategies are allowed.
            {code}
            [NO]_SEMIJOIN([@query_block_name] [strategy [, strategy] ...])
            {code}
            where strategy is one of DUPSWEEDOUT, FIRSTMATCH, LOOSESCAN, MATERIALIZATION.
            psergei Sergei Petrunia made changes -
            Description This is a self-contained description of Optimizer Hints in MariaDB, whatever is already implemented in the current patch.

            h1. Optimizer hints in MariaDB

            General idea is to be compatible with MySQL.
            MySQL hint docs: https://dev.mysql.com/doc/refman/8.4/en/optimizer-hints.html

            h2. 1. Hint syntax
            Hints are placed after the main statement verb

            {code:sql}
            UPDATE /*+ hints */ table ...;
            DELETE /*+ hints */ FROM table... ;
            SELECT /*+ hints */ ...
            {code}

            or after the SELECT keyword in any subquery:
            {code:sql}
            SELECT * FROM t1 WHERE a IN (SELECT /*+ hints */ ...)
            {code}

            There can be one or more hints separated with space
            {code}
              hints: hint hint ...
            {code}

            Each individual hint is hint name and arguments. In case there are no arguments,
            the () brackets are still present:

            {code}
            hint: hint_name([arguments])
            {code}

            Incorrect hints produce warnings. (TODO anything else?)
            Hints that are not ignored are kept in the query text (you can see them in SHOW PROCESSLIST, Slow Query Log, EXPLAIN EXTENDED)
            Hints that were incorrect and were ignored are removed from there.

            h2. 2. Hint hierarchy

            h3. 2.1 Index-level hints
            Index-level hints apply to index(es).
            The syntax is
            {code}
            hint_name(table_name [index_name [, index_name] ...])
            {code}

            where table_name may be query_block@table_name.

            (TODO: MySQL also supports hint_name(@query_block_name tbl_name) ? But we don't? )
             
            h2. 3. Query block naming: QB_NAME hint

            QB_NAME hint is used to assign a name to the query block the hint is in. The Query Block is either a SELECT or a top-level construct of UPDATE or DELETE statement.

            {code:sql}
            SELECT /*+ QB_NAME(foo) */ select_list FROM ...
            {code}

            The name can later be used
            * to refer to a query block, where required
            * to refer to a table as {{table_name@query_block_name}}.

            Hints inside VIEWs are not supported, yet. One can neither use hints in VIEW definitions, nor control query plans inside non-merged VIEWs (This is because QB_NAME binding is done "early", before we know that some tables are VIEWs)

            Besides the given name, any query block is given a name {{select#n}}, so one can refer to it like so:
            {code:sql}
            SELECT /*+ BKA(tbl1@`select#1`) */ 1 FROM tbl1 ...;
            {code}
            (TODO: QB_NAME in CTEs that are used in multiple places?)

            h2. 4. Effect of optimizer hints

            Optimizer can be controlled by
            1. Server variables - optimizer_switch, join_cache_level, etc, etc
            2. Old-style hints
            3. New-style hints

            Old-style hints did not overlap with server variable settings.

            New-style hints are more specific than server variable settings, so they override the server variable settings.

            Should new-style hints override old-style hints? TODO.

            Hints are "narrowly interpreted" and "best effort" - if a hint dictates to do something, like
            {code:sql}
            SELECT /*+ MRR(t1 t1_index1) */ ... FROM t1 ...
            {code}
            that means:
            {quote}
            When considering a query plan that involves using t1_index1 in a way that one can use MRR, use MRR.
            {quote}
            if the query planning is such that use of {{t1_index1}} doesn't allow to use MRR, it won't be used.
            The optimizer may also consider using {{t1_index2}} and pick that over using {{t1_index1}}.
            In such cases the hint is effectively ignored and no warning is given.
            Examples: [^mdev35483-mrr-is-narrow.sql]

            h2. 5. List of hints

            h3. 5.1 NO_RANGE_OPTIMIZATION hint

            It's an index-level hint that disables range optimization for certain index(es):
            {code:sql}
            SELECT /*+ NO_RANGE_OPTIMIZATION(tbl index1 index2) */ * FROM tbl ...
            {code}

            h3. 5.2 NO_ICP hint
            It's an index-level hint that disables Index Condition Pushdown for the indexes. ICP+BKA is disabled as well.
            {code:sql}
            SELECT /*+ NO_ICP(tbl index1 index2) */ * FROM tbl ...
            {code}

            h3. 5.3 MRR and NO_MRR hints

            Index-level hint to force or disable use of MRR.

            {code:sql}
            SELECT /*+ MRR(tbl index1 index2) */ * FROM tbl ...
            SELECT /*+ NO_MRR(tbl index1 index2) */ * FROM tbl ...
            {code}
            This controls
            * MRR optimization for range access ( [^mdev35483-mrr-is-narrow.sql] )
            * BKA [^mdev35483-mrr-controls-bka-partially.sql]

            h3. 5.4 BKA() and NO_BKA() hints
            It's a query block or table-level hint.

            BKA() also enables MRR to make BKA possible. (This is different from session variables, where one needs to enable MRR separately).

            This also enables BKAH. TODO what was the reason for this?

            TODO: NO_BKA() seems to lso enable BNL-H: [^mdev35483-no-bka-enables-hash-join.txt] ?

            h3. 5.5 BNL() and NO_BNL() hints

            In MySQL this controls hash join, so in MariaDB it controls BNL-H.

            The implementation is "BNL() hint effectively increases join_cache_level up to 4 "
            TODO: this seems to fail a fairly trivial example: [^mdev35483-bnl-fails-why.txt] ?

            h3. 5.6 MAX_EXECUTION_TIME() hint
            Example:
            {code:sql}
            SELECT /*+ MAX_EXECUTION_TIME(milliseconds) */ ... ;
            {code}

            This is a global hint. It limits query execution time. A query that doesn't finish in the time specified will be aborted with an error.

            Note: if the {{@@max_statement_time}} is set, the hint will be ignored and warning produced.
            TODO: This contradicts with the stated principle that "New-style hints are more specific than server variable settings, so they override the server variable settings".

            h2. 6. Subquery hints

            h3. 6.1. SUBQUERY hint

            {code}
            SUBQUERY([@query_block_name] MATERIALIZATION)
            SUBQUERY([@query_block_name] INTOEXISTS)
            {code}

            This controls non-semi-join subqueries. It controls choice of one of the two possible strategies.

            h3. 6.2 SEMIJOIN, NO_SEMIJOIN

            This controls conversion of subquery to semi-join and which semi-join strategies are allowed.
            {code}
            [NO]_SEMIJOIN([@query_block_name] [strategy [, strategy] ...])
            {code}
            where strategy is one of DUPSWEEDOUT, FIRSTMATCH, LOOSESCAN, MATERIALIZATION.
            This is a self-contained description of Optimizer Hints in MariaDB, whatever is already implemented in the current patch.

            h1. Optimizer hints in MariaDB

            General idea is to be compatible with MySQL.
            MySQL hint docs: https://dev.mysql.com/doc/refman/8.4/en/optimizer-hints.html

            h2. 1. Hint syntax
            Hints are placed after the main statement verb

            {code:sql}
            UPDATE /*+ hints */ table ...;
            DELETE /*+ hints */ FROM table... ;
            SELECT /*+ hints */ ...
            {code}

            or after the SELECT keyword in any subquery:
            {code:sql}
            SELECT * FROM t1 WHERE a IN (SELECT /*+ hints */ ...)
            {code}

            There can be one or more hints separated with space
            {code}
              hints: hint hint ...
            {code}

            Each individual hint is hint name and arguments. In case there are no arguments,
            the () brackets are still present:

            {code}
            hint: hint_name([arguments])
            {code}

            Incorrect hints produce warnings. (TODO anything else?)
            Hints that are not ignored are kept in the query text (you can see them in SHOW PROCESSLIST, Slow Query Log, EXPLAIN EXTENDED)
            Hints that were incorrect and were ignored are removed from there.

            h2. 2. Hint hierarchy

            h3. 2.1 Index-level hints
            Index-level hints apply to index(es).
            The syntax is
            {code}
            hint_name(table_name [index_name [, index_name] ...])
            {code}

            where table_name may be query_block@table_name.

            (TODO: MySQL also supports hint_name(@query_block_name tbl_name) ? But we don't? )
             
            h2. 3. Query block naming: QB_NAME hint

            QB_NAME hint is used to assign a name to the query block the hint is in. The Query Block is either a SELECT or a top-level construct of UPDATE or DELETE statement.

            {code:sql}
            SELECT /*+ QB_NAME(foo) */ select_list FROM ...
            {code}

            The name can later be used
            * to refer to a query block, where required
            * to refer to a table as {{table_name@query_block_name}}.

            Hints inside VIEWs are not supported, yet. One can neither use hints in VIEW definitions, nor control query plans inside non-merged VIEWs (This is because QB_NAME binding is done "early", before we know that some tables are VIEWs)

            Besides the given name, any query block is given a name {{select#n}}, so one can refer to it like so:
            {code:sql}
            SELECT /*+ BKA(tbl1@`select#1`) */ 1 FROM tbl1 ...;
            {code}
            (TODO: QB_NAME in CTEs that are used in multiple places?)

            h2. 4. Effect of optimizer hints

            Optimizer can be controlled by
            1. Server variables - optimizer_switch, join_cache_level, etc, etc
            2. Old-style hints
            3. New-style hints

            Old-style hints did not overlap with server variable settings.

            New-style hints are more specific than server variable settings, so they override the server variable settings.

            Should new-style hints override old-style hints? TODO.

            Hints are "narrowly interpreted" and "best effort" - if a hint dictates to do something, like
            {code:sql}
            SELECT /*+ MRR(t1 t1_index1) */ ... FROM t1 ...
            {code}
            that means:
            {quote}
            When considering a query plan that involves using t1_index1 in a way that one can use MRR, use MRR.
            {quote}
            if the query planning is such that use of {{t1_index1}} doesn't allow to use MRR, it won't be used.
            The optimizer may also consider using {{t1_index2}} and pick that over using {{t1_index1}}.
            In such cases the hint is effectively ignored and no warning is given.
            Examples: [^mdev35483-mrr-is-narrow.sql]

            h2. 5. List of hints

            h3. 5.1 NO_RANGE_OPTIMIZATION hint

            It's an index-level hint that disables range optimization for certain index(es):
            {code:sql}
            SELECT /*+ NO_RANGE_OPTIMIZATION(tbl index1 index2) */ * FROM tbl ...
            {code}

            h3. 5.2 NO_ICP hint
            It's an index-level hint that disables Index Condition Pushdown for the indexes. ICP+BKA is disabled as well.
            {code:sql}
            SELECT /*+ NO_ICP(tbl index1 index2) */ * FROM tbl ...
            {code}

            h3. 5.3 MRR and NO_MRR hints

            Index-level hint to force or disable use of MRR.

            {code:sql}
            SELECT /*+ MRR(tbl index1 index2) */ * FROM tbl ...
            SELECT /*+ NO_MRR(tbl index1 index2) */ * FROM tbl ...
            {code}
            This controls
            * MRR optimization for range access ( [^mdev35483-mrr-is-narrow.sql] )
            * BKA [^mdev35483-mrr-controls-bka-partially.sql]

            h3. 5.4 BKA() and NO_BKA() hints
            It's a query block or table-level hint.

            BKA() also enables MRR to make BKA possible. (This is different from session variables, where one needs to enable MRR separately).

            This also enables BKAH. TODO what was the reason for this?

            TODO: NO_BKA() seems to lso enable BNL-H: [^mdev35483-no-bka-enables-hash-join.txt] ?

            h3. 5.5 BNL() and NO_BNL() hints

            In MySQL this controls hash join, so in MariaDB it controls BNL-H.

            The implementation is "BNL() hint effectively increases join_cache_level up to 4 "
            TODO: this seems to fail a fairly trivial example: [^mdev35483-bnl-fails-why.txt] ?

            h3. 5.6 MAX_EXECUTION_TIME() hint
            Example:
            {code:sql}
            SELECT /*+ MAX_EXECUTION_TIME(milliseconds) */ ... ;
            {code}

            This is a global hint. It limits query execution time. A query that doesn't finish in the time specified will be aborted with an error.

            Note: if the {{@@max_statement_time}} is set, the hint will be ignored and warning produced.
            TODO: This contradicts with the stated principle that "New-style hints are more specific than server variable settings, so they override the server variable settings".

            h2. 6. Subquery hints

            h3. 6.1. SUBQUERY hint

            {code}
            SUBQUERY([@query_block_name] MATERIALIZATION)
            SUBQUERY([@query_block_name] INTOEXISTS)
            {code}

            This controls non-semi-join subqueries. The parameter specifies which subquery to use. Use of this hint disables conversion of subquery into semi-join.

            h3. 6.2 SEMIJOIN, NO_SEMIJOIN

            This controls conversion of subquery to semi-join and which semi-join strategies are allowed.
            {code}
            [NO]_SEMIJOIN([@query_block_name] [strategy [, strategy] ...])
            {code}
            where strategy is one of DUPSWEEDOUT, FIRSTMATCH, LOOSESCAN, MATERIALIZATION.
            psergei Sergei Petrunia made changes -
            Description This is a self-contained description of Optimizer Hints in MariaDB, whatever is already implemented in the current patch.

            h1. Optimizer hints in MariaDB

            General idea is to be compatible with MySQL.
            MySQL hint docs: https://dev.mysql.com/doc/refman/8.4/en/optimizer-hints.html

            h2. 1. Hint syntax
            Hints are placed after the main statement verb

            {code:sql}
            UPDATE /*+ hints */ table ...;
            DELETE /*+ hints */ FROM table... ;
            SELECT /*+ hints */ ...
            {code}

            or after the SELECT keyword in any subquery:
            {code:sql}
            SELECT * FROM t1 WHERE a IN (SELECT /*+ hints */ ...)
            {code}

            There can be one or more hints separated with space
            {code}
              hints: hint hint ...
            {code}

            Each individual hint is hint name and arguments. In case there are no arguments,
            the () brackets are still present:

            {code}
            hint: hint_name([arguments])
            {code}

            Incorrect hints produce warnings. (TODO anything else?)
            Hints that are not ignored are kept in the query text (you can see them in SHOW PROCESSLIST, Slow Query Log, EXPLAIN EXTENDED)
            Hints that were incorrect and were ignored are removed from there.

            h2. 2. Hint hierarchy

            h3. 2.1 Index-level hints
            Index-level hints apply to index(es).
            The syntax is
            {code}
            hint_name(table_name [index_name [, index_name] ...])
            {code}

            where table_name may be query_block@table_name.

            (TODO: MySQL also supports hint_name(@query_block_name tbl_name) ? But we don't? )
             
            h2. 3. Query block naming: QB_NAME hint

            QB_NAME hint is used to assign a name to the query block the hint is in. The Query Block is either a SELECT or a top-level construct of UPDATE or DELETE statement.

            {code:sql}
            SELECT /*+ QB_NAME(foo) */ select_list FROM ...
            {code}

            The name can later be used
            * to refer to a query block, where required
            * to refer to a table as {{table_name@query_block_name}}.

            Hints inside VIEWs are not supported, yet. One can neither use hints in VIEW definitions, nor control query plans inside non-merged VIEWs (This is because QB_NAME binding is done "early", before we know that some tables are VIEWs)

            Besides the given name, any query block is given a name {{select#n}}, so one can refer to it like so:
            {code:sql}
            SELECT /*+ BKA(tbl1@`select#1`) */ 1 FROM tbl1 ...;
            {code}
            (TODO: QB_NAME in CTEs that are used in multiple places?)

            h2. 4. Effect of optimizer hints

            Optimizer can be controlled by
            1. Server variables - optimizer_switch, join_cache_level, etc, etc
            2. Old-style hints
            3. New-style hints

            Old-style hints did not overlap with server variable settings.

            New-style hints are more specific than server variable settings, so they override the server variable settings.

            Should new-style hints override old-style hints? TODO.

            Hints are "narrowly interpreted" and "best effort" - if a hint dictates to do something, like
            {code:sql}
            SELECT /*+ MRR(t1 t1_index1) */ ... FROM t1 ...
            {code}
            that means:
            {quote}
            When considering a query plan that involves using t1_index1 in a way that one can use MRR, use MRR.
            {quote}
            if the query planning is such that use of {{t1_index1}} doesn't allow to use MRR, it won't be used.
            The optimizer may also consider using {{t1_index2}} and pick that over using {{t1_index1}}.
            In such cases the hint is effectively ignored and no warning is given.
            Examples: [^mdev35483-mrr-is-narrow.sql]

            h2. 5. List of hints

            h3. 5.1 NO_RANGE_OPTIMIZATION hint

            It's an index-level hint that disables range optimization for certain index(es):
            {code:sql}
            SELECT /*+ NO_RANGE_OPTIMIZATION(tbl index1 index2) */ * FROM tbl ...
            {code}

            h3. 5.2 NO_ICP hint
            It's an index-level hint that disables Index Condition Pushdown for the indexes. ICP+BKA is disabled as well.
            {code:sql}
            SELECT /*+ NO_ICP(tbl index1 index2) */ * FROM tbl ...
            {code}

            h3. 5.3 MRR and NO_MRR hints

            Index-level hint to force or disable use of MRR.

            {code:sql}
            SELECT /*+ MRR(tbl index1 index2) */ * FROM tbl ...
            SELECT /*+ NO_MRR(tbl index1 index2) */ * FROM tbl ...
            {code}
            This controls
            * MRR optimization for range access ( [^mdev35483-mrr-is-narrow.sql] )
            * BKA [^mdev35483-mrr-controls-bka-partially.sql]

            h3. 5.4 BKA() and NO_BKA() hints
            It's a query block or table-level hint.

            BKA() also enables MRR to make BKA possible. (This is different from session variables, where one needs to enable MRR separately).

            This also enables BKAH. TODO what was the reason for this?

            TODO: NO_BKA() seems to lso enable BNL-H: [^mdev35483-no-bka-enables-hash-join.txt] ?

            h3. 5.5 BNL() and NO_BNL() hints

            In MySQL this controls hash join, so in MariaDB it controls BNL-H.

            The implementation is "BNL() hint effectively increases join_cache_level up to 4 "
            TODO: this seems to fail a fairly trivial example: [^mdev35483-bnl-fails-why.txt] ?

            h3. 5.6 MAX_EXECUTION_TIME() hint
            Example:
            {code:sql}
            SELECT /*+ MAX_EXECUTION_TIME(milliseconds) */ ... ;
            {code}

            This is a global hint. It limits query execution time. A query that doesn't finish in the time specified will be aborted with an error.

            Note: if the {{@@max_statement_time}} is set, the hint will be ignored and warning produced.
            TODO: This contradicts with the stated principle that "New-style hints are more specific than server variable settings, so they override the server variable settings".

            h2. 6. Subquery hints

            h3. 6.1. SUBQUERY hint

            {code}
            SUBQUERY([@query_block_name] MATERIALIZATION)
            SUBQUERY([@query_block_name] INTOEXISTS)
            {code}

            This controls non-semi-join subqueries. The parameter specifies which subquery to use. Use of this hint disables conversion of subquery into semi-join.

            h3. 6.2 SEMIJOIN, NO_SEMIJOIN

            This controls conversion of subquery to semi-join and which semi-join strategies are allowed.
            {code}
            [NO]_SEMIJOIN([@query_block_name] [strategy [, strategy] ...])
            {code}
            where strategy is one of DUPSWEEDOUT, FIRSTMATCH, LOOSESCAN, MATERIALIZATION.
            This is a self-contained description of Optimizer Hints in MariaDB, whatever is already implemented in the current patch.

            h1. Optimizer hints in MariaDB

            General idea is to be compatible with MySQL.
            MySQL hint docs: https://dev.mysql.com/doc/refman/8.4/en/optimizer-hints.html

            h2. 1. Hint syntax
            Hints are placed after the main statement verb

            {code:sql}
            UPDATE /*+ hints */ table ...;
            DELETE /*+ hints */ FROM table... ;
            SELECT /*+ hints */ ...
            {code}

            or after the SELECT keyword in any subquery:
            {code:sql}
            SELECT * FROM t1 WHERE a IN (SELECT /*+ hints */ ...)
            {code}

            There can be one or more hints separated with space
            {code}
              hints: hint hint ...
            {code}

            Each individual hint is hint name and arguments. In case there are no arguments,
            the () brackets are still present:

            {code}
            hint: hint_name([arguments])
            {code}

            Incorrect hints produce warnings. (TODO anything else?)
            Hints that are not ignored are kept in the query text (you can see them in SHOW PROCESSLIST, Slow Query Log, EXPLAIN EXTENDED)
            Hints that were incorrect and were ignored are removed from there.

            h2. 2. Hint hierarchy

            h3. 2.1 Index-level hints
            Index-level hints apply to index(es).
            The syntax is
            {code}
            hint_name(table_name [index_name [, index_name] ...])
            {code}

            where table_name may be query_block@table_name.

            (TODO: MySQL also supports hint_name(@query_block_name tbl_name) ? But we don't? )
             
            h2. 3. Query block naming: QB_NAME hint

            QB_NAME hint is used to assign a name to the query block the hint is in. The Query Block is either a SELECT or a top-level construct of UPDATE or DELETE statement.

            {code:sql}
            SELECT /*+ QB_NAME(foo) */ select_list FROM ...
            {code}

            The name can later be used
            * to refer to a query block, where required
            * to refer to a table as {{table_name@query_block_name}}.

            Hints inside VIEWs are not supported, yet. One can neither use hints in VIEW definitions, nor control query plans inside non-merged VIEWs (This is because QB_NAME binding is done "early", before we know that some tables are VIEWs)

            Besides the given name, any query block is given a name {{select#n}}, so one can refer to it like so:
            {code:sql}
            SELECT /*+ BKA(tbl1@`select#1`) */ 1 FROM tbl1 ...;
            {code}
            (TODO: QB_NAME in CTEs that are used in multiple places?)

            h2. 4. Effect of optimizer hints

            Optimizer can be controlled by
            1. Server variables - optimizer_switch, join_cache_level, etc, etc
            2. Old-style hints
            3. New-style hints

            Old-style hints did not overlap with server variable settings.

            New-style hints are more specific than server variable settings, so they override the server variable settings.

            Should new-style hints override old-style hints? TODO.

            Hints are "narrowly interpreted" and "best effort" - if a hint dictates to do something, like
            {code:sql}
            SELECT /*+ MRR(t1 t1_index1) */ ... FROM t1 ...
            {code}
            that means:
            {quote}
            When considering a query plan that involves using t1_index1 in a way that one can use MRR, use MRR.
            {quote}
            if the query planning is such that use of {{t1_index1}} doesn't allow to use MRR, it won't be used.
            The optimizer may also consider using {{t1_index2}} and pick that over using {{t1_index1}}.
            In such cases the hint is effectively ignored and no warning is given.
            Examples: [^mdev35483-mrr-is-narrow.sql]

            h2. 5. List of hints

            h3. 5.1 NO_RANGE_OPTIMIZATION hint

            It's an index-level hint that disables range optimization for certain index(es):
            {code:sql}
            SELECT /*+ NO_RANGE_OPTIMIZATION(tbl index1 index2) */ * FROM tbl ...
            {code}

            h3. 5.2 NO_ICP hint
            It's an index-level hint that disables Index Condition Pushdown for the indexes. ICP+BKA is disabled as well.
            {code:sql}
            SELECT /*+ NO_ICP(tbl index1 index2) */ * FROM tbl ...
            {code}

            h3. 5.3 MRR and NO_MRR hints

            Index-level hint to force or disable use of MRR.

            {code:sql}
            SELECT /*+ MRR(tbl index1 index2) */ * FROM tbl ...
            SELECT /*+ NO_MRR(tbl index1 index2) */ * FROM tbl ...
            {code}
            This controls
            * MRR optimization for range access ( [^mdev35483-mrr-is-narrow.sql] )
            * BKA [^mdev35483-mrr-controls-bka-partially.sql]

            h3. 5.4 BKA() and NO_BKA() hints
            It's a query block or table-level hint.

            BKA() also enables MRR to make BKA possible. (This is different from session variables, where one needs to enable MRR separately).

            This also enables BKAH. TODO what was the reason for this?

            TODO: NO_BKA() seems to lso enable BNL-H: [^mdev35483-no-bka-enables-hash-join.txt] ?

            h3. 5.5 BNL() and NO_BNL() hints

            In MySQL this controls hash join, so in MariaDB it controls BNL-H.

            The implementation is "BNL() hint effectively increases join_cache_level up to 4 "
            TODO: this seems to fail a fairly trivial example: [^mdev35483-bnl-fails-why.txt] ?

            h3. 5.6 MAX_EXECUTION_TIME() hint
            Example:
            {code:sql}
            SELECT /*+ MAX_EXECUTION_TIME(milliseconds) */ ... ;
            {code}

            This is a global hint. It limits query execution time. A query that doesn't finish in the time specified will be aborted with an error.

            Note: if the {{@@max_statement_time}} is set, the hint will be ignored and warning produced.
            TODO: This contradicts with the stated principle that "New-style hints are more specific than server variable settings, so they override the server variable settings".

            h2. 6. Subquery hints

            h3. 6.1. SUBQUERY hint

            {code}
            SUBQUERY([@query_block_name] MATERIALIZATION)
            SUBQUERY([@query_block_name] INTOEXISTS)
            {code}

            This controls non-semi-join subqueries. The parameter specifies which subquery to use. Use of this hint disables conversion of subquery into semi-join.

            h3. 6.2 SEMIJOIN, NO_SEMIJOIN

            This controls conversion of subquery to semi-join and which semi-join strategies are allowed.
            {code}
            [NO_]SEMIJOIN([@query_block_name] [strategy [, strategy] ...])
            {code}
            where strategy is one of DUPSWEEDOUT, FIRSTMATCH, LOOSESCAN, MATERIALIZATION.
            psergei Sergei Petrunia made changes -
            Description This is a self-contained description of Optimizer Hints in MariaDB, whatever is already implemented in the current patch.

            h1. Optimizer hints in MariaDB

            General idea is to be compatible with MySQL.
            MySQL hint docs: https://dev.mysql.com/doc/refman/8.4/en/optimizer-hints.html

            h2. 1. Hint syntax
            Hints are placed after the main statement verb

            {code:sql}
            UPDATE /*+ hints */ table ...;
            DELETE /*+ hints */ FROM table... ;
            SELECT /*+ hints */ ...
            {code}

            or after the SELECT keyword in any subquery:
            {code:sql}
            SELECT * FROM t1 WHERE a IN (SELECT /*+ hints */ ...)
            {code}

            There can be one or more hints separated with space
            {code}
              hints: hint hint ...
            {code}

            Each individual hint is hint name and arguments. In case there are no arguments,
            the () brackets are still present:

            {code}
            hint: hint_name([arguments])
            {code}

            Incorrect hints produce warnings. (TODO anything else?)
            Hints that are not ignored are kept in the query text (you can see them in SHOW PROCESSLIST, Slow Query Log, EXPLAIN EXTENDED)
            Hints that were incorrect and were ignored are removed from there.

            h2. 2. Hint hierarchy

            h3. 2.1 Index-level hints
            Index-level hints apply to index(es).
            The syntax is
            {code}
            hint_name(table_name [index_name [, index_name] ...])
            {code}

            where table_name may be query_block@table_name.

            (TODO: MySQL also supports hint_name(@query_block_name tbl_name) ? But we don't? )
             
            h2. 3. Query block naming: QB_NAME hint

            QB_NAME hint is used to assign a name to the query block the hint is in. The Query Block is either a SELECT or a top-level construct of UPDATE or DELETE statement.

            {code:sql}
            SELECT /*+ QB_NAME(foo) */ select_list FROM ...
            {code}

            The name can later be used
            * to refer to a query block, where required
            * to refer to a table as {{table_name@query_block_name}}.

            Hints inside VIEWs are not supported, yet. One can neither use hints in VIEW definitions, nor control query plans inside non-merged VIEWs (This is because QB_NAME binding is done "early", before we know that some tables are VIEWs)

            Besides the given name, any query block is given a name {{select#n}}, so one can refer to it like so:
            {code:sql}
            SELECT /*+ BKA(tbl1@`select#1`) */ 1 FROM tbl1 ...;
            {code}
            (TODO: QB_NAME in CTEs that are used in multiple places?)

            h2. 4. Effect of optimizer hints

            Optimizer can be controlled by
            1. Server variables - optimizer_switch, join_cache_level, etc, etc
            2. Old-style hints
            3. New-style hints

            Old-style hints did not overlap with server variable settings.

            New-style hints are more specific than server variable settings, so they override the server variable settings.

            Should new-style hints override old-style hints? TODO.

            Hints are "narrowly interpreted" and "best effort" - if a hint dictates to do something, like
            {code:sql}
            SELECT /*+ MRR(t1 t1_index1) */ ... FROM t1 ...
            {code}
            that means:
            {quote}
            When considering a query plan that involves using t1_index1 in a way that one can use MRR, use MRR.
            {quote}
            if the query planning is such that use of {{t1_index1}} doesn't allow to use MRR, it won't be used.
            The optimizer may also consider using {{t1_index2}} and pick that over using {{t1_index1}}.
            In such cases the hint is effectively ignored and no warning is given.
            Examples: [^mdev35483-mrr-is-narrow.sql]

            h2. 5. List of hints

            h3. 5.1 NO_RANGE_OPTIMIZATION hint

            It's an index-level hint that disables range optimization for certain index(es):
            {code:sql}
            SELECT /*+ NO_RANGE_OPTIMIZATION(tbl index1 index2) */ * FROM tbl ...
            {code}

            h3. 5.2 NO_ICP hint
            It's an index-level hint that disables Index Condition Pushdown for the indexes. ICP+BKA is disabled as well.
            {code:sql}
            SELECT /*+ NO_ICP(tbl index1 index2) */ * FROM tbl ...
            {code}

            h3. 5.3 MRR and NO_MRR hints

            Index-level hint to force or disable use of MRR.

            {code:sql}
            SELECT /*+ MRR(tbl index1 index2) */ * FROM tbl ...
            SELECT /*+ NO_MRR(tbl index1 index2) */ * FROM tbl ...
            {code}
            This controls
            * MRR optimization for range access ( [^mdev35483-mrr-is-narrow.sql] )
            * BKA [^mdev35483-mrr-controls-bka-partially.sql]

            h3. 5.4 BKA() and NO_BKA() hints
            It's a query block or table-level hint.

            BKA() also enables MRR to make BKA possible. (This is different from session variables, where one needs to enable MRR separately).

            This also enables BKAH. TODO what was the reason for this?

            TODO: NO_BKA() seems to lso enable BNL-H: [^mdev35483-no-bka-enables-hash-join.txt] ?

            h3. 5.5 BNL() and NO_BNL() hints

            In MySQL this controls hash join, so in MariaDB it controls BNL-H.

            The implementation is "BNL() hint effectively increases join_cache_level up to 4 "
            TODO: this seems to fail a fairly trivial example: [^mdev35483-bnl-fails-why.txt] ?

            h3. 5.6 MAX_EXECUTION_TIME() hint
            Example:
            {code:sql}
            SELECT /*+ MAX_EXECUTION_TIME(milliseconds) */ ... ;
            {code}

            This is a global hint. It limits query execution time. A query that doesn't finish in the time specified will be aborted with an error.

            Note: if the {{@@max_statement_time}} is set, the hint will be ignored and warning produced.
            TODO: This contradicts with the stated principle that "New-style hints are more specific than server variable settings, so they override the server variable settings".

            h2. 6. Subquery hints

            h3. 6.1. SUBQUERY hint

            {code}
            SUBQUERY([@query_block_name] MATERIALIZATION)
            SUBQUERY([@query_block_name] INTOEXISTS)
            {code}

            This controls non-semi-join subqueries. The parameter specifies which subquery to use. Use of this hint disables conversion of subquery into semi-join.

            h3. 6.2 SEMIJOIN, NO_SEMIJOIN

            This controls conversion of subquery to semi-join and which semi-join strategies are allowed.
            {code}
            [NO_]SEMIJOIN([@query_block_name] [strategy [, strategy] ...])
            {code}
            where strategy is one of DUPSWEEDOUT, FIRSTMATCH, LOOSESCAN, MATERIALIZATION.
            This is a self-contained description of Optimizer Hints in MariaDB, whatever is already implemented in the current patch.

            h1. Optimizer hints in MariaDB

            General idea is to be compatible with MySQL.
            MySQL hint docs: https://dev.mysql.com/doc/refman/8.4/en/optimizer-hints.html

            h2. 1. Hint syntax
            Hints are placed after the main statement verb

            {code:sql}
            UPDATE /*+ hints */ table ...;
            DELETE /*+ hints */ FROM table... ;
            SELECT /*+ hints */ ...
            {code}

            or after the SELECT keyword in any subquery:
            {code:sql}
            SELECT * FROM t1 WHERE a IN (SELECT /*+ hints */ ...)
            {code}

            There can be one or more hints separated with space
            {code}
              hints: hint hint ...
            {code}

            Each individual hint is hint name and arguments. In case there are no arguments,
            the () brackets are still present:

            {code}
            hint: hint_name([arguments])
            {code}

            Incorrect hints produce warnings. (TODO anything else?)
            Hints that are not ignored are kept in the query text (you can see them in SHOW PROCESSLIST, Slow Query Log, EXPLAIN EXTENDED)
            Hints that were incorrect and were ignored are removed from there.

            h2. 2. Hint hierarchy

            h3. 2.1 Index-level hints
            Index-level hints apply to index(es).
            The syntax is
            {code}
            hint_name(table_name [index_name [, index_name] ...])
            {code}

            where table_name may be query_block@table_name.

            (TODO: MySQL also supports hint_name(@query_block_name tbl_name) ? But we don't? )
             
            h2. 3. Query block naming: QB_NAME hint

            QB_NAME hint is used to assign a name to the query block the hint is in. The Query Block is either a SELECT or a top-level construct of UPDATE or DELETE statement.

            {code:sql}
            SELECT /*+ QB_NAME(foo) */ select_list FROM ...
            {code}

            The name can later be used
            * to refer to a query block, where required
            * to refer to a table as {{table_name@query_block_name}}.

            Hints inside VIEWs are not supported, yet. One can neither use hints in VIEW definitions, nor control query plans inside non-merged VIEWs (This is because QB_NAME binding is done "early", before we know that some tables are VIEWs)

            h3. 3.1 select#n names.
            Besides the given name, any query block is given a name {{select#n}}. It is printed in EXPLAIN EXTENDED output:
            {code}
            Warnings:
            Note 1003 select /*+ NO_RANGE_OPTIMIZATION(`t3`@`select#1` `PRIMARY`) */ ...
            {code}

            *At the moment it is NOT yet possible to use it in the hint text*:
            {code:sql}
            SELECT /*+ BKA(tbl1@`select#1`) */ 1 FROM tbl1 ...;
            {code}

            h3. 3.2 QB_NAME in CTEs.
            What {{QB_NAME(@name)}} is used in a CTE which is then used in multiple places? Hints that control @name will control the first use of the CTE.
            (This "just happens" due to the way CTEs are implemented. We could address it when addressing VIEWs)

            h2. 4. Effect of optimizer hints

            Optimizer can be controlled by
            1. Server variables - optimizer_switch, join_cache_level, etc, etc
            2. Old-style hints
            3. New-style hints

            Old-style hints did not overlap with server variable settings.

            New-style hints are more specific than server variable settings, so they override the server variable settings.

            Should new-style hints override old-style hints? TODO.

            Hints are "narrowly interpreted" and "best effort" - if a hint dictates to do something, like
            {code:sql}
            SELECT /*+ MRR(t1 t1_index1) */ ... FROM t1 ...
            {code}
            that means:
            {quote}
            When considering a query plan that involves using t1_index1 in a way that one can use MRR, use MRR.
            {quote}
            if the query planning is such that use of {{t1_index1}} doesn't allow to use MRR, it won't be used.
            The optimizer may also consider using {{t1_index2}} and pick that over using {{t1_index1}}.
            In such cases the hint is effectively ignored and no warning is given.
            Examples: [^mdev35483-mrr-is-narrow.sql]

            h2. 5. List of hints

            h3. 5.1 NO_RANGE_OPTIMIZATION hint

            It's an index-level hint that disables range optimization for certain index(es):
            {code:sql}
            SELECT /*+ NO_RANGE_OPTIMIZATION(tbl index1 index2) */ * FROM tbl ...
            {code}

            h3. 5.2 NO_ICP hint
            It's an index-level hint that disables Index Condition Pushdown for the indexes. ICP+BKA is disabled as well.
            {code:sql}
            SELECT /*+ NO_ICP(tbl index1 index2) */ * FROM tbl ...
            {code}

            h3. 5.3 MRR and NO_MRR hints

            Index-level hint to force or disable use of MRR.

            {code:sql}
            SELECT /*+ MRR(tbl index1 index2) */ * FROM tbl ...
            SELECT /*+ NO_MRR(tbl index1 index2) */ * FROM tbl ...
            {code}
            This controls
            * MRR optimization for range access ( [^mdev35483-mrr-is-narrow.sql] )
            * BKA [^mdev35483-mrr-controls-bka-partially.sql]

            h3. 5.4 BKA() and NO_BKA() hints
            It's a query block or table-level hint.

            BKA() also enables MRR to make BKA possible. (This is different from session variables, where one needs to enable MRR separately).

            This also enables BKAH. TODO what was the reason for this?

            TODO: NO_BKA() seems to lso enable BNL-H: [^mdev35483-no-bka-enables-hash-join.txt] ?

            h3. 5.5 BNL() and NO_BNL() hints

            In MySQL this controls hash join, so in MariaDB it controls BNL-H.

            The implementation is "BNL() hint effectively increases join_cache_level up to 4 "
            TODO: this seems to fail a fairly trivial example: [^mdev35483-bnl-fails-why.txt] ?

            h3. 5.6 MAX_EXECUTION_TIME() hint
            Example:
            {code:sql}
            SELECT /*+ MAX_EXECUTION_TIME(milliseconds) */ ... ;
            {code}

            This is a global hint. It limits query execution time. A query that doesn't finish in the time specified will be aborted with an error.

            Note: if the {{@@max_statement_time}} is set, the hint will be ignored and warning produced.
            TODO: This contradicts with the stated principle that "New-style hints are more specific than server variable settings, so they override the server variable settings".

            h2. 6. Subquery hints

            h3. 6.1. SUBQUERY hint

            {code}
            SUBQUERY([@query_block_name] MATERIALIZATION)
            SUBQUERY([@query_block_name] INTOEXISTS)
            {code}

            This controls non-semi-join subqueries. The parameter specifies which subquery to use. Use of this hint disables conversion of subquery into semi-join.

            h3. 6.2 SEMIJOIN, NO_SEMIJOIN

            This controls conversion of subquery to semi-join and which semi-join strategies are allowed.
            {code}
            [NO_]SEMIJOIN([@query_block_name] [strategy [, strategy] ...])
            {code}
            where strategy is one of DUPSWEEDOUT, FIRSTMATCH, LOOSESCAN, MATERIALIZATION.
            psergei Sergei Petrunia made changes -
            Description This is a self-contained description of Optimizer Hints in MariaDB, whatever is already implemented in the current patch.

            h1. Optimizer hints in MariaDB

            General idea is to be compatible with MySQL.
            MySQL hint docs: https://dev.mysql.com/doc/refman/8.4/en/optimizer-hints.html

            h2. 1. Hint syntax
            Hints are placed after the main statement verb

            {code:sql}
            UPDATE /*+ hints */ table ...;
            DELETE /*+ hints */ FROM table... ;
            SELECT /*+ hints */ ...
            {code}

            or after the SELECT keyword in any subquery:
            {code:sql}
            SELECT * FROM t1 WHERE a IN (SELECT /*+ hints */ ...)
            {code}

            There can be one or more hints separated with space
            {code}
              hints: hint hint ...
            {code}

            Each individual hint is hint name and arguments. In case there are no arguments,
            the () brackets are still present:

            {code}
            hint: hint_name([arguments])
            {code}

            Incorrect hints produce warnings. (TODO anything else?)
            Hints that are not ignored are kept in the query text (you can see them in SHOW PROCESSLIST, Slow Query Log, EXPLAIN EXTENDED)
            Hints that were incorrect and were ignored are removed from there.

            h2. 2. Hint hierarchy

            h3. 2.1 Index-level hints
            Index-level hints apply to index(es).
            The syntax is
            {code}
            hint_name(table_name [index_name [, index_name] ...])
            {code}

            where table_name may be query_block@table_name.

            (TODO: MySQL also supports hint_name(@query_block_name tbl_name) ? But we don't? )
             
            h2. 3. Query block naming: QB_NAME hint

            QB_NAME hint is used to assign a name to the query block the hint is in. The Query Block is either a SELECT or a top-level construct of UPDATE or DELETE statement.

            {code:sql}
            SELECT /*+ QB_NAME(foo) */ select_list FROM ...
            {code}

            The name can later be used
            * to refer to a query block, where required
            * to refer to a table as {{table_name@query_block_name}}.

            Hints inside VIEWs are not supported, yet. One can neither use hints in VIEW definitions, nor control query plans inside non-merged VIEWs (This is because QB_NAME binding is done "early", before we know that some tables are VIEWs)

            h3. 3.1 select#n names.
            Besides the given name, any query block is given a name {{select#n}}. It is printed in EXPLAIN EXTENDED output:
            {code}
            Warnings:
            Note 1003 select /*+ NO_RANGE_OPTIMIZATION(`t3`@`select#1` `PRIMARY`) */ ...
            {code}

            *At the moment it is NOT yet possible to use it in the hint text*:
            {code:sql}
            SELECT /*+ BKA(tbl1@`select#1`) */ 1 FROM tbl1 ...;
            {code}

            h3. 3.2 QB_NAME in CTEs.
            What {{QB_NAME(@name)}} is used in a CTE which is then used in multiple places? Hints that control @name will control the first use of the CTE.
            (This "just happens" due to the way CTEs are implemented. We could address it when addressing VIEWs)

            h2. 4. Effect of optimizer hints

            Optimizer can be controlled by
            1. Server variables - optimizer_switch, join_cache_level, etc, etc
            2. Old-style hints
            3. New-style hints

            Old-style hints did not overlap with server variable settings.

            New-style hints are more specific than server variable settings, so they override the server variable settings.

            Should new-style hints override old-style hints? TODO.

            Hints are "narrowly interpreted" and "best effort" - if a hint dictates to do something, like
            {code:sql}
            SELECT /*+ MRR(t1 t1_index1) */ ... FROM t1 ...
            {code}
            that means:
            {quote}
            When considering a query plan that involves using t1_index1 in a way that one can use MRR, use MRR.
            {quote}
            if the query planning is such that use of {{t1_index1}} doesn't allow to use MRR, it won't be used.
            The optimizer may also consider using {{t1_index2}} and pick that over using {{t1_index1}}.
            In such cases the hint is effectively ignored and no warning is given.
            Examples: [^mdev35483-mrr-is-narrow.sql]

            h2. 5. List of hints

            h3. 5.1 NO_RANGE_OPTIMIZATION hint

            It's an index-level hint that disables range optimization for certain index(es):
            {code:sql}
            SELECT /*+ NO_RANGE_OPTIMIZATION(tbl index1 index2) */ * FROM tbl ...
            {code}

            h3. 5.2 NO_ICP hint
            It's an index-level hint that disables Index Condition Pushdown for the indexes. ICP+BKA is disabled as well.
            {code:sql}
            SELECT /*+ NO_ICP(tbl index1 index2) */ * FROM tbl ...
            {code}

            h3. 5.3 MRR and NO_MRR hints

            Index-level hint to force or disable use of MRR.

            {code:sql}
            SELECT /*+ MRR(tbl index1 index2) */ * FROM tbl ...
            SELECT /*+ NO_MRR(tbl index1 index2) */ * FROM tbl ...
            {code}
            This controls
            * MRR optimization for range access ( [^mdev35483-mrr-is-narrow.sql] )
            * BKA [^mdev35483-mrr-controls-bka-partially.sql]

            h3. 5.4 BKA() and NO_BKA() hints
            It's a query block or table-level hint.

            BKA() also enables MRR to make BKA possible. (This is different from session variables, where one needs to enable MRR separately).

            This also enables BKAH. TODO what was the reason for this?

            TODO: NO_BKA() seems to lso enable BNL-H: [^mdev35483-no-bka-enables-hash-join.txt] ?

            h3. 5.5 BNL() and NO_BNL() hints

            In MySQL this controls hash join, so in MariaDB it controls BNL-H.

            The implementation is "BNL() hint effectively increases join_cache_level up to 4 "
            TODO: this seems to fail a fairly trivial example: [^mdev35483-bnl-fails-why.txt] ?

            h3. 5.6 MAX_EXECUTION_TIME() hint
            Example:
            {code:sql}
            SELECT /*+ MAX_EXECUTION_TIME(milliseconds) */ ... ;
            {code}

            This is a global hint. It limits query execution time. A query that doesn't finish in the time specified will be aborted with an error.

            Note: if the {{@@max_statement_time}} is set, the hint will be ignored and warning produced.
            TODO: This contradicts with the stated principle that "New-style hints are more specific than server variable settings, so they override the server variable settings".

            h2. 6. Subquery hints

            h3. 6.1. SUBQUERY hint

            {code}
            SUBQUERY([@query_block_name] MATERIALIZATION)
            SUBQUERY([@query_block_name] INTOEXISTS)
            {code}

            This controls non-semi-join subqueries. The parameter specifies which subquery to use. Use of this hint disables conversion of subquery into semi-join.

            h3. 6.2 SEMIJOIN, NO_SEMIJOIN

            This controls conversion of subquery to semi-join and which semi-join strategies are allowed.
            {code}
            [NO_]SEMIJOIN([@query_block_name] [strategy [, strategy] ...])
            {code}
            where strategy is one of DUPSWEEDOUT, FIRSTMATCH, LOOSESCAN, MATERIALIZATION.
            This is a self-contained description of Optimizer Hints in MariaDB, whatever is already implemented in the current patch.

            h1. Optimizer hints in MariaDB

            General idea is to be compatible with MySQL.
            MySQL hint docs: https://dev.mysql.com/doc/refman/8.4/en/optimizer-hints.html

            h2. 1. Hint syntax
            Hints are placed after the main statement verb

            {code:sql}
            UPDATE /*+ hints */ table ...;
            DELETE /*+ hints */ FROM table... ;
            SELECT /*+ hints */ ...
            {code}

            or after the SELECT keyword in any subquery:
            {code:sql}
            SELECT * FROM t1 WHERE a IN (SELECT /*+ hints */ ...)
            {code}

            There can be one or more hints separated with space
            {code}
              hints: hint hint ...
            {code}

            Each individual hint is hint name and arguments. In case there are no arguments,
            the () brackets are still present:

            {code}
            hint: hint_name([arguments])
            {code}

            Incorrect hints produce warnings. (TODO anything else?)
            Hints that are not ignored are kept in the query text (you can see them in SHOW PROCESSLIST, Slow Query Log, EXPLAIN EXTENDED)
            Hints that were incorrect and were ignored are removed from there.

            h2. 2. Hint hierarchy
            (todo: elaborate)

            h3. 2.1 Index-level hints
            Index-level hints apply to index(es).
            Possible syntax variants:
            {code}
            hint_name(table_name [index_name [, index_name] ...])
            hint_name(table_name@query_block [index_name [, index_name] ...])
            hint_name(@query_block hint_name(table_name@query_block [index_name [, index_name] ...]) [index_name [, index_name] ...])
            {code}
             
            h2. 3. Query block naming: QB_NAME hint

            QB_NAME hint is used to assign a name to the query block the hint is in. The Query Block is either a SELECT or a top-level construct of UPDATE or DELETE statement.

            {code:sql}
            SELECT /*+ QB_NAME(foo) */ select_list FROM ...
            {code}

            The name can later be used
            * to refer to a query block, where required
            * to refer to a table as {{table_name@query_block_name}}.

            Hints inside VIEWs are not supported, yet. One can neither use hints in VIEW definitions, nor control query plans inside non-merged VIEWs (This is because QB_NAME binding is done "early", before we know that some tables are VIEWs)

            h3. 3.1 select#n names.
            Besides the given name, any query block is given a name {{select#n}}. It is printed in EXPLAIN EXTENDED output:
            {code}
            Warnings:
            Note 1003 select /*+ NO_RANGE_OPTIMIZATION(`t3`@`select#1` `PRIMARY`) */ ...
            {code}

            *At the moment it is NOT yet possible to use it in the hint text*:
            {code:sql}
            SELECT /*+ BKA(tbl1@`select#1`) */ 1 FROM tbl1 ...;
            {code}

            h3. 3.2 QB_NAME in CTEs.
            What {{QB_NAME(@name)}} is used in a CTE which is then used in multiple places? Hints that control @name will control the first use of the CTE.
            (This "just happens" due to the way CTEs are implemented. We could address it when addressing VIEWs)

            h2. 4. Effect of optimizer hints

            Optimizer can be controlled by
            1. Server variables - optimizer_switch, join_cache_level, etc, etc
            2. Old-style hints
            3. New-style hints

            Old-style hints did not overlap with server variable settings.

            New-style hints are more specific than server variable settings, so they override the server variable settings.

            Should new-style hints override old-style hints? TODO.

            Hints are "narrowly interpreted" and "best effort" - if a hint dictates to do something, like
            {code:sql}
            SELECT /*+ MRR(t1 t1_index1) */ ... FROM t1 ...
            {code}
            that means:
            {quote}
            When considering a query plan that involves using t1_index1 in a way that one can use MRR, use MRR.
            {quote}
            if the query planning is such that use of {{t1_index1}} doesn't allow to use MRR, it won't be used.
            The optimizer may also consider using {{t1_index2}} and pick that over using {{t1_index1}}.
            In such cases the hint is effectively ignored and no warning is given.
            Examples: [^mdev35483-mrr-is-narrow.sql]

            h2. 5. List of hints

            h3. 5.1 NO_RANGE_OPTIMIZATION hint

            It's an index-level hint that disables range optimization for certain index(es):
            {code:sql}
            SELECT /*+ NO_RANGE_OPTIMIZATION(tbl index1 index2) */ * FROM tbl ...
            {code}

            h3. 5.2 NO_ICP hint
            It's an index-level hint that disables Index Condition Pushdown for the indexes. ICP+BKA is disabled as well.
            {code:sql}
            SELECT /*+ NO_ICP(tbl index1 index2) */ * FROM tbl ...
            {code}

            h3. 5.3 MRR and NO_MRR hints

            Index-level hint to force or disable use of MRR.

            {code:sql}
            SELECT /*+ MRR(tbl index1 index2) */ * FROM tbl ...
            SELECT /*+ NO_MRR(tbl index1 index2) */ * FROM tbl ...
            {code}
            This controls
            * MRR optimization for range access ( [^mdev35483-mrr-is-narrow.sql] )
            * BKA [^mdev35483-mrr-controls-bka-partially.sql]

            h3. 5.4 BKA() and NO_BKA() hints
            It's a query block or table-level hint.

            BKA() also enables MRR to make BKA possible. (This is different from session variables, where one needs to enable MRR separately).

            This also enables BKAH. TODO what was the reason for this?

            TODO: NO_BKA() seems to lso enable BNL-H: [^mdev35483-no-bka-enables-hash-join.txt] ?

            h3. 5.5 BNL() and NO_BNL() hints

            In MySQL this controls hash join, so in MariaDB it controls BNL-H.

            The implementation is "BNL() hint effectively increases join_cache_level up to 4 "
            TODO: this seems to fail a fairly trivial example: [^mdev35483-bnl-fails-why.txt] ?

            h3. 5.6 MAX_EXECUTION_TIME() hint
            Example:
            {code:sql}
            SELECT /*+ MAX_EXECUTION_TIME(milliseconds) */ ... ;
            {code}

            This is a global hint. It limits query execution time. A query that doesn't finish in the time specified will be aborted with an error.

            Note: if the {{@@max_statement_time}} is set, the hint will be ignored and warning produced.
            TODO: This contradicts with the stated principle that "New-style hints are more specific than server variable settings, so they override the server variable settings".

            h2. 6. Subquery hints

            h3. 6.1. SUBQUERY hint

            {code}
            SUBQUERY([@query_block_name] MATERIALIZATION)
            SUBQUERY([@query_block_name] INTOEXISTS)
            {code}

            This controls non-semi-join subqueries. The parameter specifies which subquery to use. Use of this hint disables conversion of subquery into semi-join.

            h3. 6.2 SEMIJOIN, NO_SEMIJOIN

            This controls conversion of subquery to semi-join and which semi-join strategies are allowed.
            {code}
            [NO_]SEMIJOIN([@query_block_name] [strategy [, strategy] ...])
            {code}
            where strategy is one of DUPSWEEDOUT, FIRSTMATCH, LOOSESCAN, MATERIALIZATION.
            psergei Sergei Petrunia made changes -
            Description This is a self-contained description of Optimizer Hints in MariaDB, whatever is already implemented in the current patch.

            h1. Optimizer hints in MariaDB

            General idea is to be compatible with MySQL.
            MySQL hint docs: https://dev.mysql.com/doc/refman/8.4/en/optimizer-hints.html

            h2. 1. Hint syntax
            Hints are placed after the main statement verb

            {code:sql}
            UPDATE /*+ hints */ table ...;
            DELETE /*+ hints */ FROM table... ;
            SELECT /*+ hints */ ...
            {code}

            or after the SELECT keyword in any subquery:
            {code:sql}
            SELECT * FROM t1 WHERE a IN (SELECT /*+ hints */ ...)
            {code}

            There can be one or more hints separated with space
            {code}
              hints: hint hint ...
            {code}

            Each individual hint is hint name and arguments. In case there are no arguments,
            the () brackets are still present:

            {code}
            hint: hint_name([arguments])
            {code}

            Incorrect hints produce warnings. (TODO anything else?)
            Hints that are not ignored are kept in the query text (you can see them in SHOW PROCESSLIST, Slow Query Log, EXPLAIN EXTENDED)
            Hints that were incorrect and were ignored are removed from there.

            h2. 2. Hint hierarchy
            (todo: elaborate)

            h3. 2.1 Index-level hints
            Index-level hints apply to index(es).
            Possible syntax variants:
            {code}
            hint_name(table_name [index_name [, index_name] ...])
            hint_name(table_name@query_block [index_name [, index_name] ...])
            hint_name(@query_block hint_name(table_name@query_block [index_name [, index_name] ...]) [index_name [, index_name] ...])
            {code}
             
            h2. 3. Query block naming: QB_NAME hint

            QB_NAME hint is used to assign a name to the query block the hint is in. The Query Block is either a SELECT or a top-level construct of UPDATE or DELETE statement.

            {code:sql}
            SELECT /*+ QB_NAME(foo) */ select_list FROM ...
            {code}

            The name can later be used
            * to refer to a query block, where required
            * to refer to a table as {{table_name@query_block_name}}.

            Hints inside VIEWs are not supported, yet. One can neither use hints in VIEW definitions, nor control query plans inside non-merged VIEWs (This is because QB_NAME binding is done "early", before we know that some tables are VIEWs)

            h3. 3.1 select#n names.
            Besides the given name, any query block is given a name {{select#n}}. It is printed in EXPLAIN EXTENDED output:
            {code}
            Warnings:
            Note 1003 select /*+ NO_RANGE_OPTIMIZATION(`t3`@`select#1` `PRIMARY`) */ ...
            {code}

            *At the moment it is NOT yet possible to use it in the hint text*:
            {code:sql}
            SELECT /*+ BKA(tbl1@`select#1`) */ 1 FROM tbl1 ...;
            {code}

            h3. 3.2 QB_NAME in CTEs.
            What {{QB_NAME(@name)}} is used in a CTE which is then used in multiple places? Hints that control @name will control the first use of the CTE.
            (This "just happens" due to the way CTEs are implemented. We could address it when addressing VIEWs)

            h2. 4. Effect of optimizer hints

            Optimizer can be controlled by
            1. Server variables - optimizer_switch, join_cache_level, etc, etc
            2. Old-style hints
            3. New-style hints

            Old-style hints did not overlap with server variable settings.

            New-style hints are more specific than server variable settings, so they override the server variable settings.

            Should new-style hints override old-style hints? TODO.

            Hints are "narrowly interpreted" and "best effort" - if a hint dictates to do something, like
            {code:sql}
            SELECT /*+ MRR(t1 t1_index1) */ ... FROM t1 ...
            {code}
            that means:
            {quote}
            When considering a query plan that involves using t1_index1 in a way that one can use MRR, use MRR.
            {quote}
            if the query planning is such that use of {{t1_index1}} doesn't allow to use MRR, it won't be used.
            The optimizer may also consider using {{t1_index2}} and pick that over using {{t1_index1}}.
            In such cases the hint is effectively ignored and no warning is given.
            Examples: [^mdev35483-mrr-is-narrow.sql]

            h2. 5. List of hints

            h3. 5.1 NO_RANGE_OPTIMIZATION hint

            It's an index-level hint that disables range optimization for certain index(es):
            {code:sql}
            SELECT /*+ NO_RANGE_OPTIMIZATION(tbl index1 index2) */ * FROM tbl ...
            {code}

            h3. 5.2 NO_ICP hint
            It's an index-level hint that disables Index Condition Pushdown for the indexes. ICP+BKA is disabled as well.
            {code:sql}
            SELECT /*+ NO_ICP(tbl index1 index2) */ * FROM tbl ...
            {code}

            h3. 5.3 MRR and NO_MRR hints

            Index-level hint to force or disable use of MRR.

            {code:sql}
            SELECT /*+ MRR(tbl index1 index2) */ * FROM tbl ...
            SELECT /*+ NO_MRR(tbl index1 index2) */ * FROM tbl ...
            {code}
            This controls
            * MRR optimization for range access ( [^mdev35483-mrr-is-narrow.sql] )
            * BKA [^mdev35483-mrr-controls-bka-partially.sql]

            h3. 5.4 BKA() and NO_BKA() hints
            It's a query block or table-level hint.

            BKA() also enables MRR to make BKA possible. (This is different from session variables, where one needs to enable MRR separately).

            This also enables BKAH. TODO what was the reason for this?

            TODO: NO_BKA() seems to lso enable BNL-H: [^mdev35483-no-bka-enables-hash-join.txt] ?

            h3. 5.5 BNL() and NO_BNL() hints

            In MySQL this controls hash join, so in MariaDB it controls BNL-H.

            The implementation is "BNL() hint effectively increases join_cache_level up to 4 "
            TODO: this seems to fail a fairly trivial example: [^mdev35483-bnl-fails-why.txt] ?

            h3. 5.6 MAX_EXECUTION_TIME() hint
            Example:
            {code:sql}
            SELECT /*+ MAX_EXECUTION_TIME(milliseconds) */ ... ;
            {code}

            This is a global hint. It limits query execution time. A query that doesn't finish in the time specified will be aborted with an error.

            Note: if the {{@@max_statement_time}} is set, the hint will be ignored and warning produced.
            TODO: This contradicts with the stated principle that "New-style hints are more specific than server variable settings, so they override the server variable settings".

            h2. 6. Subquery hints

            h3. 6.1. SUBQUERY hint

            {code}
            SUBQUERY([@query_block_name] MATERIALIZATION)
            SUBQUERY([@query_block_name] INTOEXISTS)
            {code}

            This controls non-semi-join subqueries. The parameter specifies which subquery to use. Use of this hint disables conversion of subquery into semi-join.

            h3. 6.2 SEMIJOIN, NO_SEMIJOIN

            This controls conversion of subquery to semi-join and which semi-join strategies are allowed.
            {code}
            [NO_]SEMIJOIN([@query_block_name] [strategy [, strategy] ...])
            {code}
            where strategy is one of DUPSWEEDOUT, FIRSTMATCH, LOOSESCAN, MATERIALIZATION.
            This is a self-contained description of Optimizer Hints in MariaDB, whatever is already implemented in the current patch.

            h1. Optimizer hints in MariaDB

            General idea is to be compatible with MySQL.
            MySQL hint docs: https://dev.mysql.com/doc/refman/8.4/en/optimizer-hints.html

            h2. 1. Hint syntax
            Hints are placed after the main statement verb

            {code:sql}
            UPDATE /*+ hints */ table ...;
            DELETE /*+ hints */ FROM table... ;
            SELECT /*+ hints */ ...
            {code}

            or after the SELECT keyword in any subquery:
            {code:sql}
            SELECT * FROM t1 WHERE a IN (SELECT /*+ hints */ ...)
            {code}

            There can be one or more hints separated with space
            {code}
              hints: hint hint ...
            {code}

            Each individual hint is hint name and arguments. In case there are no arguments,
            the () brackets are still present:

            {code}
            hint: hint_name([arguments])
            {code}

            Incorrect hints produce warnings. (TODO anything else?)
            Hints that are not ignored are kept in the query text (you can see them in SHOW PROCESSLIST, Slow Query Log, EXPLAIN EXTENDED)
            Hints that were incorrect and were ignored are removed from there.

            h2. 2. Hint hierarchy
            (todo: elaborate)

            h3. 2.1 Index-level hints
            Index-level hints apply to index(es).
            Possible syntax variants:
            {code}
            hint_name(table_name [index_name [, index_name] ...])
            hint_name(table_name@query_block [index_name [, index_name] ...])
            hint_name(@query_block table_name [index_name [, index_name] ...])
            {code}
             
            h2. 3. Query block naming: QB_NAME hint

            QB_NAME hint is used to assign a name to the query block the hint is in. The Query Block is either a SELECT or a top-level construct of UPDATE or DELETE statement.

            {code:sql}
            SELECT /*+ QB_NAME(foo) */ select_list FROM ...
            {code}

            The name can later be used
            * to refer to a query block, where required
            * to refer to a table as {{table_name@query_block_name}}.

            Hints inside VIEWs are not supported, yet. One can neither use hints in VIEW definitions, nor control query plans inside non-merged VIEWs (This is because QB_NAME binding is done "early", before we know that some tables are VIEWs)

            h3. 3.1 select#n names.
            Besides the given name, any query block is given a name {{select#n}}. It is printed in EXPLAIN EXTENDED output:
            {code}
            Warnings:
            Note 1003 select /*+ NO_RANGE_OPTIMIZATION(`t3`@`select#1` `PRIMARY`) */ ...
            {code}

            *At the moment it is NOT yet possible to use it in the hint text*:
            {code:sql}
            SELECT /*+ BKA(tbl1@`select#1`) */ 1 FROM tbl1 ...;
            {code}

            h3. 3.2 QB_NAME in CTEs.
            What {{QB_NAME(@name)}} is used in a CTE which is then used in multiple places? Hints that control @name will control the first use of the CTE.
            (This "just happens" due to the way CTEs are implemented. We could address it when addressing VIEWs)

            h2. 4. Effect of optimizer hints

            Optimizer can be controlled by
            1. Server variables - optimizer_switch, join_cache_level, etc, etc
            2. Old-style hints
            3. New-style hints

            Old-style hints did not overlap with server variable settings.

            New-style hints are more specific than server variable settings, so they override the server variable settings.

            Should new-style hints override old-style hints? TODO.

            Hints are "narrowly interpreted" and "best effort" - if a hint dictates to do something, like
            {code:sql}
            SELECT /*+ MRR(t1 t1_index1) */ ... FROM t1 ...
            {code}
            that means:
            {quote}
            When considering a query plan that involves using t1_index1 in a way that one can use MRR, use MRR.
            {quote}
            if the query planning is such that use of {{t1_index1}} doesn't allow to use MRR, it won't be used.
            The optimizer may also consider using {{t1_index2}} and pick that over using {{t1_index1}}.
            In such cases the hint is effectively ignored and no warning is given.
            Examples: [^mdev35483-mrr-is-narrow.sql]

            h2. 5. List of hints

            h3. 5.1 NO_RANGE_OPTIMIZATION hint

            It's an index-level hint that disables range optimization for certain index(es):
            {code:sql}
            SELECT /*+ NO_RANGE_OPTIMIZATION(tbl index1 index2) */ * FROM tbl ...
            {code}

            h3. 5.2 NO_ICP hint
            It's an index-level hint that disables Index Condition Pushdown for the indexes. ICP+BKA is disabled as well.
            {code:sql}
            SELECT /*+ NO_ICP(tbl index1 index2) */ * FROM tbl ...
            {code}

            h3. 5.3 MRR and NO_MRR hints

            Index-level hint to force or disable use of MRR.

            {code:sql}
            SELECT /*+ MRR(tbl index1 index2) */ * FROM tbl ...
            SELECT /*+ NO_MRR(tbl index1 index2) */ * FROM tbl ...
            {code}
            This controls
            * MRR optimization for range access ( [^mdev35483-mrr-is-narrow.sql] )
            * BKA [^mdev35483-mrr-controls-bka-partially.sql]

            h3. 5.4 BKA() and NO_BKA() hints
            It's a query block or table-level hint.

            BKA() also enables MRR to make BKA possible. (This is different from session variables, where one needs to enable MRR separately).

            This also enables BKAH. TODO what was the reason for this?

            TODO: NO_BKA() seems to lso enable BNL-H: [^mdev35483-no-bka-enables-hash-join.txt] ?

            h3. 5.5 BNL() and NO_BNL() hints

            In MySQL this controls hash join, so in MariaDB it controls BNL-H.

            The implementation is "BNL() hint effectively increases join_cache_level up to 4 "
            TODO: this seems to fail a fairly trivial example: [^mdev35483-bnl-fails-why.txt] ?

            h3. 5.6 MAX_EXECUTION_TIME() hint
            Example:
            {code:sql}
            SELECT /*+ MAX_EXECUTION_TIME(milliseconds) */ ... ;
            {code}

            This is a global hint. It limits query execution time. A query that doesn't finish in the time specified will be aborted with an error.

            Note: if the {{@@max_statement_time}} is set, the hint will be ignored and warning produced.
            TODO: This contradicts with the stated principle that "New-style hints are more specific than server variable settings, so they override the server variable settings".

            h2. 6. Subquery hints

            h3. 6.1. SUBQUERY hint

            {code}
            SUBQUERY([@query_block_name] MATERIALIZATION)
            SUBQUERY([@query_block_name] INTOEXISTS)
            {code}

            This controls non-semi-join subqueries. The parameter specifies which subquery to use. Use of this hint disables conversion of subquery into semi-join.

            h3. 6.2 SEMIJOIN, NO_SEMIJOIN

            This controls conversion of subquery to semi-join and which semi-join strategies are allowed.
            {code}
            [NO_]SEMIJOIN([@query_block_name] [strategy [, strategy] ...])
            {code}
            where strategy is one of DUPSWEEDOUT, FIRSTMATCH, LOOSESCAN, MATERIALIZATION.
            psergei Sergei Petrunia made changes -
            Description This is a self-contained description of Optimizer Hints in MariaDB, whatever is already implemented in the current patch.

            h1. Optimizer hints in MariaDB

            General idea is to be compatible with MySQL.
            MySQL hint docs: https://dev.mysql.com/doc/refman/8.4/en/optimizer-hints.html

            h2. 1. Hint syntax
            Hints are placed after the main statement verb

            {code:sql}
            UPDATE /*+ hints */ table ...;
            DELETE /*+ hints */ FROM table... ;
            SELECT /*+ hints */ ...
            {code}

            or after the SELECT keyword in any subquery:
            {code:sql}
            SELECT * FROM t1 WHERE a IN (SELECT /*+ hints */ ...)
            {code}

            There can be one or more hints separated with space
            {code}
              hints: hint hint ...
            {code}

            Each individual hint is hint name and arguments. In case there are no arguments,
            the () brackets are still present:

            {code}
            hint: hint_name([arguments])
            {code}

            Incorrect hints produce warnings. (TODO anything else?)
            Hints that are not ignored are kept in the query text (you can see them in SHOW PROCESSLIST, Slow Query Log, EXPLAIN EXTENDED)
            Hints that were incorrect and were ignored are removed from there.

            h2. 2. Hint hierarchy
            (todo: elaborate)

            h3. 2.1 Index-level hints
            Index-level hints apply to index(es).
            Possible syntax variants:
            {code}
            hint_name(table_name [index_name [, index_name] ...])
            hint_name(table_name@query_block [index_name [, index_name] ...])
            hint_name(@query_block table_name [index_name [, index_name] ...])
            {code}
             
            h2. 3. Query block naming: QB_NAME hint

            QB_NAME hint is used to assign a name to the query block the hint is in. The Query Block is either a SELECT or a top-level construct of UPDATE or DELETE statement.

            {code:sql}
            SELECT /*+ QB_NAME(foo) */ select_list FROM ...
            {code}

            The name can later be used
            * to refer to a query block, where required
            * to refer to a table as {{table_name@query_block_name}}.

            Hints inside VIEWs are not supported, yet. One can neither use hints in VIEW definitions, nor control query plans inside non-merged VIEWs (This is because QB_NAME binding is done "early", before we know that some tables are VIEWs)

            h3. 3.1 select#n names.
            Besides the given name, any query block is given a name {{select#n}}. It is printed in EXPLAIN EXTENDED output:
            {code}
            Warnings:
            Note 1003 select /*+ NO_RANGE_OPTIMIZATION(`t3`@`select#1` `PRIMARY`) */ ...
            {code}

            *At the moment it is NOT yet possible to use it in the hint text*:
            {code:sql}
            SELECT /*+ BKA(tbl1@`select#1`) */ 1 FROM tbl1 ...;
            {code}

            h3. 3.2 QB_NAME in CTEs.
            What {{QB_NAME(@name)}} is used in a CTE which is then used in multiple places? Hints that control @name will control the first use of the CTE.
            (This "just happens" due to the way CTEs are implemented. We could address it when addressing VIEWs)

            h2. 4. Effect of optimizer hints

            Optimizer can be controlled by
            1. Server variables - optimizer_switch, join_cache_level, etc, etc
            2. Old-style hints
            3. New-style hints

            Old-style hints did not overlap with server variable settings.

            New-style hints are more specific than server variable settings, so they override the server variable settings.

            Should new-style hints override old-style hints? TODO.

            Hints are "narrowly interpreted" and "best effort" - if a hint dictates to do something, like
            {code:sql}
            SELECT /*+ MRR(t1 t1_index1) */ ... FROM t1 ...
            {code}
            that means:
            {quote}
            When considering a query plan that involves using t1_index1 in a way that one can use MRR, use MRR.
            {quote}
            if the query planning is such that use of {{t1_index1}} doesn't allow to use MRR, it won't be used.
            The optimizer may also consider using {{t1_index2}} and pick that over using {{t1_index1}}.
            In such cases the hint is effectively ignored and no warning is given.
            Examples: [^mdev35483-mrr-is-narrow.sql]

            h2. 5. List of hints

            h3. 5.1 NO_RANGE_OPTIMIZATION hint

            It's an index-level hint that disables range optimization for certain index(es):
            {code:sql}
            SELECT /*+ NO_RANGE_OPTIMIZATION(tbl index1 index2) */ * FROM tbl ...
            {code}

            h3. 5.2 NO_ICP hint
            It's an index-level hint that disables Index Condition Pushdown for the indexes. ICP+BKA is disabled as well.
            {code:sql}
            SELECT /*+ NO_ICP(tbl index1 index2) */ * FROM tbl ...
            {code}

            h3. 5.3 MRR and NO_MRR hints

            Index-level hint to force or disable use of MRR.

            {code:sql}
            SELECT /*+ MRR(tbl index1 index2) */ * FROM tbl ...
            SELECT /*+ NO_MRR(tbl index1 index2) */ * FROM tbl ...
            {code}
            This controls
            * MRR optimization for range access ( [^mdev35483-mrr-is-narrow.sql] )
            * BKA [^mdev35483-mrr-controls-bka-partially.sql]

            h3. 5.4 BKA() and NO_BKA() hints
            It's a query block or table-level hint.

            BKA() also enables MRR to make BKA possible. (This is different from session variables, where one needs to enable MRR separately).

            This also enables BKAH. TODO what was the reason for this?

            TODO: NO_BKA() seems to lso enable BNL-H: [^mdev35483-no-bka-enables-hash-join.txt] ?

            h3. 5.5 BNL() and NO_BNL() hints

            In MySQL this controls hash join, so in MariaDB it controls BNL-H.

            The implementation is "BNL() hint effectively increases join_cache_level up to 4 "
            TODO: this seems to fail a fairly trivial example: [^mdev35483-bnl-fails-why.txt] ?

            h3. 5.6 MAX_EXECUTION_TIME() hint
            Example:
            {code:sql}
            SELECT /*+ MAX_EXECUTION_TIME(milliseconds) */ ... ;
            {code}

            This is a global hint. It limits query execution time. A query that doesn't finish in the time specified will be aborted with an error.

            Note: if the {{@@max_statement_time}} is set, the hint will be ignored and warning produced.
            TODO: This contradicts with the stated principle that "New-style hints are more specific than server variable settings, so they override the server variable settings".

            h2. 6. Subquery hints

            h3. 6.1. SUBQUERY hint

            {code}
            SUBQUERY([@query_block_name] MATERIALIZATION)
            SUBQUERY([@query_block_name] INTOEXISTS)
            {code}

            This controls non-semi-join subqueries. The parameter specifies which subquery to use. Use of this hint disables conversion of subquery into semi-join.

            h3. 6.2 SEMIJOIN, NO_SEMIJOIN

            This controls conversion of subquery to semi-join and which semi-join strategies are allowed.
            {code}
            [NO_]SEMIJOIN([@query_block_name] [strategy [, strategy] ...])
            {code}
            where strategy is one of DUPSWEEDOUT, FIRSTMATCH, LOOSESCAN, MATERIALIZATION.
            This is a self-contained description of Optimizer Hints in MariaDB, whatever is already implemented in the current patch.

            h1. Optimizer hints in MariaDB

            General idea is to be compatible with MySQL.
            MySQL hint docs: https://dev.mysql.com/doc/refman/8.4/en/optimizer-hints.html

            h2. 1. Hint syntax
            Hints are placed after the main statement verb

            {code:sql}
            UPDATE /*+ hints */ table ...;
            DELETE /*+ hints */ FROM table... ;
            SELECT /*+ hints */ ...
            {code}

            or after the SELECT keyword in any subquery:
            {code:sql}
            SELECT * FROM t1 WHERE a IN (SELECT /*+ hints */ ...)
            {code}

            There can be one or more hints separated with space
            {code}
              hints: hint hint ...
            {code}

            Each individual hint is hint name and arguments. In case there are no arguments,
            the () brackets are still present:

            {code}
            hint: hint_name([arguments])
            {code}

            Incorrect hints produce warnings. (TODO anything else?)
            Hints that are not ignored are kept in the query text (you can see them in SHOW PROCESSLIST, Slow Query Log, EXPLAIN EXTENDED)
            Hints that were incorrect and were ignored are removed from there.

            h2. 2. Hint hierarchy
            (todo: elaborate)

            h3. 2.1 Index-level hints
            Index-level hints apply to index(es).
            Possible syntax variants:
            {code}
            hint_name(table_name [index_name [, index_name] ...])
            hint_name(table_name@query_block [index_name [, index_name] ...])
            hint_name(@query_block table_name [index_name [, index_name] ...])
            {code}
             
            h2. 3. Query block naming: QB_NAME hint

            QB_NAME hint is used to assign a name to the query block the hint is in. The Query Block is either a SELECT or a top-level construct of UPDATE or DELETE statement.

            {code:sql}
            SELECT /*+ QB_NAME(foo) */ select_list FROM ...
            {code}

            The name can later be used
            * to refer to a query block, where required
            * to refer to a table as {{table_name@query_block_name}}.

            Hints inside VIEWs are not supported, yet. One can neither use hints in VIEW definitions, nor control query plans inside non-merged VIEWs (This is because QB_NAME binding is done "early", before we know that some tables are VIEWs)

            h3. 3.1 select#n names.
            Besides the given name, any query block is given a name {{select#n}}. It is printed in EXPLAIN EXTENDED output:
            {code}
            Warnings:
            Note 1003 select /*+ NO_RANGE_OPTIMIZATION(`t3`@`select#1` `PRIMARY`) */ ...
            {code}

            *At the moment it is NOT yet possible to use it in the hint text*:
            {code:sql}
            SELECT /*+ BKA(tbl1@`select#1`) */ 1 FROM tbl1 ...;
            {code}

            h3. 3.2 QB_NAME in CTEs.
            What {{QB_NAME(@name)}} is used in a CTE which is then used in multiple places? Hints that control @name will control the first use of the CTE.
            (This "just happens" due to the way CTEs are implemented. We could address it when addressing VIEWs)

            h2. 4. Effect of optimizer hints

            Optimizer can be controlled by
            1. Server variables - optimizer_switch, join_cache_level, etc, etc
            2. Old-style hints
            3. New-style hints

            Old-style hints did not overlap with server variable settings.

            New-style hints are more specific than server variable settings, so they override the server variable settings.

            Should new-style hints override old-style hints? TODO.

            Hints are "narrowly interpreted" and "best effort" - if a hint dictates to do something, like
            {code:sql}
            SELECT /*+ MRR(t1 t1_index1) */ ... FROM t1 ...
            {code}
            that means:
            {quote}
            When considering a query plan that involves using t1_index1 in a way that one can use MRR, use MRR.
            {quote}
            if the query planning is such that use of {{t1_index1}} doesn't allow to use MRR, it won't be used.
            The optimizer may also consider using {{t1_index2}} and pick that over using {{t1_index1}}.
            In such cases the hint is effectively ignored and no warning is given.
            Examples: [^mdev35483-mrr-is-narrow.sql]

            h2. 5. List of hints

            h3. 5.1 NO_RANGE_OPTIMIZATION hint

            It's an index-level hint that disables range optimization for certain index(es):
            {code:sql}
            SELECT /*+ NO_RANGE_OPTIMIZATION(tbl index1 index2) */ * FROM tbl ...
            {code}

            h3. 5.2 NO_ICP hint
            It's an index-level hint that disables Index Condition Pushdown for the indexes. ICP+BKA is disabled as well.
            {code:sql}
            SELECT /*+ NO_ICP(tbl index1 index2) */ * FROM tbl ...
            {code}

            h3. 5.3 MRR and NO_MRR hints

            Index-level hint to force or disable use of MRR.

            {code:sql}
            SELECT /*+ MRR(tbl index1 index2) */ * FROM tbl ...
            SELECT /*+ NO_MRR(tbl index1 index2) */ * FROM tbl ...
            {code}
            This controls
            * MRR optimization for range access ( [^mdev35483-mrr-is-narrow.sql] )
            * BKA [^mdev35483-mrr-controls-bka-partially.sql]

            h3. 5.4 BKA() and NO_BKA() hints
            It's a query block or table-level hint.

            BKA() also enables MRR to make BKA possible. (This is different from session variables, where one needs to enable MRR separately).

            This also enables BKAH. TODO what was the reason for this?

            TODO: NO_BKA() seems to lso enable BNL-H: [^mdev35483-no-bka-enables-hash-join.txt] ?

            h3. 5.5 BNL() and NO_BNL() hints

            In MySQL this controls hash join, so in MariaDB it controls BNL-H.

            The implementation is "BNL() hint effectively increases join_cache_level up to 4 "
            TODO: this seems to fail a fairly trivial example: [^mdev35483-bnl-fails-why.txt] ?

            h3. 5.6 MAX_EXECUTION_TIME() hint
            A global-level hint to limit query execution time:
            Example:
            {code:sql}
            SELECT /*+ MAX_EXECUTION_TIME(milliseconds) */ ... ;
            {code}

            A query that doesn't finish in the time specified will be aborted with an error.

            Note: if the {{@@max_statement_time}} is set, the hint will be ignored and warning produced.
            TODO: This contradicts with the stated principle that "New-style hints are more specific than server variable settings, so they override the server variable settings".

            h2. 6. Subquery hints

            h3. 6.1. SUBQUERY hint
            Query block-level hint.
            {code}
            SUBQUERY([@query_block_name] MATERIALIZATION)
            SUBQUERY([@query_block_name] INTOEXISTS)
            {code}

            This controls non-semi-join subqueries. The parameter specifies which subquery to use. Use of this hint disables conversion of subquery into semi-join.

            h3. 6.2 SEMIJOIN, NO_SEMIJOIN
            Query block-level hint.
            This controls conversion of subquery to semi-join and which semi-join strategies are allowed.
            {code}
            [NO_]SEMIJOIN([@query_block_name] [strategy [, strategy] ...])
            {code}
            where strategy is one of DUPSWEEDOUT, FIRSTMATCH, LOOSESCAN, MATERIALIZATION.
            psergei Sergei Petrunia made changes -
            Description This is a self-contained description of Optimizer Hints in MariaDB, whatever is already implemented in the current patch.

            h1. Optimizer hints in MariaDB

            General idea is to be compatible with MySQL.
            MySQL hint docs: https://dev.mysql.com/doc/refman/8.4/en/optimizer-hints.html

            h2. 1. Hint syntax
            Hints are placed after the main statement verb

            {code:sql}
            UPDATE /*+ hints */ table ...;
            DELETE /*+ hints */ FROM table... ;
            SELECT /*+ hints */ ...
            {code}

            or after the SELECT keyword in any subquery:
            {code:sql}
            SELECT * FROM t1 WHERE a IN (SELECT /*+ hints */ ...)
            {code}

            There can be one or more hints separated with space
            {code}
              hints: hint hint ...
            {code}

            Each individual hint is hint name and arguments. In case there are no arguments,
            the () brackets are still present:

            {code}
            hint: hint_name([arguments])
            {code}

            Incorrect hints produce warnings. (TODO anything else?)
            Hints that are not ignored are kept in the query text (you can see them in SHOW PROCESSLIST, Slow Query Log, EXPLAIN EXTENDED)
            Hints that were incorrect and were ignored are removed from there.

            h2. 2. Hint hierarchy
            (todo: elaborate)

            h3. 2.1 Index-level hints
            Index-level hints apply to index(es).
            Possible syntax variants:
            {code}
            hint_name(table_name [index_name [, index_name] ...])
            hint_name(table_name@query_block [index_name [, index_name] ...])
            hint_name(@query_block table_name [index_name [, index_name] ...])
            {code}
             
            h2. 3. Query block naming: QB_NAME hint

            QB_NAME hint is used to assign a name to the query block the hint is in. The Query Block is either a SELECT or a top-level construct of UPDATE or DELETE statement.

            {code:sql}
            SELECT /*+ QB_NAME(foo) */ select_list FROM ...
            {code}

            The name can later be used
            * to refer to a query block, where required
            * to refer to a table as {{table_name@query_block_name}}.

            Hints inside VIEWs are not supported, yet. One can neither use hints in VIEW definitions, nor control query plans inside non-merged VIEWs (This is because QB_NAME binding is done "early", before we know that some tables are VIEWs)

            h3. 3.1 select#n names.
            Besides the given name, any query block is given a name {{select#n}}. It is printed in EXPLAIN EXTENDED output:
            {code}
            Warnings:
            Note 1003 select /*+ NO_RANGE_OPTIMIZATION(`t3`@`select#1` `PRIMARY`) */ ...
            {code}

            *At the moment it is NOT yet possible to use it in the hint text*:
            {code:sql}
            SELECT /*+ BKA(tbl1@`select#1`) */ 1 FROM tbl1 ...;
            {code}

            h3. 3.2 QB_NAME in CTEs.
            What {{QB_NAME(@name)}} is used in a CTE which is then used in multiple places? Hints that control @name will control the first use of the CTE.
            (This "just happens" due to the way CTEs are implemented. We could address it when addressing VIEWs)

            h2. 4. Effect of optimizer hints

            Optimizer can be controlled by
            1. Server variables - optimizer_switch, join_cache_level, etc, etc
            2. Old-style hints
            3. New-style hints

            Old-style hints did not overlap with server variable settings.

            New-style hints are more specific than server variable settings, so they override the server variable settings.

            Should new-style hints override old-style hints? TODO.

            Hints are "narrowly interpreted" and "best effort" - if a hint dictates to do something, like
            {code:sql}
            SELECT /*+ MRR(t1 t1_index1) */ ... FROM t1 ...
            {code}
            that means:
            {quote}
            When considering a query plan that involves using t1_index1 in a way that one can use MRR, use MRR.
            {quote}
            if the query planning is such that use of {{t1_index1}} doesn't allow to use MRR, it won't be used.
            The optimizer may also consider using {{t1_index2}} and pick that over using {{t1_index1}}.
            In such cases the hint is effectively ignored and no warning is given.
            Examples: [^mdev35483-mrr-is-narrow.sql]

            h2. 5. List of hints

            h3. 5.1 NO_RANGE_OPTIMIZATION hint

            It's an index-level hint that disables range optimization for certain index(es):
            {code:sql}
            SELECT /*+ NO_RANGE_OPTIMIZATION(tbl index1 index2) */ * FROM tbl ...
            {code}

            h3. 5.2 NO_ICP hint
            It's an index-level hint that disables Index Condition Pushdown for the indexes. ICP+BKA is disabled as well.
            {code:sql}
            SELECT /*+ NO_ICP(tbl index1 index2) */ * FROM tbl ...
            {code}

            h3. 5.3 MRR and NO_MRR hints

            Index-level hint to force or disable use of MRR.

            {code:sql}
            SELECT /*+ MRR(tbl index1 index2) */ * FROM tbl ...
            SELECT /*+ NO_MRR(tbl index1 index2) */ * FROM tbl ...
            {code}
            This controls
            * MRR optimization for range access ( [^mdev35483-mrr-is-narrow.sql] )
            * BKA [^mdev35483-mrr-controls-bka-partially.sql]

            h3. 5.4 BKA() and NO_BKA() hints
            It's a query block or table-level hint.

            BKA() also enables MRR to make BKA possible. (This is different from session variables, where one needs to enable MRR separately).

            This also enables BKAH. TODO what was the reason for this?

            TODO: NO_BKA() seems to lso enable BNL-H: [^mdev35483-no-bka-enables-hash-join.txt] ?

            h3. 5.5 BNL() and NO_BNL() hints

            In MySQL this controls hash join, so in MariaDB it controls BNL-H.

            The implementation is "BNL() hint effectively increases join_cache_level up to 4 "
            TODO: this seems to fail a fairly trivial example: [^mdev35483-bnl-fails-why.txt] ?

            h3. 5.6 MAX_EXECUTION_TIME() hint
            A global-level hint to limit query execution time:
            Example:
            {code:sql}
            SELECT /*+ MAX_EXECUTION_TIME(milliseconds) */ ... ;
            {code}

            A query that doesn't finish in the time specified will be aborted with an error.

            Note: if the {{@@max_statement_time}} is set, the hint will be ignored and warning produced.
            TODO: This contradicts with the stated principle that "New-style hints are more specific than server variable settings, so they override the server variable settings".

            h2. 6. Subquery hints

            h3. 6.1. SUBQUERY hint
            Query block-level hint.
            {code}
            SUBQUERY([@query_block_name] MATERIALIZATION)
            SUBQUERY([@query_block_name] INTOEXISTS)
            {code}

            This controls non-semi-join subqueries. The parameter specifies which subquery to use. Use of this hint disables conversion of subquery into semi-join.

            h3. 6.2 SEMIJOIN, NO_SEMIJOIN
            Query block-level hint.
            This controls conversion of subquery to semi-join and which semi-join strategies are allowed.
            {code}
            [NO_]SEMIJOIN([@query_block_name] [strategy [, strategy] ...])
            {code}
            where strategy is one of DUPSWEEDOUT, FIRSTMATCH, LOOSESCAN, MATERIALIZATION.
            This is a self-contained description of Optimizer Hints in MariaDB, whatever is already implemented in the current patch.

            h1. Optimizer hints in MariaDB

            General idea is to be compatible with MySQL.
            MySQL hint docs: https://dev.mysql.com/doc/refman/8.4/en/optimizer-hints.html

            h2. 1. Hint syntax
            Hints are placed after the main statement verb

            {code:sql}
            UPDATE /*+ hints */ table ...;
            DELETE /*+ hints */ FROM table... ;
            SELECT /*+ hints */ ...
            {code}

            or after the SELECT keyword in any subquery:
            {code:sql}
            SELECT * FROM t1 WHERE a IN (SELECT /*+ hints */ ...)
            {code}

            There can be one or more hints separated with space
            {code}
              hints: hint hint ...
            {code}

            Each individual hint is hint name and arguments. In case there are no arguments,
            the () brackets are still present:

            {code}
            hint: hint_name([arguments])
            {code}

            Incorrect hints produce warnings. (TODO anything else?)
            Hints that are not ignored are kept in the query text (you can see them in SHOW PROCESSLIST, Slow Query Log, EXPLAIN EXTENDED)
            Hints that were incorrect and were ignored are removed from there.

            h2. 2. Hint hierarchy
            (todo: elaborate)

            h3. 2.1 Index-level hints
            Index-level hints apply to index(es).
            Possible syntax variants:
            {code}
            hint_name(table_name [index_name [, index_name] ...])
            hint_name(table_name@query_block [index_name [, index_name] ...])
            hint_name(@query_block table_name [index_name [, index_name] ...])
            {code}
             
            h2. 3. Query block naming: QB_NAME hint

            QB_NAME hint is used to assign a name to the query block the hint is in. The Query Block is either a SELECT or a top-level construct of UPDATE or DELETE statement.

            {code:sql}
            SELECT /*+ QB_NAME(foo) */ select_list FROM ...
            {code}

            The name can then can be used
            * to refer to the query block
            * to refer to a table in the query block as {{table_name@query_block_name}}.

            Query block scope is the whole statement. It is invalid to use the same name for multiple query blocks.
            One can refer to the query block "down into subquery", "down into derived table", "up to the parent" and "to a right sibling in the UNION". One cannot refer "to a left sibling in a UNION" (It's the same in MySQL).


            Hints inside VIEWs are not supported, yet. One can neither use hints in VIEW definitions, nor control query plans inside non-merged VIEWs (This is because QB_NAME binding is done "early", before we know that some tables are VIEWs)

            h3. 3.1 select#n names.
            Besides the given name, any query block is given a name {{select#n}}. It is printed in EXPLAIN EXTENDED output:
            {code}
            Warnings:
            Note 1003 select /*+ NO_RANGE_OPTIMIZATION(`t3`@`select#1` `PRIMARY`) */ ...
            {code}

            *At the moment it is NOT yet possible to use it in the hint text*:
            {code:sql}
            SELECT /*+ BKA(tbl1@`select#1`) */ 1 FROM tbl1 ...;
            {code}

            h3. 3.2 QB_NAME in CTEs.
            What {{QB_NAME(@name)}} is used in a CTE which is then used in multiple places? Hints that control @name will control the first use of the CTE.
            (This "just happens" due to the way CTEs are implemented. We could address it when addressing VIEWs)

            h2. 4. Effect of optimizer hints

            Optimizer can be controlled by
            1. Server variables - optimizer_switch, join_cache_level, etc, etc
            2. Old-style hints
            3. New-style hints

            Old-style hints did not overlap with server variable settings.

            New-style hints are more specific than server variable settings, so they override the server variable settings.

            Should new-style hints override old-style hints? TODO.

            Hints are "narrowly interpreted" and "best effort" - if a hint dictates to do something, like
            {code:sql}
            SELECT /*+ MRR(t1 t1_index1) */ ... FROM t1 ...
            {code}
            that means:
            {quote}
            When considering a query plan that involves using t1_index1 in a way that one can use MRR, use MRR.
            {quote}
            if the query planning is such that use of {{t1_index1}} doesn't allow to use MRR, it won't be used.
            The optimizer may also consider using {{t1_index2}} and pick that over using {{t1_index1}}.
            In such cases the hint is effectively ignored and no warning is given.
            Examples: [^mdev35483-mrr-is-narrow.sql]

            h2. 5. List of hints

            h3. 5.1 NO_RANGE_OPTIMIZATION hint

            It's an index-level hint that disables range optimization for certain index(es):
            {code:sql}
            SELECT /*+ NO_RANGE_OPTIMIZATION(tbl index1 index2) */ * FROM tbl ...
            {code}

            h3. 5.2 NO_ICP hint
            It's an index-level hint that disables Index Condition Pushdown for the indexes. ICP+BKA is disabled as well.
            {code:sql}
            SELECT /*+ NO_ICP(tbl index1 index2) */ * FROM tbl ...
            {code}

            h3. 5.3 MRR and NO_MRR hints

            Index-level hint to force or disable use of MRR.

            {code:sql}
            SELECT /*+ MRR(tbl index1 index2) */ * FROM tbl ...
            SELECT /*+ NO_MRR(tbl index1 index2) */ * FROM tbl ...
            {code}
            This controls
            * MRR optimization for range access ( [^mdev35483-mrr-is-narrow.sql] )
            * BKA [^mdev35483-mrr-controls-bka-partially.sql]

            h3. 5.4 BKA() and NO_BKA() hints
            It's a query block or table-level hint.

            BKA() also enables MRR to make BKA possible. (This is different from session variables, where one needs to enable MRR separately).

            This also enables BKAH. TODO what was the reason for this?

            TODO: NO_BKA() seems to lso enable BNL-H: [^mdev35483-no-bka-enables-hash-join.txt] ?

            h3. 5.5 BNL() and NO_BNL() hints

            In MySQL this controls hash join, so in MariaDB it controls BNL-H.

            The implementation is "BNL() hint effectively increases join_cache_level up to 4 "
            TODO: this seems to fail a fairly trivial example: [^mdev35483-bnl-fails-why.txt] ?

            h3. 5.6 MAX_EXECUTION_TIME() hint
            A global-level hint to limit query execution time:
            Example:
            {code:sql}
            SELECT /*+ MAX_EXECUTION_TIME(milliseconds) */ ... ;
            {code}

            A query that doesn't finish in the time specified will be aborted with an error.

            Note: if the {{@@max_statement_time}} is set, the hint will be ignored and warning produced.
            TODO: This contradicts with the stated principle that "New-style hints are more specific than server variable settings, so they override the server variable settings".

            h2. 6. Subquery hints

            h3. 6.1. SUBQUERY hint
            Query block-level hint.
            {code}
            SUBQUERY([@query_block_name] MATERIALIZATION)
            SUBQUERY([@query_block_name] INTOEXISTS)
            {code}

            This controls non-semi-join subqueries. The parameter specifies which subquery to use. Use of this hint disables conversion of subquery into semi-join.

            h3. 6.2 SEMIJOIN, NO_SEMIJOIN
            Query block-level hint.
            This controls conversion of subquery to semi-join and which semi-join strategies are allowed.
            {code}
            [NO_]SEMIJOIN([@query_block_name] [strategy [, strategy] ...])
            {code}
            where strategy is one of DUPSWEEDOUT, FIRSTMATCH, LOOSESCAN, MATERIALIZATION.
            psergei Sergei Petrunia made changes -
            Description This is a self-contained description of Optimizer Hints in MariaDB, whatever is already implemented in the current patch.

            h1. Optimizer hints in MariaDB

            General idea is to be compatible with MySQL.
            MySQL hint docs: https://dev.mysql.com/doc/refman/8.4/en/optimizer-hints.html

            h2. 1. Hint syntax
            Hints are placed after the main statement verb

            {code:sql}
            UPDATE /*+ hints */ table ...;
            DELETE /*+ hints */ FROM table... ;
            SELECT /*+ hints */ ...
            {code}

            or after the SELECT keyword in any subquery:
            {code:sql}
            SELECT * FROM t1 WHERE a IN (SELECT /*+ hints */ ...)
            {code}

            There can be one or more hints separated with space
            {code}
              hints: hint hint ...
            {code}

            Each individual hint is hint name and arguments. In case there are no arguments,
            the () brackets are still present:

            {code}
            hint: hint_name([arguments])
            {code}

            Incorrect hints produce warnings. (TODO anything else?)
            Hints that are not ignored are kept in the query text (you can see them in SHOW PROCESSLIST, Slow Query Log, EXPLAIN EXTENDED)
            Hints that were incorrect and were ignored are removed from there.

            h2. 2. Hint hierarchy
            (todo: elaborate)

            h3. 2.1 Index-level hints
            Index-level hints apply to index(es).
            Possible syntax variants:
            {code}
            hint_name(table_name [index_name [, index_name] ...])
            hint_name(table_name@query_block [index_name [, index_name] ...])
            hint_name(@query_block table_name [index_name [, index_name] ...])
            {code}
             
            h2. 3. Query block naming: QB_NAME hint

            QB_NAME hint is used to assign a name to the query block the hint is in. The Query Block is either a SELECT or a top-level construct of UPDATE or DELETE statement.

            {code:sql}
            SELECT /*+ QB_NAME(foo) */ select_list FROM ...
            {code}

            The name can then can be used
            * to refer to the query block
            * to refer to a table in the query block as {{table_name@query_block_name}}.

            Query block scope is the whole statement. It is invalid to use the same name for multiple query blocks.
            One can refer to the query block "down into subquery", "down into derived table", "up to the parent" and "to a right sibling in the UNION". One cannot refer "to a left sibling in a UNION" (It's the same in MySQL).


            Hints inside VIEWs are not supported, yet. One can neither use hints in VIEW definitions, nor control query plans inside non-merged VIEWs (This is because QB_NAME binding is done "early", before we know that some tables are VIEWs)

            h3. 3.1 select#n names.
            Besides the given name, any query block is given a name {{select#n}}. It is printed in EXPLAIN EXTENDED output:
            {code}
            Warnings:
            Note 1003 select /*+ NO_RANGE_OPTIMIZATION(`t3`@`select#1` `PRIMARY`) */ ...
            {code}

            *At the moment it is NOT yet possible to use it in the hint text*:
            {code:sql}
            SELECT /*+ BKA(tbl1@`select#1`) */ 1 FROM tbl1 ...;
            {code}

            h3. 3.2 QB_NAME in CTEs.
            What {{QB_NAME(@name)}} is used in a CTE which is then used in multiple places? Hints that control @name will control the first use of the CTE.
            (This "just happens" due to the way CTEs are implemented. We could address it when addressing VIEWs)

            h2. 4. Effect of optimizer hints

            Optimizer can be controlled by
            1. Server variables - optimizer_switch, join_cache_level, etc, etc
            2. Old-style hints
            3. New-style hints

            Old-style hints did not overlap with server variable settings.

            New-style hints are more specific than server variable settings, so they override the server variable settings.

            Should new-style hints override old-style hints? TODO.

            Hints are "narrowly interpreted" and "best effort" - if a hint dictates to do something, like
            {code:sql}
            SELECT /*+ MRR(t1 t1_index1) */ ... FROM t1 ...
            {code}
            that means:
            {quote}
            When considering a query plan that involves using t1_index1 in a way that one can use MRR, use MRR.
            {quote}
            if the query planning is such that use of {{t1_index1}} doesn't allow to use MRR, it won't be used.
            The optimizer may also consider using {{t1_index2}} and pick that over using {{t1_index1}}.
            In such cases the hint is effectively ignored and no warning is given.
            Examples: [^mdev35483-mrr-is-narrow.sql]

            h2. 5. List of hints

            h3. 5.1 NO_RANGE_OPTIMIZATION hint

            It's an index-level hint that disables range optimization for certain index(es):
            {code:sql}
            SELECT /*+ NO_RANGE_OPTIMIZATION(tbl index1 index2) */ * FROM tbl ...
            {code}

            h3. 5.2 NO_ICP hint
            It's an index-level hint that disables Index Condition Pushdown for the indexes. ICP+BKA is disabled as well.
            {code:sql}
            SELECT /*+ NO_ICP(tbl index1 index2) */ * FROM tbl ...
            {code}

            h3. 5.3 MRR and NO_MRR hints

            Index-level hint to force or disable use of MRR.

            {code:sql}
            SELECT /*+ MRR(tbl index1 index2) */ * FROM tbl ...
            SELECT /*+ NO_MRR(tbl index1 index2) */ * FROM tbl ...
            {code}
            This controls
            * MRR optimization for range access ( [^mdev35483-mrr-is-narrow.sql] )
            * BKA [^mdev35483-mrr-controls-bka-partially.sql]

            h3. 5.4 BKA() and NO_BKA() hints
            It's a query block or table-level hint.

            BKA() also enables MRR to make BKA possible. (This is different from session variables, where one needs to enable MRR separately).

            This also enables BKAH. TODO what was the reason for this?

            TODO: NO_BKA() seems to lso enable BNL-H: [^mdev35483-no-bka-enables-hash-join.txt] ?

            h3. 5.5 BNL() and NO_BNL() hints

            In MySQL this controls hash join, so in MariaDB it controls BNL-H.

            The implementation is "BNL() hint effectively increases join_cache_level up to 4 "
            TODO: this seems to fail a fairly trivial example: [^mdev35483-bnl-fails-why.txt] ?

            h3. 5.6 MAX_EXECUTION_TIME() hint
            A global-level hint to limit query execution time:
            Example:
            {code:sql}
            SELECT /*+ MAX_EXECUTION_TIME(milliseconds) */ ... ;
            {code}

            A query that doesn't finish in the time specified will be aborted with an error.

            Note: if the {{@@max_statement_time}} is set, the hint will be ignored and warning produced.
            TODO: This contradicts with the stated principle that "New-style hints are more specific than server variable settings, so they override the server variable settings".

            h2. 6. Subquery hints

            h3. 6.1. SUBQUERY hint
            Query block-level hint.
            {code}
            SUBQUERY([@query_block_name] MATERIALIZATION)
            SUBQUERY([@query_block_name] INTOEXISTS)
            {code}

            This controls non-semi-join subqueries. The parameter specifies which subquery to use. Use of this hint disables conversion of subquery into semi-join.

            h3. 6.2 SEMIJOIN, NO_SEMIJOIN
            Query block-level hint.
            This controls conversion of subquery to semi-join and which semi-join strategies are allowed.
            {code}
            [NO_]SEMIJOIN([@query_block_name] [strategy [, strategy] ...])
            {code}
            where strategy is one of DUPSWEEDOUT, FIRSTMATCH, LOOSESCAN, MATERIALIZATION.
            This is a self-contained description of Optimizer Hints in MariaDB, whatever is already implemented in the current patch.

            h1. Optimizer hints in MariaDB

            General idea is to be compatible with MySQL.
            MySQL hint docs: https://dev.mysql.com/doc/refman/8.4/en/optimizer-hints.html

            h2. 1. Hint syntax
            Hints are placed after the main statement verb

            {code:sql}
            UPDATE /*+ hints */ table ...;
            DELETE /*+ hints */ FROM table... ;
            SELECT /*+ hints */ ...
            {code}

            or after the SELECT keyword in any subquery:
            {code:sql}
            SELECT * FROM t1 WHERE a IN (SELECT /*+ hints */ ...)
            {code}

            There can be one or more hints separated with space
            {code}
              hints: hint hint ...
            {code}

            Each individual hint is hint name and arguments. In case there are no arguments,
            the () brackets are still present:

            {code}
            hint: hint_name([arguments])
            {code}

            Incorrect hints produce warnings (a setting to make them errors is not implemented yet).

            Hints that are not ignored are kept in the query text (you can see them in SHOW PROCESSLIST, Slow Query Log, EXPLAIN EXTENDED)
            Hints that were incorrect and were ignored are removed from there.

            h2. 2. Hint hierarchy
            (todo: elaborate)

            h3. 2.1 Index-level hints
            Index-level hints apply to index(es).
            Possible syntax variants:
            {code}
            hint_name(table_name [index_name [, index_name] ...])
            hint_name(table_name@query_block [index_name [, index_name] ...])
            hint_name(@query_block table_name [index_name [, index_name] ...])
            {code}
             
            h2. 3. Query block naming: QB_NAME hint

            QB_NAME hint is used to assign a name to the query block the hint is in. The Query Block is either a SELECT or a top-level construct of UPDATE or DELETE statement.

            {code:sql}
            SELECT /*+ QB_NAME(foo) */ select_list FROM ...
            {code}

            The name can then can be used
            * to refer to the query block
            * to refer to a table in the query block as {{table_name@query_block_name}}.

            Query block scope is the whole statement. It is invalid to use the same name for multiple query blocks.
            One can refer to the query block "down into subquery", "down into derived table", "up to the parent" and "to a right sibling in the UNION". One cannot refer "to a left sibling in a UNION" (It's the same in MySQL).


            Hints inside VIEWs are not supported, yet. One can neither use hints in VIEW definitions, nor control query plans inside non-merged VIEWs (This is because QB_NAME binding is done "early", before we know that some tables are VIEWs)

            h3. 3.1 select#n names.
            Besides the given name, any query block is given a name {{select#n}}. It is printed in EXPLAIN EXTENDED output:
            {code}
            Warnings:
            Note 1003 select /*+ NO_RANGE_OPTIMIZATION(`t3`@`select#1` `PRIMARY`) */ ...
            {code}

            *At the moment it is NOT yet possible to use it in the hint text*:
            {code:sql}
            SELECT /*+ BKA(tbl1@`select#1`) */ 1 FROM tbl1 ...;
            {code}

            h3. 3.2 QB_NAME in CTEs.
            What {{QB_NAME(@name)}} is used in a CTE which is then used in multiple places? Hints that control @name will control the first use of the CTE.
            (This "just happens" due to the way CTEs are implemented. We could address it when addressing VIEWs)

            h2. 4. Effect of optimizer hints

            Optimizer can be controlled by
            1. Server variables - optimizer_switch, join_cache_level, etc, etc
            2. Old-style hints
            3. New-style hints

            Old-style hints did not overlap with server variable settings.

            New-style hints are more specific than server variable settings, so they override the server variable settings.

            Should new-style hints override old-style hints? TODO.

            Hints are "narrowly interpreted" and "best effort" - if a hint dictates to do something, like
            {code:sql}
            SELECT /*+ MRR(t1 t1_index1) */ ... FROM t1 ...
            {code}
            that means:
            {quote}
            When considering a query plan that involves using t1_index1 in a way that one can use MRR, use MRR.
            {quote}
            if the query planning is such that use of {{t1_index1}} doesn't allow to use MRR, it won't be used.
            The optimizer may also consider using {{t1_index2}} and pick that over using {{t1_index1}}.
            In such cases the hint is effectively ignored and no warning is given.
            Examples: [^mdev35483-mrr-is-narrow.sql]

            h2. 5. List of hints

            h3. 5.1 NO_RANGE_OPTIMIZATION hint

            It's an index-level hint that disables range optimization for certain index(es):
            {code:sql}
            SELECT /*+ NO_RANGE_OPTIMIZATION(tbl index1 index2) */ * FROM tbl ...
            {code}

            h3. 5.2 NO_ICP hint
            It's an index-level hint that disables Index Condition Pushdown for the indexes. ICP+BKA is disabled as well.
            {code:sql}
            SELECT /*+ NO_ICP(tbl index1 index2) */ * FROM tbl ...
            {code}

            h3. 5.3 MRR and NO_MRR hints

            Index-level hint to force or disable use of MRR.

            {code:sql}
            SELECT /*+ MRR(tbl index1 index2) */ * FROM tbl ...
            SELECT /*+ NO_MRR(tbl index1 index2) */ * FROM tbl ...
            {code}
            This controls
            * MRR optimization for range access ( [^mdev35483-mrr-is-narrow.sql] )
            * BKA [^mdev35483-mrr-controls-bka-partially.sql]

            h3. 5.4 BKA() and NO_BKA() hints
            It's a query block or table-level hint.

            BKA() also enables MRR to make BKA possible. (This is different from session variables, where one needs to enable MRR separately).

            This also enables BKAH. TODO what was the reason for this?

            TODO: NO_BKA() seems to lso enable BNL-H: [^mdev35483-no-bka-enables-hash-join.txt] ?

            h3. 5.5 BNL() and NO_BNL() hints

            In MySQL this controls hash join, so in MariaDB it controls BNL-H.

            The implementation is "BNL() hint effectively increases join_cache_level up to 4 "
            TODO: this seems to fail a fairly trivial example: [^mdev35483-bnl-fails-why.txt] ?

            h3. 5.6 MAX_EXECUTION_TIME() hint
            A global-level hint to limit query execution time:
            Example:
            {code:sql}
            SELECT /*+ MAX_EXECUTION_TIME(milliseconds) */ ... ;
            {code}

            A query that doesn't finish in the time specified will be aborted with an error.

            Note: if the {{@@max_statement_time}} is set, the hint will be ignored and warning produced.
            TODO: This contradicts with the stated principle that "New-style hints are more specific than server variable settings, so they override the server variable settings".

            h2. 6. Subquery hints

            h3. 6.1. SUBQUERY hint
            Query block-level hint.
            {code}
            SUBQUERY([@query_block_name] MATERIALIZATION)
            SUBQUERY([@query_block_name] INTOEXISTS)
            {code}

            This controls non-semi-join subqueries. The parameter specifies which subquery to use. Use of this hint disables conversion of subquery into semi-join.

            h3. 6.2 SEMIJOIN, NO_SEMIJOIN
            Query block-level hint.
            This controls conversion of subquery to semi-join and which semi-join strategies are allowed.
            {code}
            [NO_]SEMIJOIN([@query_block_name] [strategy [, strategy] ...])
            {code}
            where strategy is one of DUPSWEEDOUT, FIRSTMATCH, LOOSESCAN, MATERIALIZATION.
            psergei Sergei Petrunia made changes -
            Description This is a self-contained description of Optimizer Hints in MariaDB, whatever is already implemented in the current patch.

            h1. Optimizer hints in MariaDB

            General idea is to be compatible with MySQL.
            MySQL hint docs: https://dev.mysql.com/doc/refman/8.4/en/optimizer-hints.html

            h2. 1. Hint syntax
            Hints are placed after the main statement verb

            {code:sql}
            UPDATE /*+ hints */ table ...;
            DELETE /*+ hints */ FROM table... ;
            SELECT /*+ hints */ ...
            {code}

            or after the SELECT keyword in any subquery:
            {code:sql}
            SELECT * FROM t1 WHERE a IN (SELECT /*+ hints */ ...)
            {code}

            There can be one or more hints separated with space
            {code}
              hints: hint hint ...
            {code}

            Each individual hint is hint name and arguments. In case there are no arguments,
            the () brackets are still present:

            {code}
            hint: hint_name([arguments])
            {code}

            Incorrect hints produce warnings (a setting to make them errors is not implemented yet).

            Hints that are not ignored are kept in the query text (you can see them in SHOW PROCESSLIST, Slow Query Log, EXPLAIN EXTENDED)
            Hints that were incorrect and were ignored are removed from there.

            h2. 2. Hint hierarchy
            (todo: elaborate)

            h3. 2.1 Index-level hints
            Index-level hints apply to index(es).
            Possible syntax variants:
            {code}
            hint_name(table_name [index_name [, index_name] ...])
            hint_name(table_name@query_block [index_name [, index_name] ...])
            hint_name(@query_block table_name [index_name [, index_name] ...])
            {code}
             
            h2. 3. Query block naming: QB_NAME hint

            QB_NAME hint is used to assign a name to the query block the hint is in. The Query Block is either a SELECT or a top-level construct of UPDATE or DELETE statement.

            {code:sql}
            SELECT /*+ QB_NAME(foo) */ select_list FROM ...
            {code}

            The name can then can be used
            * to refer to the query block
            * to refer to a table in the query block as {{table_name@query_block_name}}.

            Query block scope is the whole statement. It is invalid to use the same name for multiple query blocks.
            One can refer to the query block "down into subquery", "down into derived table", "up to the parent" and "to a right sibling in the UNION". One cannot refer "to a left sibling in a UNION" (It's the same in MySQL).


            Hints inside VIEWs are not supported, yet. One can neither use hints in VIEW definitions, nor control query plans inside non-merged VIEWs (This is because QB_NAME binding is done "early", before we know that some tables are VIEWs)

            h3. 3.1 select#n names.
            Besides the given name, any query block is given a name {{select#n}}. It is printed in EXPLAIN EXTENDED output:
            {code}
            Warnings:
            Note 1003 select /*+ NO_RANGE_OPTIMIZATION(`t3`@`select#1` `PRIMARY`) */ ...
            {code}

            *At the moment it is NOT yet possible to use it in the hint text*:
            {code:sql}
            SELECT /*+ BKA(tbl1@`select#1`) */ 1 FROM tbl1 ...;
            {code}

            h3. 3.2 QB_NAME in CTEs.
            What {{QB_NAME(@name)}} is used in a CTE which is then used in multiple places? Hints that control @name will control the first use of the CTE.
            (This "just happens" due to the way CTEs are implemented. We could address it when addressing VIEWs)

            h2. 4. Effect of optimizer hints

            Optimizer can be controlled by
            1. Server variables - optimizer_switch, join_cache_level, etc, etc
            2. Old-style hints
            3. New-style hints

            Old-style hints did not overlap with server variable settings.

            New-style hints are more specific than server variable settings, so they override the server variable settings.

            Should new-style hints override old-style hints? TODO.

            Hints are "narrowly interpreted" and "best effort" - if a hint dictates to do something, like
            {code:sql}
            SELECT /*+ MRR(t1 t1_index1) */ ... FROM t1 ...
            {code}
            that means:
            {quote}
            When considering a query plan that involves using t1_index1 in a way that one can use MRR, use MRR.
            {quote}
            if the query planning is such that use of {{t1_index1}} doesn't allow to use MRR, it won't be used.
            The optimizer may also consider using {{t1_index2}} and pick that over using {{t1_index1}}.
            In such cases the hint is effectively ignored and no warning is given.
            Examples: [^mdev35483-mrr-is-narrow.sql]

            h2. 5. List of hints

            h3. 5.1 NO_RANGE_OPTIMIZATION hint

            It's an index-level hint that disables range optimization for certain index(es):
            {code:sql}
            SELECT /*+ NO_RANGE_OPTIMIZATION(tbl index1 index2) */ * FROM tbl ...
            {code}

            h3. 5.2 NO_ICP hint
            It's an index-level hint that disables Index Condition Pushdown for the indexes. ICP+BKA is disabled as well.
            {code:sql}
            SELECT /*+ NO_ICP(tbl index1 index2) */ * FROM tbl ...
            {code}

            h3. 5.3 MRR and NO_MRR hints

            Index-level hint to force or disable use of MRR.

            {code:sql}
            SELECT /*+ MRR(tbl index1 index2) */ * FROM tbl ...
            SELECT /*+ NO_MRR(tbl index1 index2) */ * FROM tbl ...
            {code}
            This controls
            * MRR optimization for range access ( [^mdev35483-mrr-is-narrow.sql] )
            * BKA [^mdev35483-mrr-controls-bka-partially.sql]

            h3. 5.4 BKA() and NO_BKA() hints
            It's a query block or table-level hint.

            BKA() also enables MRR to make BKA possible. (This is different from session variables, where one needs to enable MRR separately).

            This also enables BKAH. TODO what was the reason for this?

            TODO: NO_BKA() seems to lso enable BNL-H: [^mdev35483-no-bka-enables-hash-join.txt] ?

            h3. 5.5 BNL() and NO_BNL() hints

            In MySQL this controls hash join, so in MariaDB it controls BNL-H.

            The implementation is "BNL() hint effectively increases join_cache_level up to 4 "
            TODO: this seems to fail a fairly trivial example: [^mdev35483-bnl-fails-why.txt] ?

            h3. 5.6 MAX_EXECUTION_TIME() hint
            A global-level hint to limit query execution time:
            Example:
            {code:sql}
            SELECT /*+ MAX_EXECUTION_TIME(milliseconds) */ ... ;
            {code}

            A query that doesn't finish in the time specified will be aborted with an error.

            Note: if the {{@@max_statement_time}} is set, the hint will be ignored and warning produced.
            TODO: This contradicts with the stated principle that "New-style hints are more specific than server variable settings, so they override the server variable settings".

            h2. 6. Subquery hints

            h3. 6.1. SUBQUERY hint
            Query block-level hint.
            {code}
            SUBQUERY([@query_block_name] MATERIALIZATION)
            SUBQUERY([@query_block_name] INTOEXISTS)
            {code}

            This controls non-semi-join subqueries. The parameter specifies which subquery to use. Use of this hint disables conversion of subquery into semi-join.

            h3. 6.2 SEMIJOIN, NO_SEMIJOIN
            Query block-level hint.
            This controls conversion of subquery to semi-join and which semi-join strategies are allowed.
            {code}
            [NO_]SEMIJOIN([@query_block_name] [strategy [, strategy] ...])
            {code}
            where strategy is one of DUPSWEEDOUT, FIRSTMATCH, LOOSESCAN, MATERIALIZATION.
            This is a self-contained description of Optimizer Hints in MariaDB, whatever is already implemented in the current patch.

            h1. Optimizer hints in MariaDB

            General idea is to be compatible with MySQL.
            MySQL hint docs: https://dev.mysql.com/doc/refman/8.4/en/optimizer-hints.html

            h2. 1. Hint syntax
            Hints are placed after the main statement verb

            {code:sql}
            UPDATE /*+ hints */ table ...;
            DELETE /*+ hints */ FROM table... ;
            SELECT /*+ hints */ ...
            {code}

            or after the SELECT keyword in any subquery:
            {code:sql}
            SELECT * FROM t1 WHERE a IN (SELECT /*+ hints */ ...)
            {code}

            There can be one or more hints separated with space
            {code}
              hints: hint hint ...
            {code}

            Each individual hint is hint name and arguments. In case there are no arguments,
            the () brackets are still present:

            {code}
            hint: hint_name([arguments])
            {code}

            Incorrect hints produce warnings (a setting to make them errors is not implemented yet).

            Hints that are not ignored are kept in the query text (you can see them in SHOW PROCESSLIST, Slow Query Log, EXPLAIN EXTENDED)
            Hints that were incorrect and were ignored are removed from there.

            h2. 2. Hint hierarchy
            (todo: elaborate)

            h3. 2.1 Index-level hints
            Index-level hints apply to index(es).
            Possible syntax variants:
            {code}
            hint_name(table_name [index_name [, index_name] ...])
            hint_name(table_name@query_block [index_name [, index_name] ...])
            hint_name(@query_block table_name [index_name [, index_name] ...])
            {code}
             
            h2. 3. Query block naming: QB_NAME hint

            QB_NAME hint is used to assign a name to the query block the hint is in. The Query Block is either a SELECT or a top-level construct of UPDATE or DELETE statement.

            {code:sql}
            SELECT /*+ QB_NAME(foo) */ select_list FROM ...
            {code}

            The name can then can be used
            * to refer to the query block
            * to refer to a table in the query block as {{table_name@query_block_name}}.

            Query block scope is the whole statement. It is invalid to use the same name for multiple query blocks.
            One can refer to the query block "down into subquery", "down into derived table", "up to the parent" and "to a right sibling in the UNION". One cannot refer "to a left sibling in a UNION" (It's the same in MySQL).


            Hints inside VIEWs are not supported, yet. One can neither use hints in VIEW definitions, nor control query plans inside non-merged VIEWs (This is because QB_NAME binding is done "early", before we know that some tables are VIEWs)

            h3. 3.1 select#n names.
            Besides the given name, any query block is given a name {{select#n}}. It is printed in EXPLAIN EXTENDED output:
            {code}
            Warnings:
            Note 1003 select /*+ NO_RANGE_OPTIMIZATION(`t3`@`select#1` `PRIMARY`) */ ...
            {code}

            *At the moment it is NOT yet possible to use it in the hint text*:
            {code:sql}
            SELECT /*+ BKA(tbl1@`select#1`) */ 1 FROM tbl1 ...;
            {code}

            h3. 3.2 QB_NAME in CTEs.
            What {{QB_NAME(@name)}} is used in a CTE which is then used in multiple places? Hints that control @name will control the first use of the CTE.
            (This "just happens" due to the way CTEs are implemented. We could address it when addressing VIEWs)

            h2. 4. Effect of optimizer hints

            Optimizer can be controlled by
            1. Server variables - optimizer_switch, join_cache_level, etc, etc
            2. Old-style hints
            3. New-style hints

            Old-style hints did not overlap with server variable settings.

            New-style hints are more specific than server variable settings, so they override the server variable settings.

            Should new-style hints override old-style hints? TODO.

            Hints are "narrowly interpreted" and "best effort" - if a hint dictates to do something, like
            {code:sql}
            SELECT /*+ MRR(t1 t1_index1) */ ... FROM t1 ...
            {code}
            that means:
            {quote}
            When considering a query plan that involves using t1_index1 in a way that one can use MRR, use MRR.
            {quote}
            if the query planning is such that use of {{t1_index1}} doesn't allow to use MRR, it won't be used.
            The optimizer may also consider using {{t1_index2}} and pick that over using {{t1_index1}}.
            In such cases the hint is effectively ignored and no warning is given.
            Examples: [^mdev35483-mrr-is-narrow.sql]

            h2. 5. List of hints

            h3. 5.1 NO_RANGE_OPTIMIZATION hint

            It's an index-level hint that disables range optimization for certain index(es):
            {code:sql}
            SELECT /*+ NO_RANGE_OPTIMIZATION(tbl index1 index2) */ * FROM tbl ...
            {code}

            h3. 5.2 NO_ICP hint
            It's an index-level hint that disables Index Condition Pushdown for the indexes. ICP+BKA is disabled as well.
            {code:sql}
            SELECT /*+ NO_ICP(tbl index1 index2) */ * FROM tbl ...
            {code}

            h3. 5.3 MRR and NO_MRR hints

            Index-level hint to force or disable use of MRR.

            {code:sql}
            SELECT /*+ MRR(tbl index1 index2) */ * FROM tbl ...
            SELECT /*+ NO_MRR(tbl index1 index2) */ * FROM tbl ...
            {code}
            This controls
            * MRR optimization for range access ( [^mdev35483-mrr-is-narrow.sql] )
            * BKA [^mdev35483-mrr-controls-bka-partially.sql]

            h3. 5.4 BKA() and NO_BKA() hints
            It's a query block or table-level hint.

            BKA() also enables MRR to make BKA possible. (This is different from session variables, where one needs to enable MRR separately).

            This also enables BKAH. TODO what was the reason for this?

            h3. 5.5 BNL() and NO_BNL() hints

            In MySQL this controls hash join, so in MariaDB it controls BNL-H.

            The implementation is "BNL() hint effectively increases join_cache_level up to 4 "
            TODO: this seems to fail a fairly trivial example: [^mdev35483-bnl-fails-why.txt] ?

            h3. 5.6 MAX_EXECUTION_TIME() hint
            A global-level hint to limit query execution time:
            Example:
            {code:sql}
            SELECT /*+ MAX_EXECUTION_TIME(milliseconds) */ ... ;
            {code}

            A query that doesn't finish in the time specified will be aborted with an error.

            Note: if the {{@@max_statement_time}} is set, the hint will be ignored and warning produced.
            TODO: This contradicts with the stated principle that "New-style hints are more specific than server variable settings, so they override the server variable settings".

            h2. 6. Subquery hints

            h3. 6.1. SUBQUERY hint
            Query block-level hint.
            {code}
            SUBQUERY([@query_block_name] MATERIALIZATION)
            SUBQUERY([@query_block_name] INTOEXISTS)
            {code}

            This controls non-semi-join subqueries. The parameter specifies which subquery to use. Use of this hint disables conversion of subquery into semi-join.

            h3. 6.2 SEMIJOIN, NO_SEMIJOIN
            Query block-level hint.
            This controls conversion of subquery to semi-join and which semi-join strategies are allowed.
            {code}
            [NO_]SEMIJOIN([@query_block_name] [strategy [, strategy] ...])
            {code}
            where strategy is one of DUPSWEEDOUT, FIRSTMATCH, LOOSESCAN, MATERIALIZATION.
            psergei Sergei Petrunia made changes -
            Attachment mdev35483-no-bka-enables-hash-join.txt [ 74272 ]
            psergei Sergei Petrunia made changes -
            Description This is a self-contained description of Optimizer Hints in MariaDB, whatever is already implemented in the current patch.

            h1. Optimizer hints in MariaDB

            General idea is to be compatible with MySQL.
            MySQL hint docs: https://dev.mysql.com/doc/refman/8.4/en/optimizer-hints.html

            h2. 1. Hint syntax
            Hints are placed after the main statement verb

            {code:sql}
            UPDATE /*+ hints */ table ...;
            DELETE /*+ hints */ FROM table... ;
            SELECT /*+ hints */ ...
            {code}

            or after the SELECT keyword in any subquery:
            {code:sql}
            SELECT * FROM t1 WHERE a IN (SELECT /*+ hints */ ...)
            {code}

            There can be one or more hints separated with space
            {code}
              hints: hint hint ...
            {code}

            Each individual hint is hint name and arguments. In case there are no arguments,
            the () brackets are still present:

            {code}
            hint: hint_name([arguments])
            {code}

            Incorrect hints produce warnings (a setting to make them errors is not implemented yet).

            Hints that are not ignored are kept in the query text (you can see them in SHOW PROCESSLIST, Slow Query Log, EXPLAIN EXTENDED)
            Hints that were incorrect and were ignored are removed from there.

            h2. 2. Hint hierarchy
            (todo: elaborate)

            h3. 2.1 Index-level hints
            Index-level hints apply to index(es).
            Possible syntax variants:
            {code}
            hint_name(table_name [index_name [, index_name] ...])
            hint_name(table_name@query_block [index_name [, index_name] ...])
            hint_name(@query_block table_name [index_name [, index_name] ...])
            {code}
             
            h2. 3. Query block naming: QB_NAME hint

            QB_NAME hint is used to assign a name to the query block the hint is in. The Query Block is either a SELECT or a top-level construct of UPDATE or DELETE statement.

            {code:sql}
            SELECT /*+ QB_NAME(foo) */ select_list FROM ...
            {code}

            The name can then can be used
            * to refer to the query block
            * to refer to a table in the query block as {{table_name@query_block_name}}.

            Query block scope is the whole statement. It is invalid to use the same name for multiple query blocks.
            One can refer to the query block "down into subquery", "down into derived table", "up to the parent" and "to a right sibling in the UNION". One cannot refer "to a left sibling in a UNION" (It's the same in MySQL).


            Hints inside VIEWs are not supported, yet. One can neither use hints in VIEW definitions, nor control query plans inside non-merged VIEWs (This is because QB_NAME binding is done "early", before we know that some tables are VIEWs)

            h3. 3.1 select#n names.
            Besides the given name, any query block is given a name {{select#n}}. It is printed in EXPLAIN EXTENDED output:
            {code}
            Warnings:
            Note 1003 select /*+ NO_RANGE_OPTIMIZATION(`t3`@`select#1` `PRIMARY`) */ ...
            {code}

            *At the moment it is NOT yet possible to use it in the hint text*:
            {code:sql}
            SELECT /*+ BKA(tbl1@`select#1`) */ 1 FROM tbl1 ...;
            {code}

            h3. 3.2 QB_NAME in CTEs.
            What {{QB_NAME(@name)}} is used in a CTE which is then used in multiple places? Hints that control @name will control the first use of the CTE.
            (This "just happens" due to the way CTEs are implemented. We could address it when addressing VIEWs)

            h2. 4. Effect of optimizer hints

            Optimizer can be controlled by
            1. Server variables - optimizer_switch, join_cache_level, etc, etc
            2. Old-style hints
            3. New-style hints

            Old-style hints did not overlap with server variable settings.

            New-style hints are more specific than server variable settings, so they override the server variable settings.

            Should new-style hints override old-style hints? TODO.

            Hints are "narrowly interpreted" and "best effort" - if a hint dictates to do something, like
            {code:sql}
            SELECT /*+ MRR(t1 t1_index1) */ ... FROM t1 ...
            {code}
            that means:
            {quote}
            When considering a query plan that involves using t1_index1 in a way that one can use MRR, use MRR.
            {quote}
            if the query planning is such that use of {{t1_index1}} doesn't allow to use MRR, it won't be used.
            The optimizer may also consider using {{t1_index2}} and pick that over using {{t1_index1}}.
            In such cases the hint is effectively ignored and no warning is given.
            Examples: [^mdev35483-mrr-is-narrow.sql]

            h2. 5. List of hints

            h3. 5.1 NO_RANGE_OPTIMIZATION hint

            It's an index-level hint that disables range optimization for certain index(es):
            {code:sql}
            SELECT /*+ NO_RANGE_OPTIMIZATION(tbl index1 index2) */ * FROM tbl ...
            {code}

            h3. 5.2 NO_ICP hint
            It's an index-level hint that disables Index Condition Pushdown for the indexes. ICP+BKA is disabled as well.
            {code:sql}
            SELECT /*+ NO_ICP(tbl index1 index2) */ * FROM tbl ...
            {code}

            h3. 5.3 MRR and NO_MRR hints

            Index-level hint to force or disable use of MRR.

            {code:sql}
            SELECT /*+ MRR(tbl index1 index2) */ * FROM tbl ...
            SELECT /*+ NO_MRR(tbl index1 index2) */ * FROM tbl ...
            {code}
            This controls
            * MRR optimization for range access ( [^mdev35483-mrr-is-narrow.sql] )
            * BKA [^mdev35483-mrr-controls-bka-partially.sql]

            h3. 5.4 BKA() and NO_BKA() hints
            It's a query block or table-level hint.

            BKA() also enables MRR to make BKA possible. (This is different from session variables, where one needs to enable MRR separately).

            This also enables BKAH. TODO what was the reason for this?

            h3. 5.5 BNL() and NO_BNL() hints

            In MySQL this controls hash join, so in MariaDB it controls BNL-H.

            The implementation is "BNL() hint effectively increases join_cache_level up to 4 "
            TODO: this seems to fail a fairly trivial example: [^mdev35483-bnl-fails-why.txt] ?

            h3. 5.6 MAX_EXECUTION_TIME() hint
            A global-level hint to limit query execution time:
            Example:
            {code:sql}
            SELECT /*+ MAX_EXECUTION_TIME(milliseconds) */ ... ;
            {code}

            A query that doesn't finish in the time specified will be aborted with an error.

            Note: if the {{@@max_statement_time}} is set, the hint will be ignored and warning produced.
            TODO: This contradicts with the stated principle that "New-style hints are more specific than server variable settings, so they override the server variable settings".

            h2. 6. Subquery hints

            h3. 6.1. SUBQUERY hint
            Query block-level hint.
            {code}
            SUBQUERY([@query_block_name] MATERIALIZATION)
            SUBQUERY([@query_block_name] INTOEXISTS)
            {code}

            This controls non-semi-join subqueries. The parameter specifies which subquery to use. Use of this hint disables conversion of subquery into semi-join.

            h3. 6.2 SEMIJOIN, NO_SEMIJOIN
            Query block-level hint.
            This controls conversion of subquery to semi-join and which semi-join strategies are allowed.
            {code}
            [NO_]SEMIJOIN([@query_block_name] [strategy [, strategy] ...])
            {code}
            where strategy is one of DUPSWEEDOUT, FIRSTMATCH, LOOSESCAN, MATERIALIZATION.
            This is a self-contained description of Optimizer Hints in MariaDB, whatever is already implemented in the current patch.

            h1. Optimizer hints in MariaDB

            General idea is to be compatible with MySQL.
            MySQL hint docs: https://dev.mysql.com/doc/refman/8.4/en/optimizer-hints.html

            h2. 1. Hint syntax
            Hints are placed after the main statement verb

            {code:sql}
            UPDATE /*+ hints */ table ...;
            DELETE /*+ hints */ FROM table... ;
            SELECT /*+ hints */ ...
            {code}

            or after the SELECT keyword in any subquery:
            {code:sql}
            SELECT * FROM t1 WHERE a IN (SELECT /*+ hints */ ...)
            {code}

            There can be one or more hints separated with space
            {code}
              hints: hint hint ...
            {code}

            Each individual hint is hint name and arguments. In case there are no arguments,
            the () brackets are still present:

            {code}
            hint: hint_name([arguments])
            {code}

            Incorrect hints produce warnings (a setting to make them errors is not implemented yet).

            Hints that are not ignored are kept in the query text (you can see them in SHOW PROCESSLIST, Slow Query Log, EXPLAIN EXTENDED)
            Hints that were incorrect and were ignored are removed from there.

            h2. 2. Hint hierarchy
            (todo: elaborate)
            Hints can be global, table-level, or index-level.

            h3. 2.1 Table-level hints
            {code}
            hint_name(table_name [index_name [, index_name] ...])
            {code}
            h3. 2.2 Index-level hints
            Index-level hints apply to index(es).
            Possible syntax variants:
            {code}
            hint_name(table_name [index_name [, index_name] ...])
            hint_name(table_name@query_block [index_name [, index_name] ...])
            hint_name(@query_block table_name [index_name [, index_name] ...])
            {code}
             
            h2. 3. Query block naming: QB_NAME hint

            QB_NAME hint is used to assign a name to the query block the hint is in. The Query Block is either a SELECT or a top-level construct of UPDATE or DELETE statement.

            {code:sql}
            SELECT /*+ QB_NAME(foo) */ select_list FROM ...
            {code}

            The name can then can be used
            * to refer to the query block
            * to refer to a table in the query block as {{table_name@query_block_name}}.

            Query block scope is the whole statement. It is invalid to use the same name for multiple query blocks.
            One can refer to the query block "down into subquery", "down into derived table", "up to the parent" and "to a right sibling in the UNION". One cannot refer "to a left sibling in a UNION" (It's the same in MySQL).


            Hints inside VIEWs are not supported, yet. One can neither use hints in VIEW definitions, nor control query plans inside non-merged VIEWs (This is because QB_NAME binding is done "early", before we know that some tables are VIEWs)

            h3. 3.1 select#n names.
            Besides the given name, any query block is given a name {{select#n}}. It is printed in EXPLAIN EXTENDED output:
            {code}
            Warnings:
            Note 1003 select /*+ NO_RANGE_OPTIMIZATION(`t3`@`select#1` `PRIMARY`) */ ...
            {code}

            *At the moment it is NOT yet possible to use it in the hint text*:
            {code:sql}
            SELECT /*+ BKA(tbl1@`select#1`) */ 1 FROM tbl1 ...;
            {code}

            h3. 3.2 QB_NAME in CTEs.
            What {{QB_NAME(@name)}} is used in a CTE which is then used in multiple places? Hints that control @name will control the first use of the CTE.
            (This "just happens" due to the way CTEs are implemented. We could address it when addressing VIEWs)

            h2. 4. Effect of optimizer hints

            Optimizer can be controlled by
            1. Server variables - optimizer_switch, join_cache_level, etc, etc
            2. Old-style hints
            3. New-style hints

            Old-style hints did not overlap with server variable settings.

            New-style hints are more specific than server variable settings, so they override the server variable settings.

            Should new-style hints override old-style hints? TODO.

            Hints are "narrowly interpreted" and "best effort" - if a hint dictates to do something, like
            {code:sql}
            SELECT /*+ MRR(t1 t1_index1) */ ... FROM t1 ...
            {code}
            that means:
            {quote}
            When considering a query plan that involves using t1_index1 in a way that one can use MRR, use MRR.
            {quote}
            if the query planning is such that use of {{t1_index1}} doesn't allow to use MRR, it won't be used.
            The optimizer may also consider using {{t1_index2}} and pick that over using {{t1_index1}}.
            In such cases the hint is effectively ignored and no warning is given.
            Examples: [^mdev35483-mrr-is-narrow.sql]

            h2. 5. List of hints

            h3. 5.1 NO_RANGE_OPTIMIZATION hint

            It's an index-level hint that disables range optimization for certain index(es):
            {code:sql}
            SELECT /*+ NO_RANGE_OPTIMIZATION(tbl index1 index2) */ * FROM tbl ...
            {code}

            h3. 5.2 NO_ICP hint
            It's an index-level hint that disables Index Condition Pushdown for the indexes. ICP+BKA is disabled as well.
            {code:sql}
            SELECT /*+ NO_ICP(tbl index1 index2) */ * FROM tbl ...
            {code}

            h3. 5.3 MRR and NO_MRR hints

            Index-level hint to force or disable use of MRR.

            {code:sql}
            SELECT /*+ MRR(tbl index1 index2) */ * FROM tbl ...
            SELECT /*+ NO_MRR(tbl index1 index2) */ * FROM tbl ...
            {code}
            This controls
            * MRR optimization for range access ( [^mdev35483-mrr-is-narrow.sql] )
            * BKA [^mdev35483-mrr-controls-bka-partially.sql]

            h3. 5.4 BKA() and NO_BKA() hints
            It's a query block or table-level hint.

            BKA() also enables MRR to make BKA possible. (This is different from session variables, where one needs to enable MRR separately).

            This also enables BKAH. TODO what was the reason for this?

            h3. 5.5 BNL() and NO_BNL() hints

            In MySQL this controls hash join, so in MariaDB it controls BNL-H.

            The implementation is "BNL() hint effectively increases join_cache_level up to 4 "
            TODO: this seems to fail a fairly trivial example: [^mdev35483-bnl-fails-why.txt] ?

            h3. 5.6 MAX_EXECUTION_TIME() hint
            A global-level hint to limit query execution time:
            Example:
            {code:sql}
            SELECT /*+ MAX_EXECUTION_TIME(milliseconds) */ ... ;
            {code}

            A query that doesn't finish in the time specified will be aborted with an error.

            Note: if the {{@@max_statement_time}} is set, the hint will be ignored and warning produced.
            TODO: This contradicts with the stated principle that "New-style hints are more specific than server variable settings, so they override the server variable settings".

            h2. 6. Subquery hints

            h3. 6.1. SUBQUERY hint
            Query block-level hint.
            {code}
            SUBQUERY([@query_block_name] MATERIALIZATION)
            SUBQUERY([@query_block_name] INTOEXISTS)
            {code}

            This controls non-semi-join subqueries. The parameter specifies which subquery to use. Use of this hint disables conversion of subquery into semi-join.

            h3. 6.2 SEMIJOIN, NO_SEMIJOIN
            Query block-level hint.
            This controls conversion of subquery to semi-join and which semi-join strategies are allowed.
            {code}
            [NO_]SEMIJOIN([@query_block_name] [strategy [, strategy] ...])
            {code}
            where strategy is one of DUPSWEEDOUT, FIRSTMATCH, LOOSESCAN, MATERIALIZATION.
            psergei Sergei Petrunia made changes -
            Description This is a self-contained description of Optimizer Hints in MariaDB, whatever is already implemented in the current patch.

            h1. Optimizer hints in MariaDB

            General idea is to be compatible with MySQL.
            MySQL hint docs: https://dev.mysql.com/doc/refman/8.4/en/optimizer-hints.html

            h2. 1. Hint syntax
            Hints are placed after the main statement verb

            {code:sql}
            UPDATE /*+ hints */ table ...;
            DELETE /*+ hints */ FROM table... ;
            SELECT /*+ hints */ ...
            {code}

            or after the SELECT keyword in any subquery:
            {code:sql}
            SELECT * FROM t1 WHERE a IN (SELECT /*+ hints */ ...)
            {code}

            There can be one or more hints separated with space
            {code}
              hints: hint hint ...
            {code}

            Each individual hint is hint name and arguments. In case there are no arguments,
            the () brackets are still present:

            {code}
            hint: hint_name([arguments])
            {code}

            Incorrect hints produce warnings (a setting to make them errors is not implemented yet).

            Hints that are not ignored are kept in the query text (you can see them in SHOW PROCESSLIST, Slow Query Log, EXPLAIN EXTENDED)
            Hints that were incorrect and were ignored are removed from there.

            h2. 2. Hint hierarchy
            (todo: elaborate)
            Hints can be global, table-level, or index-level.

            h3. 2.1 Table-level hints
            {code}
            hint_name(table_name [index_name [, index_name] ...])
            {code}
            h3. 2.2 Index-level hints
            Index-level hints apply to index(es).
            Possible syntax variants:
            {code}
            hint_name(table_name [index_name [, index_name] ...])
            hint_name(table_name@query_block [index_name [, index_name] ...])
            hint_name(@query_block table_name [index_name [, index_name] ...])
            {code}
             
            h2. 3. Query block naming: QB_NAME hint

            QB_NAME hint is used to assign a name to the query block the hint is in. The Query Block is either a SELECT or a top-level construct of UPDATE or DELETE statement.

            {code:sql}
            SELECT /*+ QB_NAME(foo) */ select_list FROM ...
            {code}

            The name can then can be used
            * to refer to the query block
            * to refer to a table in the query block as {{table_name@query_block_name}}.

            Query block scope is the whole statement. It is invalid to use the same name for multiple query blocks.
            One can refer to the query block "down into subquery", "down into derived table", "up to the parent" and "to a right sibling in the UNION". One cannot refer "to a left sibling in a UNION" (It's the same in MySQL).


            Hints inside VIEWs are not supported, yet. One can neither use hints in VIEW definitions, nor control query plans inside non-merged VIEWs (This is because QB_NAME binding is done "early", before we know that some tables are VIEWs)

            h3. 3.1 select#n names.
            Besides the given name, any query block is given a name {{select#n}}. It is printed in EXPLAIN EXTENDED output:
            {code}
            Warnings:
            Note 1003 select /*+ NO_RANGE_OPTIMIZATION(`t3`@`select#1` `PRIMARY`) */ ...
            {code}

            *At the moment it is NOT yet possible to use it in the hint text*:
            {code:sql}
            SELECT /*+ BKA(tbl1@`select#1`) */ 1 FROM tbl1 ...;
            {code}

            h3. 3.2 QB_NAME in CTEs.
            What {{QB_NAME(@name)}} is used in a CTE which is then used in multiple places? Hints that control @name will control the first use of the CTE.
            (This "just happens" due to the way CTEs are implemented. We could address it when addressing VIEWs)

            h2. 4. Effect of optimizer hints

            Optimizer can be controlled by
            1. Server variables - optimizer_switch, join_cache_level, etc, etc
            2. Old-style hints
            3. New-style hints

            Old-style hints did not overlap with server variable settings.

            New-style hints are more specific than server variable settings, so they override the server variable settings.

            Should new-style hints override old-style hints? TODO.

            Hints are "narrowly interpreted" and "best effort" - if a hint dictates to do something, like
            {code:sql}
            SELECT /*+ MRR(t1 t1_index1) */ ... FROM t1 ...
            {code}
            that means:
            {quote}
            When considering a query plan that involves using t1_index1 in a way that one can use MRR, use MRR.
            {quote}
            if the query planning is such that use of {{t1_index1}} doesn't allow to use MRR, it won't be used.
            The optimizer may also consider using {{t1_index2}} and pick that over using {{t1_index1}}.
            In such cases the hint is effectively ignored and no warning is given.
            Examples: [^mdev35483-mrr-is-narrow.sql]

            h2. 5. List of hints

            h3. 5.1 NO_RANGE_OPTIMIZATION hint

            It's an index-level hint that disables range optimization for certain index(es):
            {code:sql}
            SELECT /*+ NO_RANGE_OPTIMIZATION(tbl index1 index2) */ * FROM tbl ...
            {code}

            h3. 5.2 NO_ICP hint
            It's an index-level hint that disables Index Condition Pushdown for the indexes. ICP+BKA is disabled as well.
            {code:sql}
            SELECT /*+ NO_ICP(tbl index1 index2) */ * FROM tbl ...
            {code}

            h3. 5.3 MRR and NO_MRR hints

            Index-level hint to force or disable use of MRR.

            {code:sql}
            SELECT /*+ MRR(tbl index1 index2) */ * FROM tbl ...
            SELECT /*+ NO_MRR(tbl index1 index2) */ * FROM tbl ...
            {code}
            This controls
            * MRR optimization for range access ( [^mdev35483-mrr-is-narrow.sql] )
            * BKA [^mdev35483-mrr-controls-bka-partially.sql]

            h3. 5.4 BKA() and NO_BKA() hints
            It's a query block or table-level hint.

            BKA() also enables MRR to make BKA possible. (This is different from session variables, where one needs to enable MRR separately).

            This also enables BKAH. TODO what was the reason for this?

            h3. 5.5 BNL() and NO_BNL() hints

            In MySQL this controls hash join, so in MariaDB it controls BNL-H.

            The implementation is "BNL() hint effectively increases join_cache_level up to 4 "
            TODO: this seems to fail a fairly trivial example: [^mdev35483-bnl-fails-why.txt] ?

            h3. 5.6 MAX_EXECUTION_TIME() hint
            A global-level hint to limit query execution time:
            Example:
            {code:sql}
            SELECT /*+ MAX_EXECUTION_TIME(milliseconds) */ ... ;
            {code}

            A query that doesn't finish in the time specified will be aborted with an error.

            Note: if the {{@@max_statement_time}} is set, the hint will be ignored and warning produced.
            TODO: This contradicts with the stated principle that "New-style hints are more specific than server variable settings, so they override the server variable settings".

            h2. 6. Subquery hints

            h3. 6.1. SUBQUERY hint
            Query block-level hint.
            {code}
            SUBQUERY([@query_block_name] MATERIALIZATION)
            SUBQUERY([@query_block_name] INTOEXISTS)
            {code}

            This controls non-semi-join subqueries. The parameter specifies which subquery to use. Use of this hint disables conversion of subquery into semi-join.

            h3. 6.2 SEMIJOIN, NO_SEMIJOIN
            Query block-level hint.
            This controls conversion of subquery to semi-join and which semi-join strategies are allowed.
            {code}
            [NO_]SEMIJOIN([@query_block_name] [strategy [, strategy] ...])
            {code}
            where strategy is one of DUPSWEEDOUT, FIRSTMATCH, LOOSESCAN, MATERIALIZATION.
            This is a self-contained description of Optimizer Hints in MariaDB, whatever is already implemented in the current patch.

            h1. Optimizer hints in MariaDB

            General idea is to be compatible with MySQL.
            MySQL hint docs: https://dev.mysql.com/doc/refman/8.4/en/optimizer-hints.html

            h2. 1. Hint syntax
            Hints are placed after the main statement verb

            {code:sql}
            UPDATE /*+ hints */ table ...;
            DELETE /*+ hints */ FROM table... ;
            SELECT /*+ hints */ ...
            {code}

            or after the SELECT keyword in any subquery:
            {code:sql}
            SELECT * FROM t1 WHERE a IN (SELECT /*+ hints */ ...)
            {code}

            There can be one or more hints separated with space
            {code}
              hints: hint hint ...
            {code}

            Each individual hint is hint name and arguments. In case there are no arguments,
            the () brackets are still present:

            {code}
            hint: hint_name([arguments])
            {code}

            Incorrect hints produce warnings (a setting to make them errors is not implemented yet).

            Hints that are not ignored are kept in the query text (you can see them in SHOW PROCESSLIST, Slow Query Log, EXPLAIN EXTENDED)
            Hints that were incorrect and were ignored are removed from there.

            h2. 2. Hint hierarchy
            (todo: elaborate)
            Hints can be
            * global - applies to whole query
            * table-level - applies to a table
            * index-level - applies to an index in a table


            h3. 2.1 Table-level hints
            {code}
            hint_name([table_name [table_name [,...]] )
            {code}

            h3. 2.2 Index-level hints
            Index-level hints apply to index(es).
            Possible syntax variants:
            {code}
            hint_name(table_name [index_name [, index_name] ...])
            hint_name(table_name@query_block [index_name [, index_name] ...])
            hint_name(@query_block table_name [index_name [, index_name] ...])
            {code}
             
            h2. 3. Query block naming: QB_NAME hint

            QB_NAME hint is used to assign a name to the query block the hint is in. The Query Block is either a SELECT or a top-level construct of UPDATE or DELETE statement.

            {code:sql}
            SELECT /*+ QB_NAME(foo) */ select_list FROM ...
            {code}

            The name can then can be used
            * to refer to the query block
            * to refer to a table in the query block as {{table_name@query_block_name}}.

            Query block scope is the whole statement. It is invalid to use the same name for multiple query blocks.
            One can refer to the query block "down into subquery", "down into derived table", "up to the parent" and "to a right sibling in the UNION". One cannot refer "to a left sibling in a UNION" (It's the same in MySQL).


            Hints inside VIEWs are not supported, yet. One can neither use hints in VIEW definitions, nor control query plans inside non-merged VIEWs (This is because QB_NAME binding is done "early", before we know that some tables are VIEWs)

            h3. 3.1 select#n names.
            Besides the given name, any query block is given a name {{select#n}}. It is printed in EXPLAIN EXTENDED output:
            {code}
            Warnings:
            Note 1003 select /*+ NO_RANGE_OPTIMIZATION(`t3`@`select#1` `PRIMARY`) */ ...
            {code}

            *At the moment it is NOT yet possible to use it in the hint text*:
            {code:sql}
            SELECT /*+ BKA(tbl1@`select#1`) */ 1 FROM tbl1 ...;
            {code}

            h3. 3.2 QB_NAME in CTEs.
            What {{QB_NAME(@name)}} is used in a CTE which is then used in multiple places? Hints that control @name will control the first use of the CTE.
            (This "just happens" due to the way CTEs are implemented. We could address it when addressing VIEWs)

            h2. 4. Effect of optimizer hints

            Optimizer can be controlled by
            1. Server variables - optimizer_switch, join_cache_level, etc, etc
            2. Old-style hints
            3. New-style hints

            Old-style hints did not overlap with server variable settings.

            New-style hints are more specific than server variable settings, so they override the server variable settings.

            Should new-style hints override old-style hints? TODO.

            Hints are "narrowly interpreted" and "best effort" - if a hint dictates to do something, like
            {code:sql}
            SELECT /*+ MRR(t1 t1_index1) */ ... FROM t1 ...
            {code}
            that means:
            {quote}
            When considering a query plan that involves using t1_index1 in a way that one can use MRR, use MRR.
            {quote}
            if the query planning is such that use of {{t1_index1}} doesn't allow to use MRR, it won't be used.
            The optimizer may also consider using {{t1_index2}} and pick that over using {{t1_index1}}.
            In such cases the hint is effectively ignored and no warning is given.
            Examples: [^mdev35483-mrr-is-narrow.sql]

            h2. 5. List of hints

            h3. 5.1 NO_RANGE_OPTIMIZATION hint

            It's an index-level hint that disables range optimization for certain index(es):
            {code:sql}
            SELECT /*+ NO_RANGE_OPTIMIZATION(tbl index1 index2) */ * FROM tbl ...
            {code}

            h3. 5.2 NO_ICP hint
            It's an index-level hint that disables Index Condition Pushdown for the indexes. ICP+BKA is disabled as well.
            {code:sql}
            SELECT /*+ NO_ICP(tbl index1 index2) */ * FROM tbl ...
            {code}

            h3. 5.3 MRR and NO_MRR hints

            Index-level hint to force or disable use of MRR.

            {code:sql}
            SELECT /*+ MRR(tbl index1 index2) */ * FROM tbl ...
            SELECT /*+ NO_MRR(tbl index1 index2) */ * FROM tbl ...
            {code}
            This controls
            * MRR optimization for range access ( [^mdev35483-mrr-is-narrow.sql] )
            * BKA [^mdev35483-mrr-controls-bka-partially.sql]

            h3. 5.4 BKA() and NO_BKA() hints
            It's a query block or table-level hint.

            BKA() also enables MRR to make BKA possible. (This is different from session variables, where one needs to enable MRR separately).

            This also enables BKAH. TODO what was the reason for this?

            h3. 5.5 BNL() and NO_BNL() hints

            In MySQL this controls hash join, so in MariaDB it controls BNL-H.

            The implementation is "BNL() hint effectively increases join_cache_level up to 4 "
            TODO: this seems to fail a fairly trivial example: [^mdev35483-bnl-fails-why.txt] ?

            h3. 5.6 MAX_EXECUTION_TIME() hint
            A global-level hint to limit query execution time:
            Example:
            {code:sql}
            SELECT /*+ MAX_EXECUTION_TIME(milliseconds) */ ... ;
            {code}

            A query that doesn't finish in the time specified will be aborted with an error.

            Note: if the {{@@max_statement_time}} is set, the hint will be ignored and warning produced.
            TODO: This contradicts with the stated principle that "New-style hints are more specific than server variable settings, so they override the server variable settings".

            h2. 6. Subquery hints

            h3. 6.1. SUBQUERY hint
            Query block-level hint.
            {code}
            SUBQUERY([@query_block_name] MATERIALIZATION)
            SUBQUERY([@query_block_name] INTOEXISTS)
            {code}

            This controls non-semi-join subqueries. The parameter specifies which subquery to use. Use of this hint disables conversion of subquery into semi-join.

            h3. 6.2 SEMIJOIN, NO_SEMIJOIN
            Query block-level hint.
            This controls conversion of subquery to semi-join and which semi-join strategies are allowed.
            {code}
            [NO_]SEMIJOIN([@query_block_name] [strategy [, strategy] ...])
            {code}
            where strategy is one of DUPSWEEDOUT, FIRSTMATCH, LOOSESCAN, MATERIALIZATION.
            psergei Sergei Petrunia made changes -
            psergei Sergei Petrunia made changes -
            psergei Sergei Petrunia made changes -
            Assignee Sergei Petrunia [ psergey ]
            psergei Sergei Petrunia made changes -
            Fix Version/s 11.8 [ 29921 ]
            psergei Sergei Petrunia made changes -
            Component/s Optimizer [ 10200 ]
            psergei Sergei Petrunia made changes -
            Labels documentation
            psergei Sergei Petrunia made changes -
            Status Open [ 1 ] In Progress [ 3 ]
            serg Sergei Golubchik made changes -
            Fix Version/s N/A [ 14700 ]
            Fix Version/s 11.8 [ 29921 ]
            JIraAutomate JiraAutomate made changes -
            psergei Sergei Petrunia made changes -
            Description This is a self-contained description of Optimizer Hints in MariaDB, whatever is already implemented in the current patch.

            h1. Optimizer hints in MariaDB

            General idea is to be compatible with MySQL.
            MySQL hint docs: https://dev.mysql.com/doc/refman/8.4/en/optimizer-hints.html

            h2. 1. Hint syntax
            Hints are placed after the main statement verb

            {code:sql}
            UPDATE /*+ hints */ table ...;
            DELETE /*+ hints */ FROM table... ;
            SELECT /*+ hints */ ...
            {code}

            or after the SELECT keyword in any subquery:
            {code:sql}
            SELECT * FROM t1 WHERE a IN (SELECT /*+ hints */ ...)
            {code}

            There can be one or more hints separated with space
            {code}
              hints: hint hint ...
            {code}

            Each individual hint is hint name and arguments. In case there are no arguments,
            the () brackets are still present:

            {code}
            hint: hint_name([arguments])
            {code}

            Incorrect hints produce warnings (a setting to make them errors is not implemented yet).

            Hints that are not ignored are kept in the query text (you can see them in SHOW PROCESSLIST, Slow Query Log, EXPLAIN EXTENDED)
            Hints that were incorrect and were ignored are removed from there.

            h2. 2. Hint hierarchy
            (todo: elaborate)
            Hints can be
            * global - applies to whole query
            * table-level - applies to a table
            * index-level - applies to an index in a table


            h3. 2.1 Table-level hints
            {code}
            hint_name([table_name [table_name [,...]] )
            {code}

            h3. 2.2 Index-level hints
            Index-level hints apply to index(es).
            Possible syntax variants:
            {code}
            hint_name(table_name [index_name [, index_name] ...])
            hint_name(table_name@query_block [index_name [, index_name] ...])
            hint_name(@query_block table_name [index_name [, index_name] ...])
            {code}
             
            h2. 3. Query block naming: QB_NAME hint

            QB_NAME hint is used to assign a name to the query block the hint is in. The Query Block is either a SELECT or a top-level construct of UPDATE or DELETE statement.

            {code:sql}
            SELECT /*+ QB_NAME(foo) */ select_list FROM ...
            {code}

            The name can then can be used
            * to refer to the query block
            * to refer to a table in the query block as {{table_name@query_block_name}}.

            Query block scope is the whole statement. It is invalid to use the same name for multiple query blocks.
            One can refer to the query block "down into subquery", "down into derived table", "up to the parent" and "to a right sibling in the UNION". One cannot refer "to a left sibling in a UNION" (It's the same in MySQL).


            Hints inside VIEWs are not supported, yet. One can neither use hints in VIEW definitions, nor control query plans inside non-merged VIEWs (This is because QB_NAME binding is done "early", before we know that some tables are VIEWs)

            h3. 3.1 select#n names.
            Besides the given name, any query block is given a name {{select#n}}. It is printed in EXPLAIN EXTENDED output:
            {code}
            Warnings:
            Note 1003 select /*+ NO_RANGE_OPTIMIZATION(`t3`@`select#1` `PRIMARY`) */ ...
            {code}

            *At the moment it is NOT yet possible to use it in the hint text*:
            {code:sql}
            SELECT /*+ BKA(tbl1@`select#1`) */ 1 FROM tbl1 ...;
            {code}

            h3. 3.2 QB_NAME in CTEs.
            What {{QB_NAME(@name)}} is used in a CTE which is then used in multiple places? Hints that control @name will control the first use of the CTE.
            (This "just happens" due to the way CTEs are implemented. We could address it when addressing VIEWs)

            h2. 4. Effect of optimizer hints

            Optimizer can be controlled by
            1. Server variables - optimizer_switch, join_cache_level, etc, etc
            2. Old-style hints
            3. New-style hints

            Old-style hints did not overlap with server variable settings.

            New-style hints are more specific than server variable settings, so they override the server variable settings.

            Should new-style hints override old-style hints? TODO.

            Hints are "narrowly interpreted" and "best effort" - if a hint dictates to do something, like
            {code:sql}
            SELECT /*+ MRR(t1 t1_index1) */ ... FROM t1 ...
            {code}
            that means:
            {quote}
            When considering a query plan that involves using t1_index1 in a way that one can use MRR, use MRR.
            {quote}
            if the query planning is such that use of {{t1_index1}} doesn't allow to use MRR, it won't be used.
            The optimizer may also consider using {{t1_index2}} and pick that over using {{t1_index1}}.
            In such cases the hint is effectively ignored and no warning is given.
            Examples: [^mdev35483-mrr-is-narrow.sql]

            h2. 5. List of hints

            h3. 5.1 NO_RANGE_OPTIMIZATION hint

            It's an index-level hint that disables range optimization for certain index(es):
            {code:sql}
            SELECT /*+ NO_RANGE_OPTIMIZATION(tbl index1 index2) */ * FROM tbl ...
            {code}

            h3. 5.2 NO_ICP hint
            It's an index-level hint that disables Index Condition Pushdown for the indexes. ICP+BKA is disabled as well.
            {code:sql}
            SELECT /*+ NO_ICP(tbl index1 index2) */ * FROM tbl ...
            {code}

            h3. 5.3 MRR and NO_MRR hints

            Index-level hint to force or disable use of MRR.

            {code:sql}
            SELECT /*+ MRR(tbl index1 index2) */ * FROM tbl ...
            SELECT /*+ NO_MRR(tbl index1 index2) */ * FROM tbl ...
            {code}
            This controls
            * MRR optimization for range access ( [^mdev35483-mrr-is-narrow.sql] )
            * BKA [^mdev35483-mrr-controls-bka-partially.sql]

            h3. 5.4 BKA() and NO_BKA() hints
            It's a query block or table-level hint.

            BKA() also enables MRR to make BKA possible. (This is different from session variables, where one needs to enable MRR separately).

            This also enables BKAH. TODO what was the reason for this?

            h3. 5.5 BNL() and NO_BNL() hints

            In MySQL this controls hash join, so in MariaDB it controls BNL-H.

            The implementation is "BNL() hint effectively increases join_cache_level up to 4 "
            TODO: this seems to fail a fairly trivial example: [^mdev35483-bnl-fails-why.txt] ?

            h3. 5.6 MAX_EXECUTION_TIME() hint
            A global-level hint to limit query execution time:
            Example:
            {code:sql}
            SELECT /*+ MAX_EXECUTION_TIME(milliseconds) */ ... ;
            {code}

            A query that doesn't finish in the time specified will be aborted with an error.

            Note: if the {{@@max_statement_time}} is set, the hint will be ignored and warning produced.
            TODO: This contradicts with the stated principle that "New-style hints are more specific than server variable settings, so they override the server variable settings".

            h2. 6. Subquery hints

            h3. 6.1. SUBQUERY hint
            Query block-level hint.
            {code}
            SUBQUERY([@query_block_name] MATERIALIZATION)
            SUBQUERY([@query_block_name] INTOEXISTS)
            {code}

            This controls non-semi-join subqueries. The parameter specifies which subquery to use. Use of this hint disables conversion of subquery into semi-join.

            h3. 6.2 SEMIJOIN, NO_SEMIJOIN
            Query block-level hint.
            This controls conversion of subquery to semi-join and which semi-join strategies are allowed.
            {code}
            [NO_]SEMIJOIN([@query_block_name] [strategy [, strategy] ...])
            {code}
            where strategy is one of DUPSWEEDOUT, FIRSTMATCH, LOOSESCAN, MATERIALIZATION.
            This is a self-contained description of Optimizer Hints in MariaDB, whatever is already implemented in the current patch.

            h1. Optimizer hints in MariaDB

            General idea is to be compatible with MySQL.
            MySQL hint docs: https://dev.mysql.com/doc/refman/8.4/en/optimizer-hints.html

            h2. 1. Hint syntax
            Hints are placed after the main statement verb

            {code:sql}
            UPDATE /*+ hints */ table ...;
            DELETE /*+ hints */ FROM table... ;
            SELECT /*+ hints */ ...
            {code}

            or after the SELECT keyword in any subquery:
            {code:sql}
            SELECT * FROM t1 WHERE a IN (SELECT /*+ hints */ ...)
            {code}

            There can be one or more hints separated with space
            {code}
              hints: hint hint ...
            {code}

            Each individual hint is hint name and arguments. In case there are no arguments,
            the () brackets are still present:

            {code}
            hint: hint_name([arguments])
            {code}

            Incorrect hints produce warnings (a setting to make them errors is not implemented yet).

            Hints that are not ignored are kept in the query text (you can see them in SHOW PROCESSLIST, Slow Query Log, EXPLAIN EXTENDED)
            Hints that were incorrect and were ignored are removed from there.

            h2. 2. Hint hierarchy
            (todo: elaborate)
            Hints can be
            * global - applies to whole query
            * table-level - applies to a table
            * index-level - applies to an index in a table


            h3. 2.1 Table-level hints
            {code}
            hint_name([table_name [table_name [,...]] )
            {code}

            h3. 2.2 Index-level hints
            Index-level hints apply to index(es).
            Possible syntax variants:
            {code}
            hint_name(table_name [index_name [, index_name] ...])
            hint_name(table_name@query_block [index_name [, index_name] ...])
            hint_name(@query_block table_name [index_name [, index_name] ...])
            {code}
             
            h2. 3. Query block naming: QB_NAME hint

            QB_NAME hint is used to assign a name to the query block the hint is in. The Query Block is either a SELECT or a top-level construct of UPDATE or DELETE statement.

            {code:sql}
            SELECT /*+ QB_NAME(foo) */ select_list FROM ...
            {code}

            The name can then can be used
            * to refer to the query block
            * to refer to a table in the query block as {{table_name@query_block_name}}.

            Query block scope is the whole statement. It is invalid to use the same name for multiple query blocks.
            One can refer to the query block "down into subquery", "down into derived table", "up to the parent" and "to a right sibling in the UNION". One cannot refer "to a left sibling in a UNION" (It's the same in MySQL).


            Hints inside VIEWs are not supported, yet. One can neither use hints in VIEW definitions, nor control query plans inside non-merged VIEWs (This is because QB_NAME binding is done "early", before we know that some tables are VIEWs)

            h3. 3.1 select#n names.
            Besides the given name, any query block is given a name {{select#n}}. It is printed in EXPLAIN EXTENDED output:
            {code}
            Warnings:
            Note 1003 select /*+ NO_RANGE_OPTIMIZATION(`t3`@`select#1` `PRIMARY`) */ ...
            {code}

            *At the moment it is NOT yet possible to use it in the hint text*:
            {code:sql}
            SELECT /*+ BKA(tbl1@`select#1`) */ 1 FROM tbl1 ...;
            {code}

            h3. 3.2 QB_NAME in CTEs.
            What {{QB_NAME(@name)}} is used in a CTE which is then used in multiple places? Hints that control @name will control the first use of the CTE.
            (This "just happens" due to the way CTEs are implemented. We could address it when addressing VIEWs)

            h2. 4. Effect of optimizer hints

            Optimizer can be controlled by
            1. Server variables - optimizer_switch, join_cache_level, etc, etc
            2. Old-style hints
            3. New-style hints

            Old-style hints did not overlap with server variable settings.

            New-style hints are more specific than server variable settings, so they override the server variable settings.

            Should new-style hints override old-style hints? TODO.

            Hints are "narrowly interpreted" and "best effort" - if a hint dictates to do something, like
            {code:sql}
            SELECT /*+ MRR(t1 t1_index1) */ ... FROM t1 ...
            {code}
            that means:
            {quote}
            When considering a query plan that involves using t1_index1 in a way that one can use MRR, use MRR.
            {quote}
            if the query planning is such that use of {{t1_index1}} doesn't allow to use MRR, it won't be used.
            The optimizer may also consider using {{t1_index2}} and pick that over using {{t1_index1}}.
            In such cases the hint is effectively ignored and no warning is given.
            Examples: [^mdev35483-mrr-is-narrow.sql]

            h2. 5. List of hints

            h3. 5.1 NO_RANGE_OPTIMIZATION hint

            It's an index-level hint that disables range optimization for certain index(es):
            {code:sql}
            SELECT /*+ NO_RANGE_OPTIMIZATION(tbl index1 index2) */ * FROM tbl ...
            {code}

            h3. 5.2 NO_ICP hint
            It's an index-level hint that disables Index Condition Pushdown for the indexes. ICP+BKA is disabled as well.
            {code:sql}
            SELECT /*+ NO_ICP(tbl index1 index2) */ * FROM tbl ...
            {code}

            h3. 5.3 MRR and NO_MRR hints

            Index-level hint to force or disable use of MRR.

            {code:sql}
            SELECT /*+ MRR(tbl index1 index2) */ * FROM tbl ...
            SELECT /*+ NO_MRR(tbl index1 index2) */ * FROM tbl ...
            {code}
            This controls
            * MRR optimization for range access ( [^mdev35483-mrr-is-narrow.sql] )
            * BKA [^mdev35483-mrr-controls-bka-partially.sql]

            h3. 5.4 BKA() and NO_BKA() hints
            It's a query block or table-level hint.

            BKA() also enables MRR to make BKA possible. (This is different from session variables, where one needs to enable MRR separately).

            This also enables BKAH. TODO what was the reason for this?

            h3. 5.5 BNL() and NO_BNL() hints

            In MySQL this controls hash join, so in MariaDB it controls BNL-H.

            The implementation is "BNL() hint effectively increases join_cache_level up to 4 " .. for the table(s) it applies to)
            (FIXED: this seems to fail a fairly trivial example: [^mdev35483-bnl-fails-why.txt] )

            h3. 5.6 MAX_EXECUTION_TIME() hint
            A global-level hint to limit query execution time:
            Example:
            {code:sql}
            SELECT /*+ MAX_EXECUTION_TIME(milliseconds) */ ... ;
            {code}

            A query that doesn't finish in the time specified will be aborted with an error.

            Note: if the {{@@max_statement_time}} is set, the hint will be ignored and warning produced.
            TODO: This contradicts with the stated principle that "New-style hints are more specific than server variable settings, so they override the server variable settings".

            h2. 6. Subquery hints

            h3. 6.1. SUBQUERY hint
            Query block-level hint.
            {code}
            SUBQUERY([@query_block_name] MATERIALIZATION)
            SUBQUERY([@query_block_name] INTOEXISTS)
            {code}

            This controls non-semi-join subqueries. The parameter specifies which subquery to use. Use of this hint disables conversion of subquery into semi-join.

            h3. 6.2 SEMIJOIN, NO_SEMIJOIN
            Query block-level hint.
            This controls conversion of subquery to semi-join and which semi-join strategies are allowed.
            {code}
            [NO_]SEMIJOIN([@query_block_name] [strategy [, strategy] ...])
            {code}
            where strategy is one of DUPSWEEDOUT, FIRSTMATCH, LOOSESCAN, MATERIALIZATION.
            psergei Sergei Petrunia made changes -
            psergei Sergei Petrunia made changes -
            greenman Ian Gilfillan added a comment - Documented so far on https://mariadb.com/kb/en/optimizer-hints
            Roel Roel Van de Paar made changes -
            julien.fritsch Julien Fritsch made changes -
            julien.fritsch Julien Fritsch made changes -
            JIraAutomate JiraAutomate made changes -
            Status In Progress [ 3 ] Stalled [ 10000 ]

            People

              psergei Sergei Petrunia
              psergei Sergei Petrunia
              Votes:
              0 Vote for this issue
              Watchers:
              4 Start watching this issue

              Dates

                Created:
                Updated:

                Git Integration

                  Error rendering 'com.xiplink.jira.git.jira_git_plugin:git-issue-webpanel'. Please contact your Jira administrators.