【发布时间】:2016-05-13 04:08:22
【问题描述】:
我最近为我的 PHP 会话迁移到数据库存储。在创建会话处理函数后,我意识到我的写入速度很慢。
以下查询在 MySQL 上需要 0.04 秒,在 SQLite 上需要 0.08 秒。这似乎并不慢,直到我意识到新设置的表格只有 6 行。
UPDATE sm_sessions
SET last_access = '1463104877'
WHERE session_id = 'smsess-5734112c09619927459593e9866792515f74ba3115d3a1093b3a31018'
LIMIT 1
还有,这是表结构。
CREATE TABLE IF NOT EXISTS `sm_sessions` (
`id` int(10) NOT NULL AUTO_INCREMENT,
`session_id` char(64) COLLATE utf8mb4_unicode_ci NOT NULL,
`session_data` text COLLATE utf8mb4_unicode_ci,
`last_access` int(10) NOT NULL,
PRIMARY KEY (`id`),
KEY `session_id` (`session_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci AUTO_INCREMENT=57 ;
请注意,我已经尝试了所有方法,包括以下内容:
- 添加了主键和自增“id”(这个字段一开始是不存在的,尝试添加看看会不会影响性能)
- 在 session_id 上尝试了主键、唯一索引和常规索引
- 尝试删除所有索引
- 尝试修改查询以使用 where 子句中的 id 而不是 64 个字符的 session_id 进行更新(没有改进)
- 尝试使用 REPLACE INTO 和 ON DUPLICATE KEY 更新(更糟)
- 直接从 mysql cli 和 phpmyadmin(以及 sqlite cli 和 sqliteadmin)运行查询 - 性能相同,所以我知道它不是 php 或 pdo 减慢它的速度
我知道 0.04 秒还不错。但是,读取在 0.0006 秒左右完成。如果我有 10 次写入,那就是 0.4 秒。而且,是的,我知道读取通常总是比写入快,但是对于一个有 6 行、新设置和如此简单查询的表来说,0.04 或更差的速度听起来非常糟糕。
我觉得这个更新查询在 WORST 应该需要 0.01 秒,通常在 0.005 秒的范围内。这是一个合理的期望吗?
这是在本地完成的,但似乎即使在不同的服务器上写入也会相对较慢,因为其他一切都很快。我可以发布代码或 mysql/sqlite 设置,但我觉得这在最近制作的 6 行表上并不重要。
怎么了?
编辑|更新安装mysql时创建的mysql表,一个简单的更新查询耗时0.005秒。相同的数据库服务器。出了点问题。
EDIT2|将存储引擎从 InnoDB 更改为 MyISAM 使查询运行得更快 - 0.0009 秒。我会将此标记为已解决,我可能会,但有谁知道为什么会加快它的速度?
EDIT3|抱歉所有的编辑,但任何阅读的人都应该知道我在下面的答案中找到了解决方案。
【问题讨论】:
-
是 0.04 秒还是 0.04 毫秒?无论哪种方式,除非您遇到严重的性能问题,否则这听起来不像是世界末日。
-
0.04 秒(40 毫秒)。我觉得这是世界末日,因为在使用数据库会话管理时,每次会话写入都需要 0.04 秒。另外,我正在编写一个开源软件,如果没有这个,页面加载时间不到 0.01 秒。还有,不管是不是世界末日,我觉得还是不应该发生的。我在上面添加了一个编辑。
-
如果您对这些类型的数据库调用感到害怕,那么您已经遇到了麻烦。如果要存储少量数据,可以使用 Redis 之类的东西,它通常比 MySQL 快,但限制更多。
-
MyISAM 不是事务性的,它非常脆弱。在轻负载下它会表现得更好,但重负载会受到表级写锁的严重影响。您确实需要在压力下进行基准测试,否则您的数字毫无意义。
-
感谢基准测试,我能够找出问题在于客户端/服务器字符集和排序规则与数据库/表/字段字符集和排序规则不同。更改客户端/服务器字符集和排序规则以匹配数据库导致速度提高了约 40 倍。
标签: mysql sql performance sqlite