【问题标题】:COUNT and GROUP BY on text fields seems slow文本字段上的 COUNT 和 GROUP BY 似乎很慢
【发布时间】:2011-03-19 08:08:57
【问题描述】:

我正在构建一个 MySQL 数据库,其中包含有关酵母物种中特殊 DNA 子串的条目。我的桌子是这样的:

+--------------+---------+------+-----+---------+-------+
| Field        | Type    | Null | Key | Default | Extra |
+--------------+---------+------+-----+---------+-------+
| species      | text    | YES  | MUL | NULL    |       |
| region       | text    | YES  | MUL | NULL    |       |
| gene         | text    | YES  | MUL | NULL    |       |
| startPos     | int(11) | YES  |     | NULL    |       |
| repeatLength | int(11) | YES  |     | NULL    |       |
| coreLength   | int(11) | YES  |     | NULL    |       |
| sequence     | text    | YES  | MUL | NULL    |       |
+--------------+---------+------+-----+---------+-------+

大约有 180 万条记录。在一种类型的查询中,我想查看有多少 DNA 子串与每种类型的物种和地区相关联,因此我发出以下查询:

select species, region, count(*) group by species, region;

物种和区域列只有两个可能的条目(物种的保守/scer,区域的启动子/编码)但此查询大约需要 30 秒

考虑到表的大小,这是否是此类查询的正常预期时间?是不是很慢,因为我使用的是文本字段而不是简单的整数或布尔值(我更喜欢文本字段,因为一些非 CS 研究人员将使用数据库)。欢迎任何其他想法和建议。

如果这是一个愚蠢的问题,请原谅,我是 SQL 新手。

附:我也见过this question,但建议的解决方案似乎与我正在做的事情无关。

编辑:将这些字段转换为 VARCHAR 可将运行时间缩短至约 2.5 秒。请注意,我还针对具有类似时间的 ENUM 进行了计时。

【问题讨论】:

  • 哪个字段是你的主键?
  • 我没有主键。我可以人工制造一个,但这有关系吗?

标签: sql mysql database query-optimization aggregate-functions


【解决方案1】:

为什么所有基于字符串的列都定义为 TEXT?如果您阅读性能比较,您会发现 TEXT 比使用相同索引的 VARCHAR 列慢约 3 倍:http://forums.mysql.com/read.php?24,105964,105964

【讨论】:

  • 好收获。没注意到他们是text
  • 我使用 TEXT 是因为我的一位同事说它与 VARCHAR 没有任何区别。 :) 使用 VARCHAR 使我的运行时间从 33 秒缩短到 2.5 秒。
  • @Rich:哇——没想到会有如此巨大的差异。如果您将物种和区域列更改为保存其各自值的表的外键,您可能会变得更低。一个 INT 总是 4 个字节,而一个 VARCHAR(4) 是 5 个所以你可以想象 VARCHAR(100) 是多少个字节。
【解决方案2】:

如果您的字段只有 2 个值,则最好将它们设为布尔值。你也应该把所有东西都写成NOT NULL,除非有真正的原因你需要它是NULL

还可以查看ENUM type,以更好地为列使用有限数量的人类可读值。

至于速度慢,首先要尝试在列上创建索引。对于您在此处显示的特定查询,species, region 上的索引应该会产生巨大的影响:

create index on mytablename (species, region);

应该这样做。

【讨论】:

  • 你确定索引会对这样的低基数数据产生巨大的影响吗?
  • 不,我不确定,但我认为这是一个很好的猜测。我开始写一些关于使用EXPLAIN 的文章,但它开始变成一罐蠕虫。我猜最终结果可能是我们应该尝试创建索引。
  • 我尝试了索引,但没有任何区别。我还按照 OMG Ponies 的建议尝试了 VARCHAR,这要快得多。之后,我对枚举进行了尝试,而 VARCHARs 没有明显的加速。
  • +1 表示NOT NULL,-1 表示make it boolean。几年前我在 SQL 新闻组中读到的内容:“我通常使用 1 个字符的标志。根据我的经验,当我最初认为我具有二进制状态时,它实际上是一个多变量标志。换句话说,只要我代码来判断门是打开还是关闭,其他人想知道它是否被锁定。”
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2023-02-01
  • 2021-12-26
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-10-16
相关资源
最近更新 更多