【问题标题】:How to make a GROUP BY SUBSTRING query faster?如何更快地进行 GROUP BY SUBSTRING 查询?
【发布时间】:2009-10-20 21:11:34
【问题描述】:

我有一个结构如下的表:

id bigNumber           text
1  1200321030011010233 "an item with some text"
2  1200321030011014563 "another item with some more text"
3  3120323434432211133 "more...."
.
.
.

该表包含大约 50,000 条记录。我想做以下查询,但速度很慢:

  SELECT COUNT(*), 
         bigNumber 
    FROM items 
GROUP BY substr(bigNumber, 1, X)

其中 X 在 2 和 19 之间变化。

创建 19 列并在每列中包含部分数字以便能够使用索引会更快吗?

【问题讨论】:

    标签: mysql sql group-by substring


    【解决方案1】:

    我建议不要使用 19 个单独的列,可能只有 3 或 4 个,如下所示:

    alter table items
    add column bignumber_l1 char(1)
    , add column bignumber_l3 varchar(3)
    , add column bignumber_l6 varchar(6);
    
    update items
    set bignumber_l1 = left(bignumber, 1)
     , bignumber_l3 = left(bignumber, 3)
     , bignumber_l6 = left(bignumber, 6);
    
    alter table items
    add index bignumber_l1
    , add index bignumber_l3
    , add index bignumber_l6;
    

    那么当你查询 x 长度的字符串时,写出最长匹配的查询,而不是更长的:

      SELECT COUNT(*), 
             bigNumber 
        FROM items 
    GROUP BY bignumber_l3, substr(bigNumber, 1, 4)
    

    此查询可以使用索引并且可能会显着提高您的性能。请注意,由于您要求的是整个表,因此即使使用上面的索引,mysql 也可能会决定您需要进行表扫描,因此您可能需要使用FORCE INDEX

    【讨论】:

      【解决方案2】:

      您可以在不添加任何列的情况下使用索引,只需在您的 bigNumber 列上创建一个索引:

      create index bignum_index on items (bigNumber);
      

      varchar 上的索引(bigNumber 是 varchar,对吗?)可用于查找任何字符串前缀。

      也就是说,您需要进行全表扫描才能回答您的查询,因此索引不会对您有太大帮助。

      【讨论】:

      • 感谢大家的快速解答!有谁知道我是否可以证明为此使用 19 列是合理的?我知道这是一个肮脏的解决方案,但我目前唯一关心的是速度:) 也许还有另一种解决方案,不是 substr 吗?澄清一下:我正在运行的实际查询有点不同,并且确实需要 group by,因为我还根据组请求了几个 cols 的 avg。再次感谢!
      • 只要您仍然需要全表扫描,向表中添加更多数据只会让您的查询变慢。所以它是否“脏”是无关紧要的——它根本不是一个解决方案。
      【解决方案3】:

      我认为您正在寻找的结果是 LIKE _X%。不过这不会使用索引。

      SELECT count(*) FROM items WHERE bignumber LIKE "_2%"
      SELECT count(*) FROM items WHERE bignumber LIKE "_19%"
      

      _ 表示一个字符

      % 表示任意数量的字符

      更多信息请参见MySQL docs

      【讨论】:

      • 谢谢,但我需要使用 GROUP BY 方法。 X 从 1 到 19 不等,即我想根据 bigNumber 中的前 X 个数字对项目进行分组。
      • 我建议将大数字的重要部分分开并使用 order by。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-11-13
      • 1970-01-01
      • 1970-01-01
      • 2017-02-24
      • 2022-06-15
      • 1970-01-01
      相关资源
      最近更新 更多