我可以在不使用索引的情况下优化这样的MySQL查询吗?

时间:2013-11-01 12:54:27

标签: mysql sql query-optimization

我的MySQL数据库的简化版本如下所示:

Table books (ENGINE=MyISAM)
id <- KEY
publisher <- LONGTEXT
publisher_id <- INT <- This is a new field that is currently null for all records

Table publishers (ENGINE=MyISAM)
id <- KEY
name <- LONGTEXT

目前books.publisher包含不断重复的值,但publishers.name保持唯一。 我想摆脱books.publisher,而是填充books.publisher_id字段。

描述我想要完成的简单的SQL代码如下:

UPDATE books 
JOIN publishers ON books.publisher = publishers.name 
SET books.publisher_id = publishers.id;

问题在于我有大量的记录,即使它有效,也需要永远。

是否有比提前使用此类内容更快的解决方案?:

CREATE INDEX publisher ON books (publisher(20));

3 个答案:

答案 0 :(得分:2)

您的问题标题是“..优化...查询而不使用索引?”

您对使用索引有什么反对意见?

如果查询运行缓慢,您应该始终检查执行计划。我猜它必须扫描每行的publishers表以找到匹配项。在publishers.name上建立索引以加快查找id是有意义的。

您可以稍后删除索引,但保留索引不会有害,因为您说该过程必须运行一段时间才能进行其他更改。我认为publishers表格不会经常更新,因此桌子上INSERTUPDATE的效果应该不是问题。

答案 1 :(得分:1)

这里有一些问题可能会有所帮助。

首先,几千行不算“大”......那是“中等”。

其次,在MySQL中说“我想在没有索引的情况下这样做”就像是说“我想把车开到纽约市,但我的轮胎是平的,我不想把它们抽出来。这是什么如果我在我的轮辋上驾驶,最好的路线是纽约?“

第三,您正在为发布商使用LONGTEXT项。有没有理由不使用像VARCHAR(200)那样的完全可索引数据类型?如果这样做,您的WHERE语句将运行得更快,索引或无。大型图书馆目录系统限制了发布商字段的长度,因此您的系统也可以。

第四,根据您的一条评论,这看起来像是例行数据维护更新,而不是一次性转换。所以你需要弄清楚如何避免一遍又一遍地重复整个交易。我在这里猜测,但看起来books表中新插入的行的publisher_id为零,并且您的查询将该列更新为有效值。

所以这是做什么的。首先,在tables.publisher_id上添加一个索引。

其次,运行维护查询的此变体:

UPDATE books 
  JOIN publishers ON books.publisher = publishers.name 
   SET books.publisher_id = publishers.id
 WHERE books.publisher_id = 0
 LIMIT 100;

这将限制您对尚未更新的行的更新。它还将一次更新100行。在每周数据维护工作中,重新发出此查询,直到MySQL宣布您的查询影响零行(查看mysqli :: rows_affected或php-to-mysql接口中的等效项)。这是监控数据库更新进度并防止更新操作失控的好方法。

答案 2 :(得分:-1)

您的更新查询语法无效,但您可以稍后解决此问题。让它运行得更快的方法是添加一个where子句,以便只更新必要的记录。