我的网络应用程序中有一个用于存储会话数据的表。它的表现很糟糕,我无法弄清楚原因。慢查询日志显示更新行需要6到60秒。
CREATE TABLE `sessions` (
`id` char(40) COLLATE utf8_unicode_ci NOT NULL,
`payload` text COLLATE utf8_unicode_ci NOT NULL,
`last_activity` int(11) unsigned NOT NULL,
PRIMARY KEY (`id`),
UNIQUE KEY `session_id_unique` (`id`) USING HASH
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci
PK是char(40
),它存储由该项目使用的框架(Laravel)生成的唯一会话哈希。
(我已经意识到PK和唯一索引的冗余,但我已经尝试了所有组合,但它对我的测试中的性能没有任何影响。这是当前状态它。)
表格很小 - 少于200行。
慢查询日志中的典型查询如下所示:
INSERT INTO sessions (id, payload, last_activity)
VALUES ('d195825ddefbc606e9087546d1254e9be97147eb',
'YTo1OntzOjY6Il90b2tlbiI7czo0MDoi...around 700 chars...oiMCI7fX0=',
1405679480)
ON DUPLICATE KEY UPDATE
payload=VALUES(payload), last_activity=VALUES(last_activity);
我做了很明显的事情,比如查看表格是否有损坏。我已经尝试添加专用的PK列作为自动增量int
,我已经尝试过没有PK,没有唯一索引,将text
列换成非常大的{ {1}},你的名字。
我已经尝试将表格切换为使用MyISAM,但它仍然很慢。
我所做的一切似乎没有任何区别 - 桌子的表现非常缓慢。
我的下一个想法是查询。这是由框架生成的,但是如果失败的话,我已经测试了将其标记为varchar
UPDATE
。 INSERT
声明继续缓慢。
我已经阅读了很多关于慢UPDATE
和INSERT
语句的问题,但这些问题通常与批量交易相关。这只是每个请求每个用户一次插入/更新。该网站并不是很忙,而且它拥有足够的资源在自己的VPS上。
什么可能导致缓慢?
答案 0 :(得分:2)
这不是答案,但SE评论的长度太短了。如此。
如果直接在命令行上运行相同的INSERT ... ON DUPLICATE KEY UPDATE ...语句会发生什么?请尝试使用和不使用应用程序的实际使用。该应用程序可能会人为地减慢此更新速度(例如,在INNODB中,事务可能会被打开,但是在消耗了大量时间之后就会提交。您也使用MyISAM进行测试,这也不支持事务。也许在这种情况下,显式LOCK可以如果框架使用这个技巧,我不确定,我不知道laravel)尝试进行基准测试以确定是否存在并发效应。
另一个问题:这是一台服务器吗?或者它是一个复制到一个或多个奴隶的主人?
除了这个问题,还有一些意见:
(虽然这个列表确实提供了改进的角度,但似乎不太可能通过这种方式来解决极端缓慢问题。必须有其他事情发生)
答案 1 :(得分:0)
令人沮丧的是,答案是这个案子是一个糟糕的磁盘。存储阵列中的一个磁盘变坏了,因此写入工作将永远完成。就是这样。