2015-06-26 74 views
1

我做了這個查詢來獲取一些數據。使用連接和「幽靈」引用優化postrgeSQL查詢?

select th.id, th.ticket_id, tp.name AS priority, ts.name AS state, owner_id AS player_id, g.id AS team_id, tt.name AS ticket_type 
from ticket_history th, ticket_priority tp, ticket_state ts, users, queue, ticket_type tt, groups g 
where th.priority_id = tp.id 
AND queue.id = g.id 
AND th.state_id = ts.id 
AND owner_id = users.id 
AND th.queue_id = queue.id 
AND th.type_id = tt.id 
AND th.id > $lastUpdateId 
ORDER BY th.id desc 

它工作得很好,但我得到了一些抱怨說,這個查詢很慢(以下簡稱「投訴人」甚至沒有到,雖然測試)...但我決定與一些內部連接調整它 - 第一個問題:這是連接表的最有效方式,並避免重複主ID(在這種情況下,ticket_history)正確嗎?

我重構查詢看起來像這樣:

select th.id, th.ticket_id, tp.name AS priority, ts.name AS state, owner_id AS player_id, g.id AS team_id, tt.name AS ticket_type 
FROM ticket_history, groups 
INNER JOIN queue ON queue.id = groups.id 
INNER JOIN ticket_priority ON ticket_priority.id = ticket_history.priority_id 
INNER JOIN ticket_state ON ticket_state.id = ticket_history.state_id 
INNER JOIN users ON users.id = ticket_history.owner_id 
INNER JOIN queue ON queue.id = ticket_history.queue_id 
INNER JOIN ticket_type ON ticket_type.id = ticket_history.type_id 
WHERE th.id > 7352616 
ORDER BY th.id desc 

,但現在我得到這讓我想起我的第二個問題的錯誤

ERROR: invalid reference to FROM-clause entry for table "ticket_history" 
LINE 4: ...NER JOIN ticket_priority ON (ticket_priority.id = ticket_his... 
                  ^
HINT: There is an entry for table "ticket_history", but it cannot be referenced from this part of the query. 
********** Error ********** 

ERROR: invalid reference to FROM-clause entry for table "ticket_history" 
SQL state: 42P01 
Hint: There is an entry for table "ticket_history", but it cannot be referenced from this part of the query. 

- 這是什麼意思?我需要引用ticket_history.priority_id ...

PS:我的目標是獲取ticket_history中的數據,但不是擁有priority_id,而是需要實際的優先級文本等等(除了用戶和組我實際上想要他們的ID而不是名稱)。最棘手的部分是我在ticket_history中有一個隊列ID,我需要從隊列表中提取我實際需要的group_id。

編輯:這裏是從第一個查詢

id; ticket_id; priority; state; user_id; group_id; type  
7376618; 203123; "4 Low"; "closed"; 385; 22; "Service Request" 
7376617; 201341; "3 Medium"; "closed"; 100; 21; "Problem" 
7376616; 2; "1 SuperDuperHigh"; "closed"; 150; 10; "Service Request" 

該查詢從本地主機實例返回19067秒(給予或採取)7360行的示例結果。 原始表「原樣」包含id而不是文本/數字。所以它包含「type_id」而不是類型。 group_id是從兩個不同表格之間的關聯中提取的。它去ticket_history-> queue->組因此它需要涉及這些ID的找到GROUP_ID

EDIT2:提供的圖表看起來像這樣(link) - 查找周邊的票表 - 這是最大的一個,你可以看到

+1

從圖中看來,您沒有從「ticket_history」到「queue」,「owner」和「state」的FK。那是對的嗎?加盟時可能會造成巨大的業績損失。你們每個專欄至少有一個索引嗎? – Patrick

+0

@帕特里克也許我連接的圖有點過時了。 ticket_history包含一個queue_id,它引用的那個隊列表包含引用組表的group_id。 – Thaenor

回答

1

我想你不能在那裏引用ticket_history,因爲你在ticket_history和groups之間有逗號,所以ticket_history不是所有這些內部連接的一部分。如果我理解正確你的表結構[如果你發佈的表DEFS和樣本數據會更容易BTW]我認爲這將工作:

select th.id, th.ticket_id, tp.name AS priority, ts.name AS state, owner_id AS player_id, g.id AS team_id, tt.name AS ticket_type 
FROM groups 
INNER JOIN queue ON queue.id = groups.id 
-- include ticket_history with a join statement 
INNER JOIN ticket_history ON queue.id = ticket_history.queue_id 
    INNER JOIN ticket_priority ON ticket_priority.id = 
ticket_history.priority_id 
INNER JOIN ticket_state ON ticket_state.id = ticket_history.state_id 
INNER JOIN users ON users.id = ticket_history.owner_id 

INNER JOIN ticket_type ON ticket_type.id = ticket_history.type_id 
WHERE th.id > 7352616 
ORDER BY th.id desc 
+0

我編輯了問題以包含示例數據。表格圖如下所示(http://ftp.otrs.org/pub/otrs/doc/database-schema/otrs-2.4-database.png) - 查找票單附近的表格 - 這是您可以看到的最大表格。 – Thaenor

3

documentation

連接子句結合了兩個FROM項目,爲了方便起見,我們將 稱爲「表格」,儘管實際上它們可以是任何類型的FROM 項目。如有必要,使用括號來確定嵌套的順序。 在沒有括號的情況下,JOIN從左到右嵌套。 無論如何 JOIN綁定比分隔FROM列表項目的逗號更緊密。

因此,連續的JOIN是相對於「組」而不是「ticket_history」。翻轉表的順序,使其工作:

SELECT th.id, th.ticket_id, tp.name AS priority, ts.name AS state, owner_id AS player_id, 
     g.id AS team_id, tt.name AS ticket_type 
FROM ticket_history th 
JOIN ticket_priority tp ON tp.id = th.priority_id 
JOIN ticket_state ts ON ts.id = th.state_id 
-- JOIN users ON users.id = th.owner_id NOT USED IN THE QUERY 
JOIN queue ON queue.id = th.queue_id 
JOIN ticket_type tt ON tt.id = th.type_id 
JOIN groups g ON g.id = queue.id 
WHERE th.id > 7352616 
ORDER BY th.id DESC; 

注意INNERJOIN之前是沒有用的字;你可以放心地省略它。

+1

即使沒有從表中選擇任何列,用戶表連接是否可能用於限制返回的記錄? (即,如果在ticket_history中沒有對應的users.id中的記錄)。 – mlinth

+1

@mlinth我非常確定優化器在構建查詢計劃時覈對了「用戶」表的引用,對於測試這個問題會很有趣。但即使沒有,這個UoD也會有很多FK和NOT NULL子句。 – Patrick

+0

在我的情況下,如果它們沒有用戶標識,可以省略ticket_history中的行。我不認爲這是發生。這些是OTRS的表格集合,票據管理開放源碼應用程序,我認爲它非常堅實的結構不允許這樣做。 – Thaenor