博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
MySQL · myrocks · collation 限制
阅读量:7043 次
发布时间:2019-06-28

本文共 7267 字,大约阅读时间需要 24 分钟。

背景

MyRocks中的数据是按索引列以memcmp方式进行排序的。对于一些数字类型,需要进行转化才能直接通过memcmp进行比较, 例如有符号数在计算机中是用补码表示的,那么如果负数和正数直接按字节比较,结果负数会比正数大,实际存储时会将符号会反转存储,读取时再转化回来。对于字符类型,处理更加复杂,涉及到字符集的转换。 记录格式可以参考,

MyRocks索引字段如果包含字符类型,默认只支持binary collation,binary、latin1_bin、 utf8_bin其中的一种

## Errorcreate table t1(c1 int primary key, c2 varchar(10) unique) engine =rocksdb character set gbk;ERROR 3046 (HY000): Unsupported collation on string indexed column test.t1.c2 Use binary collation (binary, latin1_bin, utf8_bin).## Errorcreate table t1(c1 int primary key, c2 varchar(10) unique) engine =rocksdb character set utf8 collate utf8_general_ci;ERROR 3046 (HY000): Unsupported collation on string indexed column test.t1.c2 Use binary collation (binary, latin1_bin, utf8_bin).## OKcreate table t1(c1 int primary key, c2 varchar(10) unique) engine =rocksdb character set utf8 collate utf8_bin;Query OK, 0 rows affected (0.00 sec)

通过设置rocksdb_strict_collation_check参数为OFF可以跳出binary collation的限制

set global rocksdb_strict_collation_check=OFF;## OKcreate table t1(c1 int primary key, c2 varchar(10) unique) engine =rocksdb character set gbk;Query OK, 0 rows affected (0.01 sec)

问题

MyRocks和InnoDB一样支持covering index. MyRocks在使用二级索引查询的时候,应尽量使用, 因为MyRocks回表通过主键随机查询数据的开销比较大。

例如以下场景,idx1作为convering index被使用

create table t1(c1 int primary key, c2 varchar(10) unique) engine =rocksdb character set utf8 collate utf8_bin;insert into t1 values(1,'ab');insert into t1 values(2,'cd');## covering indexexplain select c2 from t1 where c2='ab';+----+-------------+-------+-------+---------------+------+---------+-------+------+-------------+| id | select_type | table | type  | possible_keys | key  | key_len | ref   | rows | Extra       |+----+-------------+-------+-------+---------------+------+---------+-------+------+-------------+|  1 | SIMPLE      | t1    | const | c2            | c2   | 33      | const |    1 | Using index |+----+-------------+-------+-------+---------------+------+---------+-------+------+-------------+

然而设置set global rocksdb_strict_collation_check=OFF;在某些情况下会导致我们无法使用covering index.

set global rocksdb_strict_collation_check=ON;## Errorcreate table t1(c1 int primary key, c2 int, c3 varchar(10), key idx1(c2,c3)) engine =rocksdb  character set utf8 collate utf8_general_ci;ERROR 3046 (HY000): Unsupported collation on string indexed column test.t1.c3 Use binary collation (binary, latin1_bin, utf8_bin).set global rocksdb_strict_collation_check=OFF;## OKcreate table t1(c1 int primary key, c2 varchar(10) unique) engine =rocksdb character set utf8 collate utf8_general_ci;Query OK, 0 rows affected (0.00 sec)insert into t1 values(1,1,'ab');insert into t1 values(2,2,'cd');insert into t1 values(1,'ab');insert into t1 values(2,'cd');## non-covering indexexplain select c2 from t1 where c2='ab';+----+-------------+-------+-------+---------------+------+---------+-------+------+-------+| id | select_type | table | type  | possible_keys | key  | key_len | ref   | rows | Extra |+----+-------------+-------+-------+---------------+------+---------+-------+------+-------+|  1 | SIMPLE      | t1    | const | c2            | c2   | 33      | const |    1 | NULL  |+----+-------------+-------+-------+---------------+------+---------+-------+------+-------+1 row in set (0.00 sec)

原因

MyRocks二级索引由于collation的关系导致查询没有走covering index. MyRocks中索引列需要转化为memcomparable的形式,转化分为以下三种情况

  • 1) 直接转换,不需要存储额外信息

    例如 binary、latin1_bin、 utf8_bin三种collation可以直接转换

    这种情况二级索引列数据可以完整的从二级索引中取到,不影响covering index使用

  • 2) 间接转换,需在value中增加unpack_info

    例如latin1_general_ci,latin2_general_ci, ascii_general_ci,greek_general_ci等collation,具体可以参考函数rdb_is_collation_supported

    这种情况二级索引列数据可以从key和unpack_info中解析取到,也不影响covering index使用

create table t1(c1 int primary key, c2 varchar(10) unique) engine =rocksdb character set latin1 collate latin1_general_ci;insert into t1 values(1,'ab');insert into t1 values(2,'cd');## covering indexexplain select c2 from t1 where c2='ab';+----+-------------+-------+-------+---------------+------+---------+-------+------+-------------+| id | select_type | table | type  | possible_keys | key  | key_len | ref   | rows | Extra       |+----+-------------+-------+-------+---------------+------+---------+-------+------+-------------+|  1 | SIMPLE      | t1    | const | c2            | c2   | 13      | const |    1 | Using index |+----+-------------+-------+-------+---------------+------+---------+-------+------+-------------+1 row in set (0.00 sec)
  • 3) 无法转换

    除1,2两种情况外的collation, 例如utf8_general_ci

    此时从二级索引中获取不到key的完整信息,需要从主键索引上获取,因此不能走covering index

create table t1(c1 int primary key, c2 varchar(10) unique) engine =rocksdb character set utf8 collate utf8_general_ci; insert into t1 values(1,'ab'); insert into t1 values(2,'cd');## non-covering indexexplain select c2 from t1 where c2='ab';+----+-------------+-------+-------+---------------+------+---------+-------+------+-------+| id | select_type | table | type  | possible_keys | key  | key_len | ref   | rows | Extra |+----+-------------+-------+-------+---------------+------+---------+-------+------+-------+|  1 | SIMPLE      | t1    | const | c2            | c2   | 33      | const |    1 | NULL  |+----+-------------+-------+-------+---------------+------+---------+-------+------+-------+1 row in set (0.00 sec)

此时的数据获取路径如下

0  myrocks::ha_rocksdb::convert_record_from_storage_format 1  myrocks::ha_rocksdb::get_row_by_rowid2  myrocks::ha_rocksdb::get_row_by_rowid3  myrocks::ha_rocksdb::read_row_from_secondary_key 4  myrocks::ha_rocksdb::index_read_map_impl5  myrocks::ha_rocksdb::index_read_map6  handler::index_read_idx_map7  handler::ha_index_read_idx_map8  join_read_const9  join_read_const_table10 make_join_statistics11 JOIN::optimize12 mysql_execute_select13 mysql_select14 handle_select15 execute_sqlcom_select16 mysql_execute_command

转换的具体实现可以参考函数Rdb_field_packing::setup

MyRocks从索引读取数据时,不能仅通过keyread_only来判断是否可以使用covering index, 还需要判断是否存在collation列数据转换的问题,如果访问的列无法转换就不能使用covering index.

MyRocks会在value中存储covered_bitmap,表示索引列是否可以转换, read_row_from_secondary_key/secondary_index_read读取时会根据covered_bitmap来决定是否能使用covering index

bool Rdb_key_def::covers_lookup(TABLE *const table,                                const rocksdb::Slice *const unpack_info,                                const MY_BITMAP *const lookup_bitmap) const {  DBUG_ASSERT(lookup_bitmap != nullptr);  if (!use_covered_bitmap_format() || lookup_bitmap->bitmap == nullptr) {    return false;  }  Rdb_string_reader unp_reader = Rdb_string_reader::read_or_empty(unpack_info);  // Check if this unpack_info has a covered_bitmap  const char *unpack_header = unp_reader.get_current_ptr();  const bool has_covered_unpack_info =      unp_reader.remaining_bytes() &&      unpack_header[0] == RDB_UNPACK_COVERED_DATA_TAG;  if (!has_covered_unpack_info ||      !unp_reader.read(RDB_UNPACK_COVERED_HEADER_SIZE)) {    return false;  }  MY_BITMAP covered_bitmap;  my_bitmap_map covered_bits;  bitmap_init(&covered_bitmap, &covered_bits, MAX_REF_PARTS, false);  covered_bits = rdb_netbuf_to_uint16((const uchar *)unpack_header +                                      sizeof(RDB_UNPACK_COVERED_DATA_TAG) +                                      RDB_UNPACK_COVERED_DATA_LEN_SIZE);  return bitmap_is_subset(lookup_bitmap, &covered_bitmap);}

总结

MyRocks在字符collation上的限制需要引起我们关注,使用不当会影响查询效率。

转载地址:http://bhhal.baihongyu.com/

你可能感兴趣的文章
平安科技移动开发二队技术周报(第十五期)
查看>>
设计模式-行为型模式,观察者模式(13)
查看>>
Win8 Metro(C#)数字图像处理--2.41彩色图像密度分割算法
查看>>
Intellij IDEA查看所有断点
查看>>
Top K算法
查看>>
CentOs6.7 python2.6升级到2.7.11
查看>>
JavaBridge
查看>>
.NET MVC JSON JavaScriptSerializer 字符串的长度超过 maxJsonLength 值问题的解决
查看>>
statickeyword
查看>>
go语言 rune切片
查看>>
ifconfig源码分析之与内核交互数据
查看>>
python爬虫实践教学
查看>>
点到直线方程的距离、垂足、对称点
查看>>
ubuntu下使用matplotlib绘图无法显示中文label
查看>>
Mac Finder 显示路径和复制路径
查看>>
MongoDb进阶实践之九 Mongodb的备份与还原
查看>>
Java邻接表表示加权有向图,附dijkstra最短路径算法
查看>>
删库跑路?你应该看看云数据库
查看>>
浅谈架构之路:单点登录 SSO
查看>>
Docker 入门(Mac环境)- part 2 容器(container)
查看>>