我正在一个大型数据库上运行各种各样的分析,这对于我们的应用程序的用户来说是典型的。它存储了数百万条记录,我花时间确保字段类型是它们需要的类型(尽管我们也可以规范化这些列中的三个并将其移动到外键)。
默认情况下,查询按相关信息分组并统计重复记录的问题。这个组杀死了我们 - 查询在0.08
几秒钟内运行并将其减慢到5.89
平均水平。
一个示例查询:
SELECT player, x, y, z, COUNT(id), action_type
FROM prism_actions WHERE world = 'world'
AND (prism_actions.x BETWEEN -1119.650147217701 AND -919.650147217701)
AND (prism_actions.y BETWEEN -33.0 AND 167.0)
AND (prism_actions.z BETWEEN 385.14867792476133 AND 585.1486779247614)
AND prism_actions.action_time >= '2013-01-31 17:09:16'
GROUP BY prism_actions.block_id
LIMIT 1000;
我已经尝试了我们的应用程序可能使用的各种不同的查询,分组依据是最大的性能损失之一。
我们当前的表结构:
CREATE TABLE IF NOT EXISTS `prism_actions` (
`id` int(11) unsigned NOT NULL auto_increment,
`action_time` timestamp NOT NULL default CURRENT_TIMESTAMP,
`action_type` varchar(25) NOT NULL,
`player` varchar(16) NOT NULL,
`world` varchar(255) NOT NULL,
`x` int(11) NOT NULL,
`y` int(11) NOT NULL,
`z` int(11) NOT NULL,
`block_id` mediumint(5) default NULL,
`block_subid` mediumint(5) default NULL,
`old_block_id` mediumint(5) default NULL,
`old_block_subid` mediumint(5) default NULL,
`data` varchar(255) default NULL,
PRIMARY KEY (`id`),
KEY `x` (`x`),
KEY `action_type` (`action_type`),
KEY `player` (`player`),
KEY `block_id` (`block_id`)
) ENGINE=MyISAM DEFAULT CHARSET=latin1 AUTO_INCREMENT=44525743 ;
我们通常按三个字段分组,但这些字段对性能影响不大。我尝试过使用索引(有些人针对我们遇到的其他问题推荐了组合索引,但是用户可能会请求应用程序的查询有很多变体 - 无法真正知道他们将使用哪些字段) .
如何提高分组的性能?