[MDEV-14563] Wrong query plan for query with no PK Created: 2017-12-04  Updated: 2017-12-07  Resolved: 2017-12-06

Status: Closed
Project: MariaDB Server
Component/s: Storage Engine - RocksDB
Affects Version/s: 10.2
Fix Version/s: 10.2.12

Type: Bug Priority: Major
Reporter: Sergei Petrunia Assignee: Sergei Petrunia
Resolution: Fixed Votes: 0
Labels: None

Issue Links:
PartOf
includes MDEV-14607 storage_engine-rocksdb.type_bit_index... Closed
is part of MDEV-14433 RocksDB may show empty or incorrect o... Closed

 Description   

Found this while working on MDEV-14433:
Found an interesting mismatch between query plans that depends on the index number:

Upstream, MySQL 5.6

CREATE TABLE t3(
  pk int primary key,
  a varchar(10) NOT NULL,   
  e int(11) DEFAULT 0,   
  KEY (a) 
) ENGINE=ROCKSDB DEFAULT CHARSET=utf8;

insert into t3 values (1,1,1),(2,2,2);
explain select a from t3 where a <'zzz';
+----+-------------+-------+-------+---------------+------+---------+------+------+-------------+
| id | select_type | table | type  | possible_keys | key  | key_len | ref  | rows | Extra       |
+----+-------------+-------+-------+---------------+------+---------+------+------+-------------+
|  1 | SIMPLE      | t3    | range | a             | a    | 32      | NULL |    2 | Using where |
+----+-------------+-------+-------+---------------+------+---------+------+------+-------------+

CREATE TABLE t4(
  pk int,
  a varchar(10) NOT NULL,
  e int(11) DEFAULT 0,   
  KEY (a)
) ENGINE=ROCKSDB DEFAULT CHARSET=utf8;
insert into t4 values (1,1,1),(2,2,2);

explain select a from t4 where a <'zzz';
+----+-------------+-------+-------+---------------+------+---------+------+------+-------------+
| id | select_type | table | type  | possible_keys | key  | key_len | ref  | rows | Extra       |
+----+-------------+-------+-------+---------------+------+---------+------+------+-------------+
|  1 | SIMPLE      | t4    | range | a             | a    | 32      | NULL |    1 | Using where |
+----+-------------+-------+-------+---------------+------+---------+------+------+-------------+

MariaDB:

CREATE TABLE t3(
  pk int primary key,
  a varchar(10) NOT NULL,   
  e int(11) DEFAULT 0,   
  KEY (a) 
) ENGINE=ROCKSDB DEFAULT CHARSET=utf8;
insert into t3 values (1,1,1),(2,2,2);

explain select a from t3 where a <'zzz';
+------+-------------+-------+-------+---------------+------+---------+------+------+-------------+
| id   | select_type | table | type  | possible_keys | key  | key_len | ref  | rows | Extra       |
+------+-------------+-------+-------+---------------+------+---------+------+------+-------------+
|    1 | SIMPLE      | t3    | range | a             | a    | 32      | NULL |    1 | Using where |
+------+-------------+-------+-------+---------------+------+---------+------+------+-------------+

CREATE TABLE t4(
  pk int,
  a varchar(10) NOT NULL,
  e int(11) DEFAULT 0,   
  KEY (a)
) ENGINE=ROCKSDB DEFAULT CHARSET=utf8;
insert into t4 values (1,1,1),(2,2,2);

explain select a from t4 where a <'zzz';
+------+-------------+-------+-------+---------------+------+---------+------+------+--------------------------+
| id   | select_type | table | type  | possible_keys | key  | key_len | ref  | rows | Extra                    |
+------+-------------+-------+-------+---------------+------+---------+------+------+--------------------------+
|    1 | SIMPLE      | t4    | index | a             | a    | 32      | NULL |    0 | Using where; Using index |
+------+-------------+-------+-------+---------------+------+---------+------+------+--------------------------+



 Comments   
Comment by Sergei Petrunia [ 2017-12-04 ]

Debugging

CREATE TABLE t4(
  pk int,
  a varchar(10) NOT NULL,
  e int(11) DEFAULT 0,   
  KEY (a)
) ENGINE=ROCKSDB DEFAULT CHARSET=utf8;

in TABLE_SHARE::init_from_binary_frm_image, stepping into the

       if (handler_file->index_flags(key, i, 0) & HA_KEYREAD_ONLY)

call:

  myrocks::ha_rocksdb::index_flags (this=0x7fff6c01b7e8, inx=0, part=0, all_parts=false)

There, we have

(gdb) p table
  $33 = (TABLE *) 0x0
(gdb) p table_share
  $34 = (TABLE_SHARE *) 0x7ffff41bd890
(gdb) p table_share->primary_key
  $35 = 0

That is,

  • we are called for inx=0, this KEY(a) which is a secondary key
  • there is a TABLE_SHARE object which has primary_key=0
  • so the code assumes it is called for the PK:

  if (inx == table_share->primary_key) {

and returns an incorrect value.

Comment by Sergei Petrunia [ 2017-12-04 ]

table_share->primary_key is set in TABLE_SHARE::init_from_binary_frm_image but
the mentioned index_flags() call is made before that.

There is a local variable

    uint primary_key= my_strcasecmp(system_charset_info, share->keynames.type_names[0],
                                    primary_key_name) ? MAX_KEY : 0;

which is set before the index_flags() call.

Condition to set share->primary_key:

    if (primary_key < MAX_KEY &&
	(share->keys_in_use.is_set(primary_key)))
    {
      share->primary_key= primary_key;

Generated at Thu Feb 08 08:14:33 UTC 2024 using Jira 8.20.16#820016-sha1:9d11dbea5f4be3d4cc21f03a88dd11d8c8687422.