【问题标题】:Determine whether field in MySql indexed column is numeric using index semantics使用索引语义确定MySql索引列中的字段是否为数字
【发布时间】:2012-04-03 15:55:36
【问题描述】:

我有一个 MySql 表,我想在其中获取给定 VARCHAR 列具有数值的行数(您知道,可以转换为数字)。现在,我正在对该字段进行简单的 REGEXP 检查。由于这个表非常大,我使用了一系列索引到 REGEXP 尽可能少的行。

但是这个 VARCHAR 列也被索引了。我可以利用 MySql 索引算法的巧妙破解来扫描更少的行吗? :-/ 这是一个 InnoDB 表。

【问题讨论】:

    标签: mysql indexing b-tree query-performance


    【解决方案1】:

    您可能不喜欢这样,因为您可能已经在尝试避免它,而是尝试做一些聪明的技巧,当我遇到这种情况时,我添加了一个额外的列,将 varchar 存储在一个数字列中(使用触发器更新),并对此进行查询。

    但是,我可以看到有一种方法可以做到这一点(尽管我从来没有理由在生产中这样做),即利用索引将值按顺序排列的事实,这样所有开始与数字一起排序。

    假设这样的表:

    CREATE TABLE `test_1` (
      `id` int(11) NOT NULL AUTO_INCREMENT,
      `text_or_number` varchar(255),
      PRIMARY KEY (`id`),
      KEY `test_1_idx` (`text_or_number`)
    ) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8;
    

    您可以利用 utf8 字符的顺序仅选择以数字开头的值 - http://en.wikipedia.org/wiki/UTF-8#Examples

    utf-8 中 0 之前的最小值是“/”,之后的最大值是“:”,所以这应该只提取以数字开头的值:

    select   cast(text_or_number as unsigned)
    from     test_1
    where    text_or_number < ':'
    and      text_or_number > '/'
    and      cast(text_or_number as unsigned) > 0;
    

    它仍然可以包含以数字开头的值,但不以数字结尾,这就是我添加 cast(...) > 0 子句的原因,但我认为 mysql 会足够聪明地运行 where子句按顺序排列,因此希望它只会对以数字字符开头的行子集运行强制转换。

    【讨论】:

    • 不错,不错!通过一个奇怪的命运转折,看起来我所有的行在这个字段中都有一个完整的数字,或者一个完整的 alpha - 这让我不必进行正则表达式检查(尽管防御性/偏执狂迫使我检查过滤无论如何都要向下行)。与正则表达式检查相比,这似乎在我缩小的样本数据集上表现更好。
    猜你喜欢
    • 2014-08-10
    • 1970-01-01
    • 1970-01-01
    • 2011-03-08
    • 1970-01-01
    • 1970-01-01
    • 2014-10-25
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多