优化GROUP BY性能 - 增加大约五秒钟的查询时间

hel*_*on3 5 mysql

我正在大型数据库上运行各种各样的分析,这对我们的应用程序的用户来说是典型的.它存储了数百万条记录,我花时间确保字段类型是他们需要的(虽然我们也可以规范化并将这些列中的三列移动到外键).

默认情况下,查询按相关信息分组并计算重复记录的问题.这个小组会杀死我们 - 接受一个在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;
Run Code Online (Sandbox Code Playgroud)

我尝试了各种不同的查询,我们的应用可能会使用,分组是最大的性能命中之一.

我们目前的表结构:

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 ;
Run Code Online (Sandbox Code Playgroud)

我们通常按三个字段分组,但这些字段对性能影响不大.我尝试过使用索引(有些人推荐了我们已经遇到的其他问题的组合索引,但是用户可能会要求应用程序查询的查询种类太多 - 无法真正知道他们将使用哪些字段) .

如何提高分组的性能​​?

Gor*_*off 0

假设相同的查询在 3 列中表现良好,group by但在 1 列中表现不佳block_id,我们可以问有什么区别?

不同之处在于block_id它有一个索引。您可能认为索引总是可以提高性能,但事实并非如此。我建议您删除索引block_id并查看它是否可以提高查询性能。

在幕后发生的事情(假设这解决了性能问题)是索引查找记录,然后必须从表中随机获取该记录。下一条记录可能位于很远的地方。很快,页面缓存就满了,每次读取记录都需要从磁盘读取一个页面。主要的性能瓶颈。

排序方法确实读取数据,但效率更高,因为它一次读取一页上的所有记录。因此,删除索引可能会提高性能。