使用join

时间:2015-08-24 12:33:13

标签: mysql

我遇到了一些性能问题,我认为可以通过更好的查询来解决。

MySQL表现在有33,000个条目,具有以下方案: ID - kompID(外键) - 时间(时间戳) - amountIO - amountNIO - status0 - .... - status8

每隔几秒钟就会插入一个类似上面的新报告,并在超过5天时删除它们。

出于监控目的,我需要为每个kompID提供最新的条目。这是因为我在Stackoverflow上找到了一个加入的想法:

SELECT 
     r1.kompID As ID, 
     (SELECT Name 
         FROM Komponenten 
         WHERE Komponenten.KompID = ID) 
         AS Name,
     r1.time, 
     r1.status0, 
     ...
     FROM Reports r1 
     LEFT JOIN Reports r2 
        ON (r1.kompID = r2.kompID AND r1.RepID < r2.RepID)
     WHERE r2.RepID IS NULL;

它可以工作,但是对于完整的数据库,查询需要150秒(在1 vCore上)。我可以增加内核,但我想了解可以做得更好的内容。

输出如下:

ID  Name    time                 status0    ....

1   470-U1  2015-08-24 14:00:30     2   ...

2   420-C   2015-08-24 14:00:33     0   ...

如果没有任何更快的查询,我也可以先选择所有的ComponentID,然后为每个选择最新的条目激发一个新的查询。

提前感谢您的帮助。

编辑: SQL结构

-- phpMyAdmin SQL Dump
-- version 4.0.10deb1
-- http://www.phpmyadmin.net
--
-- Host: localhost
-- Erstellungszeit: 24. Aug 2015 um 16:19
-- Server Version: 5.5.44-0ubuntu0.14.04.1
-- PHP-Version: 5.5.9-1ubuntu4.11

SET SQL_MODE = "NO_AUTO_VALUE_ON_ZERO";
SET time_zone = "+00:00";


/*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT */;
/*!40101 SET @OLD_CHARACTER_SET_RESULTS=@@CHARACTER_SET_RESULTS */;
/*!40101 SET @OLD_COLLATION_CONNECTION=@@COLLATION_CONNECTION */;
/*!40101 SET NAMES utf8 */;

--
-- Datenbank: `AMS`
--

-- --------------------------------------------------------

--
-- Tabellenstruktur für Tabelle `Reports`
--

CREATE TABLE IF NOT EXISTS `Reports` (
  `RepID` int(11) NOT NULL AUTO_INCREMENT,
  `kompID` int(11) NOT NULL,
  `time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
  `AnzahlIO` int(11) NOT NULL DEFAULT '0',
  `AnzahlNIO` int(11) NOT NULL DEFAULT '0',
  `status0` int(11) NOT NULL,
  `status1` int(11) NOT NULL DEFAULT '0',
  `status2` int(11) NOT NULL DEFAULT '0',
  `status3` int(11) NOT NULL DEFAULT '0',
  `status4` int(11) NOT NULL DEFAULT '0',
  `status5` int(11) DEFAULT '0',
  `status6` int(11) NOT NULL DEFAULT '0',
  `status7` int(11) NOT NULL DEFAULT '0',
  PRIMARY KEY (`RepID`),
  KEY `FK_KomponentID` (`kompID`)
) ENGINE=InnoDB  DEFAULT CHARSET=latin1 AUTO_INCREMENT=53447 ;

--
-- Constraints der exportierten Tabellen
--

--
-- Constraints der Tabelle `Reports`
--
ALTER TABLE `Reports`
  ADD CONSTRAINT `FK_KomponentID` FOREIGN KEY (`kompID`) REFERENCES `Komponenten` (`KompID`);

DELIMITER $$
--
-- Ereignisse
--
CREATE DEFINER=`root`@`%` EVENT `AutoDeleteOldReports` ON SCHEDULE EVERY 1 DAY STARTS '2015-08-10 10:46:57' ON COMPLETION PRESERVE ENABLE COMMENT 'Reports > 5Tage löschen' DO DELETE LOW_PRIORITY FROM AMS.Reports WHERE time < DATE_SUB(NOW(), INTERVAL 5 DAY)$$

DELIMITER ;

/*!40101 SET CHARACTER_SET_CLIENT=@OLD_CHARACTER_SET_CLIENT */;
/*!40101 SET CHARACTER_SET_RESULTS=@OLD_CHARACTER_SET_RESULTS */;
/*!40101 SET COLLATION_CONNECTION=@OLD_COLLATION_CONNECTION */;

小提琴链接在这里: http://sqlfiddle.com/#!9/9ed73(我希望它能像那样工作)

解释声明: id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY r1 ALL NULL NULL NULL NULL 34560
1 PRIMARY r2 ref PRIMARY,FK_KomponentID FK_KomponentID 4 AMS.r1.kompID 16969 Using where; Using index; Not exists 2 DEPENDENT SUBQUERY Komponenten eq_ref PRIMARY PRIMARY 4 func 1

2 个答案:

答案 0 :(得分:1)

好的,我刚刚注意到解决方案非常简单:

SELECT 
(SELECT Name AS Name FROM Komponenten k1 WHERE k1.KompID = r0.kompID), 
time, 
AnzahlIO, 
AnzahlNIO, 
status0 
FROM 
(SELECT * FROM Reports ORDER BY RepID DESC) r0 
GROUP BY kompID  

因此,只需选择反向repID(带自动增量的主键),然后选择此项并按kompID分组。 像这样我们有0.001秒的运行时间。

非常感谢您的投入!

答案 1 :(得分:0)

使用此查询,您可以获得每个kompID的最新条目:

select * from Reports r0 where r0.kompID in (
select r1.kompID from (
select r1.kompID, max(time)
from Reports r1
group by r1.kompID ) );

“查询核心”显然如下:

select r1.kompID, max(time)
    from Reports r1
    group by r1.kompID

简单地按kompID分组,并为每个不同的kompID显示最大日期的那个。

希望我帮助过你!