从单个MySQL表优化SQL查询以获得各种条件下的最大值

从单个MySQL表优化SQL查询以获得各种条件下的最大值,mysql,query-optimization,greatest-n-per-group,Mysql,Query Optimization,Greatest N Per Group,我有以下SQL查询 SELECT * FROM `sensor_data` AS `sd1` WHERE (sd1.timestamp BETWEEN '2017-05-13 00:00:00' AND '2017-05-14 00:00:00') AND (`id` = ( SELECT `id` F

我有以下SQL查询

SELECT  *
    FROM  `sensor_data` AS `sd1`
    WHERE  (sd1.timestamp BETWEEN '2017-05-13 00:00:00'
                              AND '2017-05-14 00:00:00')
      AND  (`id` = 
            (
                SELECT  `id`
                    FROM  `sensor_data` AS `sd2`
                    WHERE  sd1.mid = sd2.mid
                      AND  sd1.sid = sd2.sid
                    ORDER BY  `value` DESC, `id` DESC
                    LIMIT  1)
           ) 
背景:

我已经将限制1更改为限制0,查询工作没有任何问题。然而,对于limit1,查询并没有完成,它只是在关闭并重新启动之前声明加载

分解查询:

我已将带有日期边界的查询细分如下:

SELECT  *
    FROM  `sensor_data` AS `sd1`
    WHERE  (sd1.timestamp BETWEEN '2017-05-13 00:00:00'
                              AND '2017-05-14 00:00:00') 
SELECT t1.id, t1.mid, t1.sid, t1.v, t1.ts
FROM yourtable t1
INNER JOIN (
        SELECT mid, sid, MAX(v) as v 
            FROM yourtable
        WHERE ts BETWEEN '2015-05-13 00:00:00' AND '2015-05-14 00:00:00'
        GROUP BY mid, sid
    ) t2
    ON  t1.mid = t2.mid
    AND t1.sid = t2.sid
    AND t1.v   = t2.v
INNER JOIN (
        SELECT mid, sid, v, MAX(ts) as ts
            FROM yourtable
        WHERE ts BETWEEN '2015-05-13 00:00:00' AND '2015-05-14 00:00:00'
        GROUP BY mid, sid, v
    ) t3
    ON  t1.mid = t3.mid
    AND t1.sid = t3.sid
    AND t1.v   = t3.v
    AND t1.ts  = t3.ts; 
这大约需要0.24秒来返回查询,其中8200行中每个行有5列

问题:

我怀疑我的查询的后半部分是不正确的或没有得到很好的优化。 各表如下:

SELECT  *
    FROM  `sensor_data` AS `sd1`
    WHERE  (sd1.timestamp BETWEEN '2017-05-13 00:00:00'
                              AND '2017-05-14 00:00:00') 
SELECT t1.id, t1.mid, t1.sid, t1.v, t1.ts
FROM yourtable t1
INNER JOIN (
        SELECT mid, sid, MAX(v) as v 
            FROM yourtable
        WHERE ts BETWEEN '2015-05-13 00:00:00' AND '2015-05-14 00:00:00'
        GROUP BY mid, sid
    ) t2
    ON  t1.mid = t2.mid
    AND t1.sid = t2.sid
    AND t1.v   = t2.v
INNER JOIN (
        SELECT mid, sid, v, MAX(ts) as ts
            FROM yourtable
        WHERE ts BETWEEN '2015-05-13 00:00:00' AND '2015-05-14 00:00:00'
        GROUP BY mid, sid, v
    ) t3
    ON  t1.mid = t3.mid
    AND t1.sid = t3.sid
    AND t1.v   = t3.v
    AND t1.ts  = t3.ts; 
当前表格:

问:如何获得每个mid的每个sid的最大值? NB1:在上面的示例中,第53、54、55行都有相同的值40,但我想检索具有最新时间戳的行,即第55行

预期产出:

表的结构:

NB2:
由于此表有超过1.1亿个条目,因此必须有日期边界,这将在24小时内限制为8000个条目。

查询可编写如下:

SELECT  *
    FROM  `sensor_data` AS `sd1`
    WHERE  (sd1.timestamp BETWEEN '2017-05-13 00:00:00'
                              AND '2017-05-14 00:00:00') 
SELECT t1.id, t1.mid, t1.sid, t1.v, t1.ts
FROM yourtable t1
INNER JOIN (
        SELECT mid, sid, MAX(v) as v 
            FROM yourtable
        WHERE ts BETWEEN '2015-05-13 00:00:00' AND '2015-05-14 00:00:00'
        GROUP BY mid, sid
    ) t2
    ON  t1.mid = t2.mid
    AND t1.sid = t2.sid
    AND t1.v   = t2.v
INNER JOIN (
        SELECT mid, sid, v, MAX(ts) as ts
            FROM yourtable
        WHERE ts BETWEEN '2015-05-13 00:00:00' AND '2015-05-14 00:00:00'
        GROUP BY mid, sid, v
    ) t3
    ON  t1.mid = t3.mid
    AND t1.sid = t3.sid
    AND t1.v   = t3.v
    AND t1.ts  = t3.ts; 
编辑和解释:

第一个子查询first internal JOIN获取每个mid、sid组合的MAXv。第二个子查询是为每个mid、sid、v标识MAXT。此时,这两个查询不会影响彼此的结果。还需要注意的是,ts日期范围选择是在两个子查询中独立完成的,这样最终查询要检查的行更少,并且没有其他要应用的WHERE筛选器

实际上,这转化为在第一个子查询中获得每个mid、sid组合的最大值;如果给定的mid,sid组合中有多条记录具有相同的MAXv值,则通过为第二个子查询获得的每个mid,sid,v组合选择MAXts来消除多余的记录。然后,我们通过两个内部连接条件将两个查询的输出关联起来,以获得所需记录的id


从传感器数据s1中选择*其中s1.v在s2.mid中从传感器数据s2组中选择最大值

联合


从传感器_数据s1中选择*其中s1.v按s2.sid从传感器_数据s2组中选择maxv

在选择中。。。没有很好地优化。由于相互关联,情况更糟

你要找的是一份工作

请提供显示创建表;我们至少需要知道主键是什么

建议代码

您将需要:

其中包括:INDEXtimestamp、mid、sid、v、id 没有WHERE:INDEXmid,sid,v,timestamp,id 代码:


这也可以用来比较MySQL和MariaDB的不同版本-我在一个相关的groupwise max测试中看到了3个显著不同的性能特征。

我放置了我的屏幕截图,主要的关键是idis还有什么我可以给你的优化搜索查询吗?我已经尝试过实现groupwise max,但我是认真的:任何帮助都将非常感谢:哦,我看到了斗争。看起来这个链接很难涵盖。我之前看到一条评论,现在被删除了,关于想要添加日期范围检查,但当时我无法回复。如果要为日期范围检查添加WHERE条件,我建议在子查询中这样做。顺便说一句,任何ORDER BY都应该是主查询的一部分,将其添加到子查询中通常是无效的。我还需要具有最新时间戳且满足这些条件的行,为了进一步澄清,请阅读NB1。通过添加第54行和第55行,我更改了示例表。@3kstc请告诉我是否我错了,但这在技术上是否等同于对于给定的mid、sid对可能有两个完全相同的maxv,但记录到具有不同时间戳的表中?这是正确的。。。id是唯一的,因为它是主键。对于给定的mid、sid对,我们可以将类似maxid的内容用于对应的maxv。@3kstc请检查编辑。如果表的索引正确,则希望修改后的查询能够在合理的时间内产生预期的结果。