【问题标题】:MySQL performance issue on ~3million rows containing MEDIUMTEXT?大约 300 万行包含 MEDIUMTEXT 的 MySQL 性能问题?
【发布时间】:2023-03-31 00:35:02
【问题描述】:

我有一个包含 3 列和 3600K 行的表。使用 MySQL 作为键值存储。

第一列 id 是 VARCHAR(8) 并设置为主键。第二和第三列是 MEDIUMTEXT。当调用SELECT * FROM table WHERE id=00000 MySQL 时花了大约 54 秒 ~ 3 分钟。

为了测试,我创建了一个包含 VARCHAR(8)-VARCHAR(5)-VARCHAR(5) 的表,其中的数据是从 numpy.random.randint 随便生成的。 SELECT 在没有主键的情况下需要 3 秒。与 VARCHAR(8)-MEDIUMTEXT-MEDIUMTEXT 相同的随机数据,SELECT 的时间成本为 15 秒,没有主键。(注意:在第二次测试中,第二和第三列实际上包含非常短的文本,如“65535”,但创建作为中文本)

我的问题是:如何在真实数据上实现类似的性能? (或者,不可能吗?)

【问题讨论】:

  • 很抱歉,这是 2 分 54 秒,而不是 54 秒。真实数据耗时3min(mysql和python定时time.clock()),测试数据耗时15sec。
  • 你为什么使用 VARCHAR 作为你的 id ?
  • 您是否在测试表中的“数据”列上使用索引?还是那里只有主键?我很确定您的瓶颈是磁盘 I/O 和 varchar 作为主键的次优使用
  • 就像@Imanez 说的,为什么在你的id 上使用varchar?在索引整数列上搜索要快得多。
  • @Imanez 我应该使用数字 int 还是 TINYTEXT?我被测试弄糊涂了,它使用了 VARCHAR 但比在真实场景中快得多

标签: mysql


【解决方案1】:

如果你使用

SELECT * FROM `table` WHERE id=00000

而不是

SELECT * FROM `table` WHERE id='00000'

您正在寻找等于整数0 的所有字符串,因此MySQL 必须检查所有行,因为'0''0000' 甚至' 0' 都将被转换为整数0 .所以你在id 上的主键将无济于事,你最终会得到一个缓慢的完整表。即使您不以这种方式存储值,MySQL 也不知道。

正如所有 cmets 和答案所指出的那样,最好的选择是将数据类型更改为 int

alter table `table` modify id int;

这仅在您转换为整数的 id 是唯一的情况下才有效(因此您的表中没有 '0''00')。

如果您有任何引用 id 的外键,您必须先删除它们,然后在重新创建它们之前,还要更改其他列中的数据类型。

如果你有一个已知的格式来存储你的值(例如,没有零,或者用 0 填充到 8 的长度),第二个最佳选择是使用这种确切的格式来进行查询,并包括 @ 987654334@ 不将其转换为整数。如果你例如始终将0 填充为 8 位数字,使用

SELECT * FROM `table` WHERE id='00000000';

如果您从不添加任何零,仍然添加'

SELECT * FROM `table` WHERE id='0';

通过这两个选项,MySQL 可以使用您的主键,您将在毫秒内得到结果。

【讨论】:

  • 是的,我忘记了引号!!非常感谢您指出这一点。
【解决方案2】:

如果您的 id 列仅包含数字,请将其定义为 int ,因为 int 会给您带来更好的性能(它更快)

【讨论】:

    【解决方案3】:

    将表中的列(定义为键的列)设为整数并重试。通过在您的数据库(工作台或简单命令行)中运行测试来检查第一个性能。你应该得到更好的结果。 然后,并且仅在需要时(我对此表示怀疑),修改您的 python 以在引用键列时从整数转换为字符串(和/或反之亦然)。

    【讨论】:

      猜你喜欢
      • 2012-07-27
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-11-14
      • 1970-01-01
      相关资源
      最近更新 更多