2

テーブル「ttraces」には、さまざまなタスクの多くのレコードがあります(値は「taskid」列に保持され、テーブル「ttasks」の列「id」の外部キーです)。各タスクは 8 ~ 10 秒ごとに「ttraces」にレコードを挿入するため、パフォーマンスを向上させるためにデータをキャッシュすることはお勧めできません。必要なのは、「ttraces」から各タスクの最新のレコードのみを選択することです。つまり、列「time」の最大値を持つレコードを意味します。現在、テーブルには 500000 を超えるレコードがあります。これら 2 つのテーブルの構造を非常に単純化すると、次のようになります。

-----------------------
|       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

これが私の考えです...あなたは(この順序で)と列をttraces持つ1つの複合インデックスが必要です。より、このクエリを使用します:taskidtime

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 に答える