简单的mysql更新查询有时很慢

时间:2011-12-05 12:05:27

标签: mysql performance

我有一个简单的查询,通常在0.0002秒内完成。有时(例如,200中的1)查询将花费1000倍的时间来完成。

慢查询日志:

# Time: 111205 12:21:21
# User@Host: abc[abc] @ localhost []
# Query_time: 0.120205  Lock_time: 0.000025 Rows_sent: 0  Rows_examined: 1
SET timestamp=1323084081;
UPDATE `users` 
SET `online`=NOW(), 
     lastip='123.123.123.123', 
     pageviews = pageviews + '1', 
     onlinetoday = '1' 
WHERE `user_name`='Alex' 
LIMIT 1;

user_name字段已编入索引。更新的字段(onlinelastippageviewsonlinetoday)不是。

使用主键( A_I, int(35) )而不是 user_name (varchar(50) 时会出现同样的问题。

该表包含22 000行和68个字段,其中5个是索引。

我还有另一张表有完全相同的问题:

CREATE TABLE `person_values` (
 `id` int(255) NOT NULL,
 `A1` int(255) NOT NULL DEFAULT '0',
 `A2` int(255) NOT NULL DEFAULT '0',
 `A3` int(255) NOT NULL DEFAULT '0',
 `A4` int(255) NOT NULL DEFAULT '0',
 `A5` int(255) NOT NULL DEFAULT '0',
 `A6` int(255) NOT NULL DEFAULT '0',
 `A7` int(255) NOT NULL DEFAULT '0',
 `A8` int(255) NOT NULL DEFAULT '0',
 `A9` int(255) NOT NULL DEFAULT '0',
 `A10` int(255) NOT NULL DEFAULT '0',
 `A11` int(255) NOT NULL DEFAULT '0',
 `A12` int(255) NOT NULL DEFAULT '0',
 `A13` int(255) NOT NULL DEFAULT '0',
 `A14` int(255) NOT NULL DEFAULT '0',
 `A15` int(255) NOT NULL DEFAULT '0',
 `A16` int(255) NOT NULL DEFAULT '0',
 `A17` int(255) NOT NULL DEFAULT '0',
 `A18` int(255) NOT NULL DEFAULT '0',
 `A19` int(255) NOT NULL DEFAULT '0',
 `A20` int(255) NOT NULL DEFAULT '0',
 `A21` int(255) NOT NULL DEFAULT '0',
 `A22` int(255) NOT NULL DEFAULT '0',
 `A23` int(255) NOT NULL DEFAULT '0',
 `A24` int(255) NOT NULL DEFAULT '0',
 `A25` int(255) NOT NULL DEFAULT '0',
 `A26` int(255) NOT NULL DEFAULT '0',
 `A27` int(255) NOT NULL DEFAULT '0',
 `A28` int(255) NOT NULL DEFAULT '0',
 UNIQUE KEY `person` (`id`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8

查询:

UPDATE `person_values` SET A25 = A25 + 1 WHERE id = '1' LIMIT 1;

person_values包含大约28 000行。

Mysql服务器版本:5.1.49-3-log Mysql客户端版本:5.1.49 发行:Debian 6.0.3

可能导致此问题的原因是什么?

3 个答案:

答案 0 :(得分:0)

  1. 请发布架构的相关部分:SHOW CREATE TABLE tbl_name
  2. 检查您是否设置了user_name的索引大小,     因为你最有可能使用varchar列。你应该设置     此类列上的索引的字符长度,如:CREATE INDEX part_of_name ON customer (name(10));

答案 1 :(得分:0)

如果您不需要立即回读刚刚修改过的行,可以尝试将UPDATE语句替换为REPLACE DELAYED(注意:它们的语法不同!遗憾的是没有{{1} }})看看这是否有帮助。

答案 2 :(得分:0)

如果这是InnoDB,我会回答:当行在缓冲池中时更新很快,否则它应该首先加载到缓冲池中,然后更新,最后写回。 MyISAM以类似的方式工作,它必须打开表并找到记录,以便更新它。因此,在某些时候进行简单查询花费0.1秒是完全可以接受的。您可以增加相应的设置(例如MySQL可以打开多少个表,如果在MyISAM中使用它们,可以增加一些缓冲区),以便很少或永远不会发生这种情况。