我有一個查詢選擇節點表,然後加入一個標題表。這是通過首先加入節點ID和標題ID之間的中間表來完成的,這允許前兩個表之間的多對多關係。兩個連接都是內聯的,因此只有具有正確配置和現有標題的節點才被選中。我相信這一切都是乾淨和高效的 - 問題如下:快速查詢選擇不在MySQL的另一個表中的所有記錄
還有第四個表,它爲節點提供了一個簡單的層次結構; node_parents。每行有兩個字段;節點ID和充當該節點的父節點的節點ID(node_id和parent_id)。有些節點沒有在此數據庫中配置子節點(即節點本身未在node_parents表的任何行中標記爲父節點) - 這些是我試圖選擇的節點。
這些無子節點的附加標準是它們有一個特定的標題配置 - 因此子查詢最初從node_titles選擇,然後內部加入node_parents。子查詢也有一個GROUP BY,因爲有些節點是多個節點的父節點,所以它們的node_id將不必要地出現在結果中多次。我還應該指出,正因爲如此,node_parents的主鍵是node_id和parent_id的組合。
查詢:
SELECT `nodes`.`node_id`,
`titles`.`title`
FROM `nodes`
INNER JOIN `node_titles`
ON `nodes`.`node_id` = `node_titles`.`node_id`
INNER JOIN `titles`
ON `node_titles`.`title_id` = `titles`.`title_id`
WHERE `nodes`.`node_id` NOT IN
(
SELECT `node_titles`.`node_id`
FROM `node_titles`
INNER JOIN `node_parents`
ON `node_titles`.`node_id` = `node_parents`.`parent_id`
WHERE `node_titles`.`title_id` = 1
GROUP BY `node_titles`.`node_id`
)
AND `titles`.`title_id` = 1
表尺寸: 節點=〜32000個 node_titles =〜49000個 標題= 3個 node_parents =〜55000
的查詢接受約16分鐘來完成。任何人都可以提供任何指針?我曾嘗試剖析查詢 - 這沒有任何長掛,但它確實重複這個循環什麼好像每次選定行:
| executing | 0.000005 |
| Copying to tmp table | 0.515815 |
| Sorting result | 0.000053 |
| Sending data | 0.000028 |
我也曾嘗試開溝子查詢和使用LEFT JOIN與一個WHERE foo不是NULL,但是這仍然需要很長時間來處理 - 分析器宣稱'複製到tmp表'的時間爲180秒。
最終我懷疑這可能是一個索引問題 - 但無論哪種方式,我都會欣賞不會質疑查詢實現的答案,除非他們正在追求可能的放緩原因(例如,是,標題和節點必須處於多對多關係)。謝謝大家,並提供更多信息!
您當前的查詢只有在定義了'title = 1'(可能沿着其他標題)時纔會選擇無子節點。那是你想達到的目標嗎? – Quassnoi 2011-04-21 11:44:36
@Quassnoi對不起,忘了在主要查詢中包含一個附加的where子句,它應該停止有子節點的節點被選中。 – tjbp 2011-04-21 12:04:24
查看查詢更新。 – Quassnoi 2011-04-21 12:18:42