如何对巨大的表进行连接查询?

时间:2011-03-16 14:25:34

标签: mysql

希望有人可以帮我解决这个问题。我需要列出下面ngr_titles的所有200条记录,并加入ngr_monitordata中最新的相关记录。 ngr_monitordata中的外键称为titleid,最新值应为每个标题的较高when_posted值。 问题是ngr_monitordata包含数百万条记录并且每秒都在增加。

这是我使用的查询,但执行需要14秒:

SELECT * FROM ngr_titles
LEFT JOIN 
(SELECT titleid, MAX(when_posted) FROM ngr_monitordata GROUP BY titleid) tmp1
ON ngr_titles.id= tmp1.titleid;

最好的方法是什么?

表格是:

CREATE TABLE `ngr_titles` (
  `id` int(11) NOT NULL auto_increment,
  `title` varchar(255) default NULL,
  `drop_min` int(11) NOT NULL default '50',
  `warn_pcnt` float(5,1) NOT NULL default '15.0',
  `crit_pcnt` float(5,1) NOT NULL default '25.0',
  `deviations` float(5,1) NOT NULL default '2.0',
  `addlobby` int(2) NOT NULL default '0',
  `url` varchar(255) default NULL,
  `graph_url` varchar(255) default NULL,
  `lastchecked` int(11) NOT NULL default '0',
  `last_exception` int(11) default NULL,
  `state` enum('ok','warning','critical') default NULL,
  `trend` int(11) NOT NULL default '0',
  `short_name` varchar(45) NOT NULL,
  `historical` varchar(45) NOT NULL,
  `cacti_url` varchar(255) default NULL,
  PRIMARY KEY  (`id`),
  UNIQUE KEY `title` (`title`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;



CREATE TABLE `ngr_monitordata` (
  `id` int(11) NOT NULL auto_increment,
  `titleid` int(11) default NULL,
  `when_posted` int(11) default NULL,
  `games_completed` int(11) default NULL,
  `games_created` int(11) default NULL,
  `games_in_progress` int(11) default NULL,
  `games_in_progress_gps` int(11) default NULL,
  `users_in_games` int(11) default NULL,
  `users_in_games_gps` int(11) default NULL,
  `users_in_lobby` int(11) default NULL,
  `users_in_passive` int(11) default NULL,
  `users_in_rooms` int(11) default NULL,
  `rooms` int(11) default NULL,
  `state` enum('ok','warning','critical','unknown') NOT NULL default 'ok',
  `user_drop` int(11) NOT NULL default '0',
  `retries` int(8) default NULL,
  PRIMARY KEY  (`id`),
  UNIQUE KEY `whowhenidx` (`titleid`,`when_posted`),
  KEY `whenidx` (`when_posted`),
  KEY `titleidx` (`titleid`),
  KEY `stateidx` (`state`)
) ENGINE=MyISAM AUTO_INCREMENT=120512615 DEFAULT CHARSET=utf8;

3 个答案:

答案 0 :(得分:1)

尽可能不要使用内部查询。它会很慢。

SELECT ngr_titles.*, MAX(ngr_monitordata.when_posted) as when_posted
    FROM ngr_titles
    LEFT JOIN ngr_monitordata 
    ON ngr_titles.id = ngr_monitordata.titleid 
    GROUP BY ngr_titles.id

编辑:仅当两个表的大小相同时才适用。

答案 1 :(得分:0)

SELECT 
    t.*
FROM 
    ngr_titles t 
INNER JOIN 
ngr_monitordata m
    ON 
t.id = m.titleid 
    AND 
m.when_posted = (SELECT MAX(when_posted) FROM ngr_monitordata WHERE titleid = t.id)

快速解决方案,它应该可以工作,虽然我是在急速写的。如果是我,我会稍微规范化数据,以减少聚合函数和子查询的开销。

答案 2 :(得分:-1)

尝试为以下列ngr_monitordata添加(titleid ASC, when_posted DESC)的索引。