pingcap/tidb

Allow filter condition push down to IndexScan for prefix index.

Open

#21 145 ouverte le 19 nov. 2020

Voir sur GitHub
 (4 commentaires) (0 réactions) (1 assigné)Go (6 186 forks)batch import
help wantedsig/plannertype/feature-request

Métriques du dépôt

Stars
 (40 090 stars)
Métriques de merge PR
 (Merge moyen 14j 4h) (346 PRs mergées en 30 j)

Description

Feature Request

Allow filter condition push down to IndexScan for prefix index.

mysql> create table t (a text, b text, index a_b (a(255), b(255)));
Query OK, 0 rows affected (0.01 sec)

mysql> explain select * from t where a between 'a' and 'b' and b = 'b';
+-------------------------------+---------+-----------+--------------------------+---------------------------------------------------------+
| id                            | estRows | task      | access object            | operator info                                           |
+-------------------------------+---------+-----------+--------------------------+---------------------------------------------------------+
| IndexLookUp_11                | 0.25    | root      |                          |                                                         |
| ├─IndexRangeScan_8(Build)     | 250.00  | cop[tikv] | table:t, index:a_b(a, b) | range:["a","b"], keep order:false, stats:pseudo         |
| └─Selection_10(Probe)         | 0.25    | cop[tikv] |                          | eq(test.t.b, "b"), ge(test.t.a, "a"), le(test.t.a, "b") |
|   └─TableRowIDScan_9          | 250.00  | cop[tikv] | table:t                  | keep order:false, stats:pseudo                          |
+-------------------------------+---------+-----------+--------------------------+---------------------------------------------------------+

The condition b = 'b' should be able to pushed down to IndexScan phase to reduce the lookup table cost.

We only need to make sure the equal condition value of b is less than the index column length 255.

The ideal plan should be

mysql> explain select * from t where a between 'a' and 'b' and b = 'b';
+--------------------------+---------+-----------+--------------------------+-------------------------------------------------+
| id                       | estRows | task      | access object            | operator info                                   |
+--------------------------+---------+-----------+--------------------------+-------------------------------------------------+
| IndexReader_7            | 0.25    | root      |                          | index:Selection_6                               |
| └─Selection_6            | 0.25    | cop[tikv] |                          | eq(test.t.b, "b")                               |
|   └─IndexRangeScan_5     | 250.00  | cop[tikv] | table:t, index:a_b(a, b) | range:["a","b"], keep order:false, stats:pseudo |
+--------------------------+---------+-----------+--------------------------+-------------------------------------------------+

Describe alternatives you've considered:

Teachability, Documentation, Adoption, Migration Strategy:

Guide contributeur