为什么在这个MySQL实例中,GROUPBY比同一个表连接慢?
作为一个团队,我们习惯使用MS SQL Server。这是我们第一次使用MySQL,我们对一个特殊的行为感到惊讶 我们有以下表格:为什么在这个MySQL实例中,GROUPBY比同一个表连接慢?,mysql,Mysql,作为一个团队,我们习惯使用MS SQL Server。这是我们第一次使用MySQL,我们对一个特殊的行为感到惊讶 我们有以下表格: CREATE TABLE `People` ( `PersonId` int(11) NOT NULL AUTO_INCREMENT, `AddressKey` varchar(255) DEFAULT NULL, `NameKey` varchar(255) DEFAULT NULL, PRIMARY KEY (`PersonId`), KEY
CREATE TABLE `People` (
`PersonId` int(11) NOT NULL AUTO_INCREMENT,
`AddressKey` varchar(255) DEFAULT NULL,
`NameKey` varchar(255) DEFAULT NULL,
PRIMARY KEY (`PersonId`),
KEY `AddressKey` (`AddressKey`),
KEY `NameKey` (`NameKey`)
) ENGINE=InnoDB AUTO_INCREMENT=243771506 DEFAULT CHARSET=utf8;
它非常大,有几亿张唱片。我们发现里面有一些重复的
为了识别它们,我们首先构建一个标准的GROUPBY语句
select NameKey, AddressKey, count(*) as dupes from People
group by NameKey, AddressKey having dupes > 1
limit 2;
在此查询上使用EXPLAIN可生成:
id select_type table partitions type possible_keys key key_len ref rows filtered Extra
1 SIMPLE s1 ALL AddressKey,NameKey 215543661 100.00 Using where
1 SIMPLE s2 ref AddressKey,NameKey NameKey 768 s1.NameKey 5 0.92 Using index condition; Using where
然而,这被证明是可笑的缓慢。进行自联接要快得多:
select s1.* from People s1 join People s2
on s1.NameKey = s2.NameKey and s1.AddressKey = s2.AddressKey
where s1.SuppressionId <> s2.SuppressionId
limit 50;
根据SQLServer扫描表的方式,我们假设GROUPBY会快得多,但事实并非如此。为什么不呢?我们可以做些什么来提高这个查询的性能吗?可能是因为它实际上必须具体化可能包含任意行数的整个组。它没有短路的方法。
按名称键分组,地址键
需要索引(名称键,地址键)
那么查询会更快。。。。您将使用EXPLAIN[query]
获得更多信息。您还应该为这两个查询包含这些信息。表上有索引吗?没有,您需要创建一个包含两列的索引create index idx_somename on People(AddressKey,NameKey)
取决于GROUP BY查询是否需要使用临时表和快速排序,在EXPLAIN output@JorgeCampos的额外列中是否“使用临时;使用文件排序”,这些才是真正的MySQL性能杀手。如果MySQL无法在内存中保存临时表,它将创建一个基于MyISAM磁盘的临时表。。因此,您正在使用随机磁盘i/o对磁盘进行快速排序(因为GROUP BY具有自动排序方式)。。如果索引正确,您将不会遇到此问题,MySQL将像高速列车一样运行。。
id select_type table partitions type possible_keys key key_len ref rows filtered Extra
1 SIMPLE People ALL 215543970 100.00 Using temporary; Using filesort