Uploaded image for project: 'MariaDB Server'
  1. MariaDB Server
  2. MDEV-34413

Index Condition Pushdown for reverse-ordered scans

    XMLWordPrintable

Details

    Description

      Currently, Index Condition Pushdown (and Rowid Filtering) cannot be used with reverse-ordered index scans.

      Search for IndexConditionPushdownAndReverseScans, RowidFilteringAndReverseScans in sql/sql_select.cc for detailed explanation why.
      See prepare_for_reverse_ordered_access() where we disable these features when switching to reverse scans.

      This task is about enabling ICP (and maybe Rowid Filtering) to work with reverse-ordered scans.

      re MySQL 8

      MySQL 8 actually supports ICP + Reverse scans, see handler::set_end_range call. Maybe we should adopt this, or maybe something something similar.

      Some more details about how they support it: Support added by this patch:
      https://github.com/mysql/mysql-server/commit/da1d92fd46071cd86de61058b6ea39fd9affcd87

      create table ten(a int);
      insert into ten values (0),(1),(2),(3),(4),(5),(6),(7),(8),(9);
      create table one_k(a int);
      insert into one_k select A.a + B.a* 10 + C.a * 100 from ten A, ten B, ten C;
      create table t10 (a int, b int, c int, key(a,b));
      insert into t10 select a,a,a from one_k;
       
      explain select * from t10 force index(a) where a between 10 and 20 and b+1 <3333 order by a desc, b desc;
      

      +----+-------------+-------+------------+-------+---------------+------+---------+------+------+----------+--------------------------------------------+
      | id | select_type | table | partitions | type  | possible_keys | key  | key_len | ref  | rows | filtered | Extra                                      |
      +----+-------------+-------+------------+-------+---------------+------+---------+------+------+----------+--------------------------------------------+
      |  1 | SIMPLE      | t10   | NULL       | range | a             | a    | 5       | NULL |    1 |   100.00 | Using index condition; Backward index scan |
      +----+-------------+-------+------------+-------+---------------+------+---------+------+------+----------+--------------------------------------------+
      

      As pointed out by igor, there is some interesting limitation: reverse index scan+ICP doesn't work with ref access:

      mysql> explain select * from t10 force index(a) where a=10 and b+1 <3333 order by a desc, b desc;
      +----+-------------+-------+------------+------+---------------+------+---------+-------+------+----------+----------------------------------+
      | id | select_type | table | partitions | type | possible_keys | key  | key_len | ref   | rows | filtered | Extra                            |
      +----+-------------+-------+------------+------+---------------+------+---------+-------+------+----------+----------------------------------+
      |  1 | SIMPLE      | t10   | NULL       | ref  | a             | a    | 5       | const |    1 |   100.00 | Using where; Backward index scan |
      +----+-------------+-------+------------+------+---------------+------+---------+-------+------+----------+----------------------------------+
      

      mysql> explain select * from t10 force index(a) where a=10 and b+1 <3333 order by a asc, b asc;
      +----+-------------+-------+------------+------+---------------+------+---------+-------+------+----------+-----------------------+
      | id | select_type | table | partitions | type | possible_keys | key  | key_len | ref   | rows | filtered | Extra                 |
      +----+-------------+-------+------------+------+---------------+------+---------+-------+------+----------+-----------------------+
      |  1 | SIMPLE      | t10   | NULL       | ref  | a             | a    | 5       | const |    1 |   100.00 | Using index condition |
      +----+-------------+-------+------------+------+---------------+------+---------+-------+------+----------+-----------------------+
      1 row in set, 1 warning (0.01 sec)
      

      code-wise, it is here:

      void QEP_TAB::push_index_cond(const JOIN_TAB *join_tab, uint keyno,
                                    Opt_trace_object *trace_obj) {
        JOIN *const join_ = join();
        DBUG_TRACE;
       
        ASSERT_BEST_REF_IN_JOIN_ORDER(join_);
        assert(join_tab == join_->best_ref[idx()]);
       
        if (join_tab->reversed_access)  // @todo: historical limitation, lift it!
          return;
      

      Attachments

        Issue Links

          Activity

            People

              Unassigned Unassigned
              psergei Sergei Petrunia
              Votes:
              0 Vote for this issue
              Watchers:
              3 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.