我有一個包含任務的表的數據庫。任務有一個生命週期。任務生命週期的狀態可能會改變。這些狀態轉換存儲在一個單獨的表tasktransitions中。 現在我寫了一個查詢來查找所有打開/重新打開的任務和最近更改的任務,但我已經看到執行時間變得很長(> 0.5s)的任務數量很少(< 1000)。慢查詢。錯誤的數據庫結構?
任務
+-------------+---------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+-------------+---------+------+-----+---------+----------------+
| taskid | int(11) | NO | PRI | NULL | auto_increment |
| description | text | NO | | NULL | |
+-------------+---------+------+-----+---------+----------------+
Tasktransitions
+------------------+-----------+------+-----+-------------------+----------------+
| Field | Type | Null | Key | Default | Extra |
+------------------+-----------+------+-----+-------------------+----------------+
| tasktransitionid | int(11) | NO | PRI | NULL | auto_increment |
| taskid | int(11) | NO | MUL | NULL | |
| status | int(11) | NO | MUL | NULL | |
| description | text | NO | | NULL | |
| userid | int(11) | NO | | NULL | |
| transitiondate | timestamp | NO | | CURRENT_TIMESTAMP | |
+------------------+-----------+------+-----+-------------------+----------------+
查詢
SELECT tasks.taskid,tasks.description,tasklaststatus.status
FROM tasks
LEFT OUTER JOIN
(
SELECT tasktransitions.taskid,tasktransitions.transitiondate,tasktransitions.status
FROM tasktransitions
INNER JOIN
(
SELECT taskid,MAX(transitiondate) AS lasttransitiondate
FROM tasktransitions
GROUP BY taskid
) AS tasklasttransition ON tasklasttransition.lasttransitiondate=tasktransitions.transitiondate AND tasklasttransition.taskid=tasktransitions.taskid
) AS tasklaststatus ON tasklaststatus.taskid=tasks.taskid
WHERE tasklaststatus.status IS NULL OR tasklaststatus.status=0 or tasklaststatus.transitiondate>'2013-09-01';
更可讀的,上面的查詢的描述性較差版本:
SELECT t.taskid, t.description,ls.status
FROM tasks AS t
LEFT OUTER JOIN
(
SELECT tt.taskid, tt.transitiondate, tt.status
FROM tasktransitions AS tt
INNER JOIN
(
SELECT taskid,MAX(transitiondate) AS transitiondate
FROM tasktransitions
GROUP BY taskid
) AS lt USING (taskid,transitiondate)
) AS ls USING (taskid)
WHERE ls.status IS NULL OR ls.status=0 or ls.transitiondate>'2013-09-01';
我想知道如果數據庫結構是最好的選擇性能明智。可以添加索引幫助嗎?我已經嘗試添加一些,但我沒有看到很大的改進。
+-----------------+------------+----------------+--------------+------------------+-----------+-------------+----------+--------+------+------------+---------+---------------+
| Table | Non_unique | Key_name | Seq_in_index | Column_name | Collation | Cardinality | Sub_part | Packed | Null | Index_type | Comment | Index_comment |
+-----------------+------------+----------------+--------------+------------------+-----------+-------------+----------+--------+------+------------+---------+---------------+
| tasktransitions | 0 | PRIMARY | 1 | tasktransitionid | A | 896 | NULL | NULL | | BTREE | | |
| tasktransitions | 1 | taskid_date_ix | 1 | taskid | A | 896 | NULL | NULL | | BTREE | | |
| tasktransitions | 1 | taskid_date_ix | 2 | transitiondate | A | 896 | NULL | NULL | | BTREE | | |
| tasktransitions | 1 | status_ix | 1 | status | A | 3 | NULL | NULL | | BTREE | | |
+-----------------+------------+----------------+--------------+------------------+-----------+-------------+----------+--------+------+------------+---------+---------------+
其他建議?
澄清 - 目標是選擇所有打開或重新打開或最近更新的任務? – fracz
關於表別名的好處是,它們可以防止SQL走出頁面的RHS。例如,您可以指定'FROM Tasks AS K',然後使用'K.TaskID'而不是'tasks.taskid',更重要的是'FROM TaskTransitions AS T',然後使用'T.TransitionDate'而不是'TaskTransitions .TransitionDate「(您可以根據自己的喜好忽略大小寫)。查詢你必須水平滾動才能看到所說的其他內容是痛苦的。 –
你有沒有試圖將你的查詢分成兩個UNION結果?具體來說,擺脫'LEFT JOIN'來記錄'status = 0或transitiondate>'的記錄。然後將'UNION'轉換爲不存在任務轉換的LEFT JOIN查詢(即'status IS NULL')_第二個查詢應該是一個更簡單的LEFT JOIN,因爲您不需要查找最大(日期)權限嗎?_ – AgRizzo