Skip to content
  • Chandan Kunal's avatar
    6188a828
    Bug #25207522: INCORRECT ORDER-BY BEHAVIOR ON A PARTITIONED TABLE WITH A COMPOSITE PREFIX INDEX · 6188a828
    Chandan Kunal authored
    Description:
    The SELECT query with order-by clause gives unordered results if following
    conditions are met:
    1. It should be a partitioned table with a composite prefix index.
    2. WHERE clause should have an equality condition on the prefixed column.
    3. Prefix column in index should be leading key.
    4. Column used in ORDER-BY clause should be trailing key in the index.
    5. Index should be chosen for handling for ORDER-BY clause.
    Ex: SELECT * FROM table WHERE prefixed_index_column = "constant" and order by
    "next_column_after_prefixed_index_column"
    
    ANALYSIS:
    While checking if an index could be used for sorting, optimizer picks an index
    if all the columns in the index before the ordering columns are constants for
    the execution (have equality conditions in the where clause). However this is
    not right when the columns are prefixed and the table is partitioned.
    
    To understand it better let's take following DDL:
    
    CREATE TABLE table( col1 int NOT NULL,
            col2 varchar(2) DEFAULT NULL,
            KEY col2_idx (data(1),id)
            ) DEFAULT CHARSET=utf8
            /*!50100 PARTITION BY RANGE (id)
            (PARTITION p10 VALUES LESS THAN (10) ,
             PARTITION p20 VALUES LESS THAN (20) ) */;
    
    Lets assume after inserting in table we have(records is in sorted order of
    partition column)
    partition p10 contains  (4, 'ab'), (5, 'ab'), (5, 'ac'), (6, 'ab') and
    partition p20 contains (14, 'ab'), (15, 'ab'), (15, 'aa'), (16, 'ab')
    
    Now let's take following query for execution
    SELECT col1 FROM tutf8 WHERE col2 = 'ab' ORDER BY col1 ASC;
    
    In this query we have ORDER BY clause on 'col2' but the index is on 'col2' and
    'col1'. So it is sorted accordingly. The first row to be out from both the
    partitions is "4", followed by "5" as they are lesser than "14". After this it
    will compare between ('ac', 5) and ('ab', 14). It will return 14 as
    'ab' < 'ac'. The active partition now becomes p20. This will give out 15, 16
    as 'ab', 'aa' are lesser than 'ac'. This will leave us with the final value
    which is 6.
    
    Hence final result of the query will be
    +----+
    |col1|
    +----+
    |  4 |
    |  5 |
    | 14 |
    | 15 |
    | 16 |
    |  6 |
    +----+
    
    SOLUTION:
    test_if_order_by_key() calls new function is_prefix_index to determine whether
    prefix index is being used for sorting. If it is true, optimizer does not pick
    this index for ordering.
    
    Change-Id: I2715867ca3db537ba47ed82bf44a3f4e65949465
    6188a828
    Bug #25207522: INCORRECT ORDER-BY BEHAVIOR ON A PARTITIONED TABLE WITH A COMPOSITE PREFIX INDEX
    Chandan Kunal authored
    Description:
    The SELECT query with order-by clause gives unordered results if following
    conditions are met:
    1. It should be a partitioned table with a composite prefix index.
    2. WHERE clause should have an equality condition on the prefixed column.
    3. Prefix column in index should be leading key.
    4. Column used in ORDER-BY clause should be trailing key in the index.
    5. Index should be chosen for handling for ORDER-BY clause.
    Ex: SELECT * FROM table WHERE prefixed_index_column = "constant" and order by
    "next_column_after_prefixed_index_column"
    
    ANALYSIS:
    While checking if an index could be used for sorting, optimizer picks an index
    if all the columns in the index before the ordering columns are constants for
    the execution (have equality conditions in the where clause). However this is
    not right when the columns are prefixed and the table is partitioned.
    
    To understand it better let's take following DDL:
    
    CREATE TABLE table( col1 int NOT NULL,
            col2 varchar(2) DEFAULT NULL,
            KEY col2_idx (data(1),id)
            ) DEFAULT CHARSET=utf8
            /*!50100 PARTITION BY RANGE (id)
            (PARTITION p10 VALUES LESS THAN (10) ,
             PARTITION p20 VALUES LESS THAN (20) ) */;
    
    Lets assume after inserting in table we have(records is in sorted order of
    partition column)
    partition p10 contains  (4, 'ab'), (5, 'ab'), (5, 'ac'), (6, 'ab') and
    partition p20 contains (14, 'ab'), (15, 'ab'), (15, 'aa'), (16, 'ab')
    
    Now let's take following query for execution
    SELECT col1 FROM tutf8 WHERE col2 = 'ab' ORDER BY col1 ASC;
    
    In this query we have ORDER BY clause on 'col2' but the index is on 'col2' and
    'col1'. So it is sorted accordingly. The first row to be out from both the
    partitions is "4", followed by "5" as they are lesser than "14". After this it
    will compare between ('ac', 5) and ('ab', 14). It will return 14 as
    'ab' < 'ac'. The active partition now becomes p20. This will give out 15, 16
    as 'ab', 'aa' are lesser than 'ac'. This will leave us with the final value
    which is 6.
    
    Hence final result of the query will be
    +----+
    |col1|
    +----+
    |  4 |
    |  5 |
    | 14 |
    | 15 |
    | 16 |
    |  6 |
    +----+
    
    SOLUTION:
    test_if_order_by_key() calls new function is_prefix_index to determine whether
    prefix index is being used for sorting. If it is true, optimizer does not pick
    this index for ordering.
    
    Change-Id: I2715867ca3db537ba47ed82bf44a3f4e65949465
Loading