我的查询大约需要20秒,我想了解是否有办法优化它。 表1:
CREATE TABLE IF NOT EXISTS `sessions` (
`id` int(10) unsigned NOT NULL AUTO_INCREMENT,
`user_id` int(10) unsigned NOT NULL DEFAULT '0',
PRIMARY KEY (`id`),
KEY `user_id` (`user_id`)
) ENGINE=MyISAM DEFAULT CHARSET=latin1 AUTO_INCREMENT=9845765 ;
表2:
CREATE TABLE IF NOT EXISTS `access` (
`id` int(10) unsigned NOT NULL AUTO_INCREMENT,
`session_id` int(10) unsigned NOT NULL DEFAULT '0',
PRIMARY KEY (`id`),
KEY `session_id ` (`session_id `)
) ENGINE=MyISAM DEFAULT CHARSET=latin1 AUTO_INCREMENT=9467799 ;
现在,我要做的是计算连接到一个用户的所有会话的所有访问权限,所以我的查询是:
SELECT COUNT(*)
FROM access
INNER JOIN sessions ON access.session_id=session.id
WHERE session.user_id='6';
这需要将近20秒......对于user_id 6,存储了大约3百万个会话。 我可以做些什么来优化该查询?
答案 0 :(得分:1)
从会话表中更改此行:
KEY `user_id` (`user_id`)
对此:
KEY `user_id` (`user_id`, `id`)
这将为您做什么,允许您从索引中完成查询,而无需返回到原始表。实际上,您需要在user_id
的会话表上执行索引扫描,并且对于每个项目,请返回到表中以查找用于访问表的连接的id
。通过在索引中包含id
,您可以跳过返回表格。
可悲的是,这会使你的插入更慢地进入该表,并且看起来这可能是一个出价协议,只给一个用户有3百万个会话。 Sql Server和Oracle将通过允许您在索引中包含id
列而不实际对其进行索引,在插入时节省一些工作,并允许您为索引指定较低的填充因子来解决此问题,减少了在插入时重新构建或重新排序索引的需要,但MySql不支持这些。