MySQL 在索引中使用自定义字符串比较运算符

Posted

技术标签:

【中文标题】MySQL 在索引中使用自定义字符串比较运算符【英文标题】:MySQL using a custom string comparison operator in Index 【发布时间】:2017-02-22 11:37:04 【问题描述】:

我正在寻找一种方法来指定 mysql 索引使用的顺序(使用 MariaDB 10 的 InnoDB 中的 BTREE)。更具体地说,我想创建一个索引,该索引使用类似于以下伪代码的可变长度条目来索引 varchar 列:

-- assume "str" to be the field in question, return values like strcmp
if (len(row1.str) < len(row2.str))

    return -1;
 else if (len(row1.str) > len(row2.str)) 
    return 1;
 else 
    return row1.str < row2.str;

有没有办法只为一个特定的索引指定这种排序?

【问题讨论】:

【参考方案1】:

这样的东西应该有同样的效果:

ORDER BY CHAR_LENGTH(str), str

【讨论】:

我考虑过使用具有类似ORDER BY 子句的物化视图,但这必须在数据库查询中显式使用(读取连接),而拥有索引只会启用查询优化器在我认为合适的时候选择它。【参考方案2】:

https://mariadb.com/kb/en/mariadb/virtual-computed-columns/ --

ALTER TABLE foo ADD COLUMN
  for_sorting VARCHAR(...)   -- make a little wider than `str`
      AS (       -- syntax
         CONCAT(
            RIGHT(CONCAT('0000', CHAR_LENGTH(str)), 5),  -- num sortable as string
               ':', str )  -- tack on `str` for when len differs
      ) PERSISTENT   -- "indexes can only be based on PERSISTENT virtual columns"
      COMMENT "kludge for special indexing" 

然后做ORDER BY for_sorting

(警告:我没有尝试过,但感觉它会起作用。)

【讨论】:

[In]兼容性说明:这是 MariaDB 特有的功能; MySQL 有类似的东西。 也是一个好主意,但是对于长度为 n 的字符串需要 n + log(n) + 一些恒定的额外空间。最后,我将可能输入的子集转换为整数值,并对意外值进行了硬错误。 因为是PERSISTENT,所以每个INSERT(或UPDATE)计算一次表达式;这是很小的开销。一旦它“持续存在”,ORDER BY 的开销与使用任何其他列进行排序的开销相同。是的,它确实需要额外的磁盘空间,相当于添加一列并为新列建立索引。

以上是关于MySQL 在索引中使用自定义字符串比较运算符的主要内容,如果未能解决你的问题,请参考以下文章

前端学数据库之函数

输入带有比较运算符的字符串,并在数组索引上执行比较

前端学数据库之函数

mysql模糊查询区分大小写

mysql 索引失效总结

C语言中字符串比较大小的规则!