【发布时间】:2015-12-23 04:21:44
【问题描述】:
我有一个 MySQL (5.6.26) 数据库,其中包含大量数据,但我在表连接时遇到了 COUNT 选择问题。
执行此查询大约需要 23 秒:
SELECT COUNT(0) FROM user
LEFT JOIN blog_user ON blog_user.id_user = user.id
WHERE email IS NOT NULL
AND blog_user.id_blog = 1
user 表是 MyISAM,包含用户数据,如 id、电子邮件、姓名等...
CREATE TABLE `user` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`username` varchar(50) DEFAULT NULL,
`email` varchar(100) DEFAULT '',
`hash` varchar(100) DEFAULT NULL,
`last_login` datetime NOT NULL DEFAULT '0000-00-00 00:00:00',
`created` datetime NOT NULL DEFAULT '0000-00-00 00:00:00',
PRIMARY KEY (`id`),
UNIQUE KEY `id` (`id`) USING BTREE,
UNIQUE KEY `email` (`email`) USING BTREE,
UNIQUE KEY `hash` (`hash`) USING BTREE,
FULLTEXT KEY `email_full_text` (`email`)
) ENGINE=MyISAM AUTO_INCREMENT=5728203 DEFAULT CHARSET=utf8
blog_user 表是 InnoDB,仅包含 id、id_user 和 id_blog(用户可以访问多个博客)。 id 是 PRIMARY KEY 并且在 id_blog、id_user 和 id_blog-id_user 上有索引。
CREATE TABLE `blog_user` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`id_blog` int(11) NOT NULL DEFAULT '0',
`id_user` int(11) NOT NULL DEFAULT '0',
PRIMARY KEY (`id`),
UNIQUE KEY `id_blog_user` (`id_blog`,`id_user`) USING BTREE,
KEY `id_user` (`id_user`) USING BTREE,
KEY `id_blog` (`id_blog`) USING BTREE
) ENGINE=InnoDB AUTO_INCREMENT=5250695 DEFAULT CHARSET=utf8
我删除了所有其他表,没有其他连接到 MySQL 服务器(测试环境)。
到目前为止我发现了什么:
- 当我从用户表中删除一些列时,查询的持续时间会更短(例如每个删除的列需要 2 秒)
- 当我从用户表中删除所有列(id 和电子邮件除外)时,查询的持续时间为 0.6 秒。
- 当我将 blog_user 表也更改为 MyISAM 时,查询持续时间为 46 秒。
- 当我将用户表更改为 InnoDB 时,查询持续时间为 0.1 秒。
问题是为什么 MyISAM 执行命令这么慢?
【问题讨论】:
-
使用索引和内连接(如果可能)
-
您是否在查询中使用了
explain,看看它是否让您知道它在哪里花费时间? -
MyISAM必须从磁盘读取所有数据,遍历每一行并将其添加到计数中。据我所知,它使用硬件的方式与 InnoDB 不同(如果可以的话,InnoDB 会将其所有工作数据存储在 RAM 中)。对您来说最好的解决方案是同时拥有两个表 InnoDB 并避免从磁盘读取。 -
@Mjh 谢谢,我正在考虑这个,但不幸的是,我的桌面上有全文索引,它与 MyISAM 一起工作得更好。
-
我怀疑为这两个表使用两个不同的存储引擎这一事实会对性能产生影响。
标签: php mysql database innodb myisam