我正在大型数据库上运行各种各样的分析,这对我们的应用程序的用户来说是典型的.它存储了数百万条记录,我花时间确保字段类型是他们需要的(虽然我们也可以规范化并将这些列中的三列移动到外键).
默认情况下,查询按相关信息分组并计算重复记录的问题.这个小组会杀死我们 - 接受一个在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)
我们通常按三个字段分组,但这些字段对性能影响不大.我尝试过使用索引(有些人推荐了我们已经遇到的其他问题的组合索引,但是用户可能会要求应用程序查询的查询种类太多 - 无法真正知道他们将使用哪些字段) .
如何提高分组的性能?
假设相同的查询在 3 列中表现良好,group by但在 1 列中表现不佳block_id,我们可以问有什么区别?
不同之处在于block_id它有一个索引。您可能认为索引总是可以提高性能,但事实并非如此。我建议您删除索引block_id并查看它是否可以提高查询性能。
在幕后发生的事情(假设这解决了性能问题)是索引查找记录,然后必须从表中随机获取该记录。下一条记录可能位于很远的地方。很快,页面缓存就满了,每次读取记录都需要从磁盘读取一个页面。主要的性能瓶颈。
排序方法确实读取数据,但效率更高,因为它一次读取一页上的所有记录。因此,删除索引可能会提高性能。
| 归档时间: |
|
| 查看次数: |
1587 次 |
| 最近记录: |