复杂的Max语句MySQL

时间:2019-02-14 04:39:08

标签: mysql sql query-optimization

我只有一个查询,可从MySQL数据库获取 10个最大值。它返回了正确的值,但是问题是,获取该值花了很长时间

此值是来自设备的CPU数据。因此,从单个设备中获取大约 6个模块类型。每个模块类型都有大约 120个模块编号。每个模块号都有 2个插槽(活动和备用)。模块号放置在子架中。我需要获取具有最高价值的 10个模块编号

我尝试使用自己的查询,它返回了正确的值,但是插槽不正确。然后我从堆栈溢出(MySQL query, MAX() + GROUP BY)中找到了一个查询

这是我的表格结构:

Create Table: CREATE TABLE `Router_Modul_CPU` (
  `date_id` date NOT NULL,
  `hour_id` time NOT NULL,
  `NE` varchar(50) NOT NULL,
  `modul_number` int(11) NOT NULL,
  `modul_type` varchar(50) NOT NULL,
  `slot` int(11) NOT NULL,
  `subrack` int(11) DEFAULT NULL,
  `mean_memory` float DEFAULT NULL,
  `peak_memory` float DEFAULT NULL,
  PRIMARY KEY (`date_id`,`hour_id`,`NE`,`modul_number`,`modul_type`,`slot`),
  KEY `index_key` (`date_id`,`hour_id`,`NE`,`modul_number`,`modul_type`,`slot`,`subrack`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1

这是我的查询

select
    Router_Modul_CPU.NE,
    Router_Modul_CPU.modul_number,
    Router_Modul_CPU.slot,
    Router_Modul_CPU.subrack
from Router_Modul_CPU
inner join
(
    select modul_number, max(peak_memory) as maks
    from `Router_Modul_CPU`
    group by modul_number, NE, subrack
) maxt on
   (Router_Modul_CPU.modul_number = maxt.modul_number and
    Router_Modul_CPU.peak_memory = maxt.maks)
 where modul_type='SPU' and NE='R-D5-SBT' and date_id='2019-02-14'
limit 10

获取数据大约需要 40-50秒,而这些查询仅查询一台设备

所有这些数据每5分钟插入一次此表。现在此表有大约2500万行。

我的表是否需要调优,或者有什么建议可以提高查询效率?

谢谢

1 个答案:

答案 0 :(得分:3)

您当前的查询存在几个问题。首先,子查询中的GROUP BY子句没有多大意义。其次,在外部查询中使用LIMIT而不使用ORDER BY,这也是没有意义的。我建议使用以下版本:

SELECT
    r1.NE,
    r1.modul_number,
    r1.slot,
    r1.subrack
FROM Router_Modul_CPU r1
INNER JOIN
(
    SELECT modul_number, MAX(peak_memory) AS maks
    FROM Router_Modul_CPU
    GROUP BY modul_number
) r2
    ON r1.modul_number = r2.modul_number AND
       r1.peak_memory = r2.maks
WHERE
    r1.modul_type = 'SPU' AND
    r1.NE = 'R-D5-SBT'    AND
    r1.date_id = '2019-02-14'

我已经省略了LIMIT子句,如果您想使用一个子句,那么还必须提供一个ORDER BY子句。

关于如何使其更好地执行,一种方法是将以下索引添加到Router_Model_CPU表中:

CREATE INDEX your_idx ON Router_Model_CPU (modul_number, peak_memory);

有了这个索引,MySQL可能会选择加入它而不是当前的子查询。该索引应该可以使用,因为子查询只要求每个组peak_memory的最大值。