我在大型数据库上运行各种分析,这对我们应用程序的用户来说很常见。它存储了数百万条记录,我花时间确保字段类型是它们需要的(尽管我们也可以规范化并将其中三个列移动到外键)。
默认按相关信息分组查询,统计重复记录的问题。这个 group by 杀死了我们 - 将一个在 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 ;
我们通常按三个字段分组,但这对性能影响不大。我试过使用索引(有些人已经为我们遇到的其他问题推荐了组合索引,但是用户可能会请求应用程序的查询有很多变化 - 无法真正知道他们将使用哪些字段) .
如何提高分组的性能?
最佳答案
尝试以下更改:
- 创建一个包含 world、block_id、x、y、z 和 行动时间
- 使 block_id 不为空
- 对于 x, y, z 条件,将值四舍五入,因为 x, y, z 无论如何都是整数
关于mysql - 优化 GROUP BY 性能 - 查询时间大约增加五秒,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/15754368/