我想在大約30,000行的表(history_details)上運行一個查詢,需要連接幾個表(歷史記錄,房間,室友,屬性,listers,學生和管理員)。爲什麼我的MySQL查詢與多聯接如此緩慢?
- 第一次加入歷史表很簡單。
- 只有滿足條件時才應該添加下3個連接(房間,室友,屬性)。在這種情況下,它正在查看history_details表中的listing_type列的值是什麼,並且如果它是適當的值,則應該將該連接添加到查詢中。
之後的3個連接有幾個條件需要滿足才能包含它們,但在這些條件中可能是任何OR條件。
SELECT SQL_CALC_FOUND_ROWS history_details.history_id, history_details.listing_type, history_details.listing_id, history_details.date_added, history_details.field, history_details.before_value, history_details.after_value, history_details.edit_group, history_details.email, history_details.name, history_details.correction_message, history_details.photo_filepath, history.history_message, listers.first_name, listers.last_name, students.first_name, students.last_name, admin.first_name, admin.last_name FROM history_details LEFT JOIN history ON history_details.history_id = history.history_id LEFT JOIN rooms ON history_details.listing_type="room" AND rooms.room_id = history_details.listing_id LEFT JOIN roommates ON history_details.listing_type="roommate" AND roommates.roommate_id = history_details.listing_id LEFT JOIN properties ON history_details.listing_type="property" AND properties.property_id = history_details.listing_id LEFT JOIN listers ON (history_details.listing_type="lister" AND listers.lister_id = history_details.listing_id) OR (history_details.listing_type="property" AND listers.lister_id = properties.lister_id) OR (history_details.listing_type="room" AND rooms.lister_type="lister" AND listers.lister_id = rooms.lister_id) LEFT JOIN students ON (history_details.listing_type="student" AND students.student_id = history_details.listing_id) OR (history_details.listing_type="roommate" AND students.student_id = roommates.student_id) OR (history_details.listing_type="room" AND rooms.lister_type="student" AND students.student_id = rooms.lister_id) LEFT JOIN admin ON history_details.listing_type="admin" AND admin.admin_id = history_details.listing_id LIMIT 0,100
它給我正確的結果,但它正在73秒運行。我添加了索引,但我不確定它們是否被使用。這是它顯示了當我運行使用EXPLAIN SELECT SQL_CALC_FOUND_ROWS ....
這是它顯示了當我運行使用EXPLAIN SELECT ....
這是我加入的各種表的索引解釋說明: history_details
PR operties
客房
室友
你能告訴我,如果正在使用我的索引?另外,如何改進查詢,表格結構或索引以提高速度?
編輯: 感謝阿馬丹的有益建議,它現在運行在147ms而不是73秒之前。這是最終的查詢我最終使用:
SELECT SQL_CALC_FOUND_ROWS
history_details.*,
listers.first_name AS lister_first_name,
listers.last_name AS lister_last_name,
NULL AS student_first_name,
NULL AS student_last_name,
NULL AS admin_first_name,
NULL AS admin_last_name
FROM history_details
LEFT JOIN history
ON history_details.history_id = history.history_id
LEFT JOIN listers
ON listers.lister_id = history_details.listing_id
WHERE history_details.listing_type="lister"
UNION
SELECT history_details.*,
NULL AS lister_first_name,
NULL AS lister_last_name,
students.first_name AS student_first_name,
students.last_name AS student_last_name,
NULL AS admin_first_name,
NULL AS admin_last_name
FROM history_details
LEFT JOIN history
ON history_details.history_id = history.history_id
LEFT JOIN students
ON students.student_id = history_details.listing_id
WHERE history_details.listing_type="student"
UNION
SELECT history_details.*,
listers.first_name AS lister_first_name,
listers.last_name AS lister_last_name,
NULL AS student_first_name,
NULL AS student_last_name,
NULL AS admin_first_name,
NULL AS admin_last_name
FROM history_details
LEFT JOIN history
ON history_details.history_id = history.history_id
LEFT JOIN properties
ON properties.property_id = history_details.listing_id
LEFT JOIN listers
ON listers.lister_id = properties.lister_id
WHERE history_details.listing_type="property"
UNION
SELECT history_details.*,
listers.first_name AS lister_first_name,
listers.last_name AS lister_last_name,
students.first_name AS student_first_name,
students.last_name AS student_last_name,
NULL AS admin_first_name,
NULL AS admin_last_name
FROM history_details
LEFT JOIN history
ON history_details.history_id = history.history_id
LEFT JOIN rooms
ON rooms.room_id = history_details.listing_id
LEFT JOIN listers
ON (rooms.lister_type="lister" AND listers.lister_id = rooms.lister_id)
LEFT JOIN students
ON (rooms.lister_type="student" AND students.student_id = rooms.lister_id)
WHERE history_details.listing_type="room"
UNION
SELECT history_details.*,
NULL AS lister_first_name,
NULL AS lister_last_name,
students.first_name AS student_first_name,
students.last_name AS student_last_name,
NULL AS admin_first_name,
NULL AS admin_last_name
FROM history_details
LEFT JOIN history
ON history_details.history_id = history.history_id
LEFT JOIN roommates
ON roommates.roommate_id = history_details.listing_id
LEFT JOIN students
ON students.student_id = roommates.student_id
WHERE history_details.listing_type="roommate"
UNION
SELECT history_details.*,
NULL AS lister_first_name,
NULL AS lister_last_name,
NULL AS student_first_name,
NULL AS student_last_name,
admin.first_name AS admin_first_name,
admin.last_name AS admin_last_name
FROM history_details
LEFT JOIN history
ON history_details.history_id = history.history_id
LEFT JOIN admin
ON admin.admin_id = history_details.listing_id
WHERE history_details.listing_type="admin"
ORDER BY history_details_id DESC
LIMIT 0,100
什麼'解釋select ....'顯示? – 2014-12-19 08:39:33
你應該在每個案例中看到的第一件事是執行計劃。帶OR條件的 – 2014-12-19 08:41:05
也可以減慢查詢速度。 – Abhijeet 2014-12-19 08:44:40