SQL查询性能优化 - 获取相应A的max(B)

时间:2014-05-09 10:12:22

标签: mysql sql performance query-optimization

我有一个如下所示的数据库方案(参见http://sqlfiddle.com/#!2/4c9b4/1/0):

 create table t( id int,  dataA int, dataB int);
 insert into t select 1 ,1 ,1;
 insert into t select 2 ,1 ,2;
 insert into t select 3 ,1 ,3;
 insert into t select 4 ,2 ,1;
 insert into t select 5 ,2 ,2;
 insert into t select 6 ,2 ,4;
 insert into t select 7 ,3 ,1;
 insert into t select 8 ,3 ,2;
 insert into t select 9 ,4 ,1;

一个SQL查询,用于获取与“dataA”对应的最大“dataB”的“dataA”列表

SELECT * FROM t a WHERE dataB = (SELECT MAX(dataB) FROM t b WHERE b.dataA = a.dataA)

它运行正常,但在我的数据集上运行最多可能需要90秒。

如何提高此查询的效果?

2 个答案:

答案 0 :(得分:2)

即使对于重复的数据,MySQL也可能一次又一次地执行子查询。以下语句只为每个dataA找到一次max(dataB)。其余的是一个简单的连接。希望这更快。

select t.*
from t
join (select dataA, max(dataB) as maxDataB from t group by dataA) max_t
  on t.dataA = max_t.dataA and t.dataB = max_t.maxDataB;

编辑:这是你的SQL小提琴:http://sqlfiddle.com/#!2/4c9b4/2

答案 1 :(得分:1)

MySQL不能很好地进行聚合。首先要尝试的是索引:

create index t_dataA_dataB on t(dataA, dataB);

这可能会解决问题。第二个是使用以下技巧:

select a.*
from t a
where not exists (select 1
                  from t a2
                  where a2.dataA = a.dataA and
                        a2.dataB > a.dataB
                 );

这会将“让我最大化”转换为等效内容:“从t获取所有行,其中没有行具有相同的dataA和更大的dataB”。