2

在表'ttraces'中,我有许多不同任务的记录(其值保存在'taskid'列中,并且是表'ttasks'中列'id'的外键)。每个任务每 8-10 秒插入一条记录到“ttraces”,因此缓存数据以提高性能并不是一个好主意。我需要的是从'ttraces'中只为每个任务选择最新的记录,这意味着'time'列的最大值的记录。目前,我的表中有超过 500000 条记录。这两个表的非常简化的结构如下所示:

-----------------------
|       ttasks        |
-----------------------
| id | name | blocked |
-----------------------

---------------------
|      ttraces       |
---------------------
| id | taskid | time |
---------------------

我的查询如下所示:

SELECT t.name,tr.time
FROM 
    ttraces tr 
    JOIN 
    ttasks t ON tr.itask = t.id 
    JOIN (
        SELECT taskid, MAX(time) AS max_time
        FROM ttraces 
        GROUP BY itask
    ) x ON tr.taskid = x.taskid AND tr.time = x.max_time
WHERE t.blocked

WHERE 和 JOIN 子句中使用的所有列都有索引。至于现在查询运行〜1,5秒。提高它的速度是非常关键的。感谢所有建议。顺便说一句:数据库在托管的共享服务器上运行,目前我无法将其移动到其他任何地方。

[编辑] EXPLAIN SELECT... 结果是:

--------------------------------------------------------------------------------------------------------------
id   select_type   table        type     possible_keys   key       key_len   ref          rows     Extra
--------------------------------------------------------------------------------------------------------------
1   PRIMARY        <derived2>   ALL      NULL            NULL      NULL      NULL         74   
1   PRIMARY        t            eq_ref   PRIMARY         PRIMARY   4         x.taskid     1        Using where
1   PRIMARY        tr           ref      taskid,time     time      9         x.max_time   1        Using where
2   DERIVED        ttraces      index    NULL            itask     5         NULL         570853   
--------------------------------------------------------------------------------------------------------------

引擎是 InnoDB。

4

4 回答 4

1

我可能有一点时间,但是这个查询在逻辑上是否不一样,并且(几乎可以肯定)更快?

SELECT t.id, t.name,max(tr.time)
FROM 
ttraces tr 
JOIN 
ttasks t ON tr.itask = t.id 
where BLOCKED
group by t.id, t.name
于 2012-09-26T12:32:22.623 回答
0

Here's my idea... You need one composite index on ttraces having taskid and time columns (in that order). Than, use this query:

SELECT t.name,
       trm.mtime
FROM   ttasks AS t
       JOIN (SELECT taskid,
                    Max(time) AS mtime
             FROM   ttraces
             GROUP  BY taskid) AS trm
         ON t.id = trm.taskid
WHERE  t.blocked 
于 2012-09-26T11:31:35.660 回答
0

如果每个任务有很多跟踪,那么您可以保留一个仅包含最新跟踪的表。每当你插入到 ttraces 中时,你也插入到 ttraces_newest 中:

insert into ttraces_newest (id, taskid, time) values
(3, 1, '2012-01-01 08:02:01')
on duplicate key update
`time` = current_timestamp

ttraces_newest 的主键是 (id, taskid)。查询 ttraces_newest 会更便宜。便宜多少取决于每个任务有多少跟踪。现在查询是:

SELECT t.name,tr.time
FROM 
    ttraces_newest tr 
    JOIN 
    ttasks t ON tr.itask = t.id 
WHERE t.blocked
于 2012-09-26T11:24:08.733 回答
0

此代码是否返回正确的结果?如果是这样,它的速度时间如何?

SELECT t.name, max_time 
FROM ttasks t JOIN ( 
    SELECT taskid, MAX(time) AS max_time 
    FROM ttraces  
    GROUP BY taskid
) x ON t.id = x.taskid
于 2012-09-26T11:33:05.553 回答