mysql innodb内连接用longtext很慢

时间:2012-06-18 02:45:00

标签: mysql performance innodb longtext

我上周将一个项目的所有MySQL表从MyISAM迁移到InnoDB,以支持交易。我使用了alter table的命令。

大多数工作正常,但是一个特定的查询运行速度非常慢,并且总是会出现错误Incorrect key file for table '/tmp/#sql_xxxx_x.MYI

后来我将问题缩小到2个表的内连接,即user表和agreement表。并且内连接发生在user的外键字段(即agreement_id)和agreement的主键字段(即id)之间。

user表只有50,000行数据,agreement表有一行。我们已为用户agreement_id设置了索引。

无论如何,这似乎是一个非常轻量级的查询,但事实证明它是整个瓶颈。

以下是agreement的完整架构:

CREATE TABLE IF NOT EXISTS `agreement` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `remark` varchar(200) NOT NULL,
  `content` longtext NOT NULL,
  `is_active` tinyint(1) NOT NULL,
  `date_stamp` datetime NOT NULL,
  PRIMARY KEY (`id`)
) DEFAULT CHARSET=utf8 AUTO_INCREMENT=2 ;

我怀疑的一件事是remark表中agreement的longtext字段,但我们没有使用该字段进行内连接,事实上即使我们没有使用该字段也很慢在查询结果中选择remark

最后,我们将agreement的表从innoDB转换回MyISAM,而不是一切正常。查询在不到1秒的时间内完成。

现在,我的问题是这里究竟发生了什么?这是否意味着一旦innoDB表包含任何文本字段,那么该表不能用于内连接?

我希望我能知道真正的原因,以便将来可以避免同样的问题。

非常感谢。

4 个答案:

答案 0 :(得分:2)

这是一个着名且棘手的问题。最可能的原因是你在/ tmp中没有空间。

以下是我在书签中保留的链接,可以帮助您:http://www.mysqlperformancetuning.com/a-fix-for-incorrect-key-file-for-table-mysql

  

根据我的经验,虽然有限,但看到的主要原因   此错误消息是因为您的tmpdir空间不足。喜欢   我你会检查你有多少可用空间:1Gb,2Gb,4Gb。有可能   还不够。这就是原因:MySQL可以创建临时表   比在几秒钟内更大,快速填补任何免费   空间。取决于查询的性质和大小   数据库自然。

你也可以在你的桌子上试试REPAIR,但对我而言,它与霹雳舞一样有用:/

答案 1 :(得分:1)

InnoDB有自己的缓冲区大小等设置。检查一下,如果可以调整它,请继续。只是为了测试尝试加倍,如果它有帮助,你可能想要优化它。它可以产生很大的不同。

一些可能有用的链接:

http://www.mysqlperformanceblog.com/2007/11/03/choosing-innodb_buffer_pool_size/

http://dev.mysql.com/doc/refman/5.5/en/innodb-buffer-pool.html

答案 2 :(得分:1)

这里的问题可能是remark字段定义为varchar(200)?请记住,临时表和内存表存储具有固定长度的varchar。所以带有varchar(200)的50k行可能会消耗大量内存,即使它们都是空的。

如果这是问题所以你可以尝试以下几种方法之一:

答案 3 :(得分:1)

您的查询的目的是什么?我从您的评论中看到,您只列出了用户信息,而且协议中没有任何内容让我相信您正在寻找有协议的用户? 由于您在引擎之间进行转换,因此我会在添加约束之前认为您正在进行清理。如果是这样,请考虑使用用户表中的左连接,如:

select user.* from user left join agreement on user.agreement_id = agreement.id where user.agreement_id != 0;

如果它不是清理,而只是寻找具有协议的用户,我们就这么简单

select user.* from user where user.agreement_id != 0;

如果目的不是其他,请考虑在user.agreement_id上添加索引,因为内部联接可能需要它来提高速度。让我们知道真正的目的,你可以得到更好的帮助。