無法弄清楚為什麼我的查詢如此緩慢
我有一個查詢需要 15 秒才能在 MySQL 5.6 伺服器中獲得 350 個結果,但我無法診斷原因,我對數據庫優化仍然很陌生。ü
EXPLAIN 視覺確實顯示了一些非唯一的鍵查找,但每個僅表示一個 1 行查找。
我無法解釋的表格解釋,我希望其他人可以在這裡看起來像。
我嘗試將結尾切換為 100、10
LIMIT = 350
和 1,並且查詢的執行時間完全相同,大約 15 秒。我曾嘗試取消視圖,但除了使重新創建此查詢變得困難之外,它並沒有提高性能。
也許相關,在我們的 MySQL 數據庫中的其他 EXPLAIN 語句中,我看到了一個在它旁邊引用了 Materialized 的視圖,但它並沒有出現在這個查詢中使用的三個視圖中的任何一個旁邊,事實上我什至沒有查看完全引用的視圖,而不是僅查看它們引用的表。這是一個因素嗎?
我的最後一次嘗試是用
listlineitems.*
特定的列替換最終選定的列,因為我讀過這可以提高速度並且只是更好的做法,但我覺得不會顯著改善這種情況。這是查詢 -
SELECT 0 AS 'Check', DATE_FORMAT(`listlineitems`.`dateEntered`, '%Y-%m-%d') AS 'Date Entered', `listlineitems`.`itemId` AS 'parentTableIdx', `listlineitems`.`parentProjectId` AS 'parentProjectIdx', `listlineitems`.`idx` AS 'ID', IF(`listlineitems`.`active` = 1, 'Active', 'Inactive') AS 'Active/Inactive', CONCAT(`listUsers`.`FirstName`, ' ', `listUsers`.`LastName`) AS 'Employee', CASE `listlineitems`.`type` WHEN 1 THEN 'Time Entry' WHEN 2 THEN 'Expense Entry' END AS 'Type', `listcustomers`.`name` AS 'Customer', `listlocations`.`name` AS 'Location', `listareas`.`name` AS 'Area', `listassets`.`name` AS 'Asset', `listprojects`.`name` AS 'Project', `listprojects`.`number` 'Project #', `listprojects`.`autoassign` 'autoassign', `listactivities`.`name` AS 'Activity', (CASE `listlineitems`.`type` WHEN 1 THEN `listlineitems`.`qty` WHEN 2 THEN `listlineitems`.`qty` END) AS 'Quantity', `listlineitems`.`taxable` AS 'Taxable', `listlineitems`.`totalAmount` - `listlineitems`.`taxAmount` AS 'Pre-Tax Amount', `listlineitems`.`taxAmount` AS 'Tax Amount', `listlineitems`.`totalAmount` AS 'Total Amount', `listCustomers`.`idx` AS 'parentCustomerIdx', `listLocations`.`idx` AS 'parentLocationIdx', `listAreas`.`idx` AS 'parentAreaIdx', `listAssets`.`idx` AS 'parentAssetIdx', CONCAT(`listcustomers`.`name`, '/', `listlocations`.`name`, '/', `listareas`.`name`, '/', `listassets`.`name`, '/', `listprojects`.`name`) AS 'Path', IF(`listlineitems`.`customerViewable` = 1, 'Yes', 'No') AS 'Cust. Viewable', (CASE WHEN `listlineitems`.`type` = 2 THEN `listexpenseentry`.`TotalCostToPSI` - `listexpenseentry`.`TaxCostToPSI` ELSE `listlineitems`.`totalAmount` - `listlineitems`.`taxAmount` END) AS 'preTaxCostPSI', (CASE WHEN `listlineitems`.`type` = 2 THEN `listexpenseentry`.`TaxCostToPSI` ELSE `listlineitems`.`taxAmount` END) AS 'taxCostPSI', (CASE WHEN `listlineitems`.`type` = 2 THEN `listexpenseentry`.`TotalCostToPSI` ELSE `listlineitems`.`totalAmount` END) AS 'totalCostPSI', view_solinx2.lastAltered AS 'lastalteredSO', view_polinx2.lastAlteredPO AS 'lastalteredPO', view_invlinx2.lastAlteredInv AS 'lastalteredInv', view_solinx2.lastAlteredAfterConfirmation AS 'lastAlteredAfterConfirmation', view_solinx2.roleIdSO AS 'roleIdSO', view_polinx2.roleIdPO AS 'roleIdPO', view_polinx2.userIdPO AS 'userIdPO', view_polinx2.lastAlteredafterConfirmation AS 'lastAlteredAfterConfirmationPO', view_invlinx2.roleIdInv AS 'roleIdInv', view_invlinx2.userIdInv AS 'userIdInv', view_invlinx2.lastAlteredafterConfirmation AS 'lastAlteredAfterConfirmationInv', view_solinx2.roleId AS 'roleId', view_solinx2.userId AS 'userId', view_solinx2.soId AS 'SOId', view_solinx2.autoassignSO AS 'autoassignSO', IF(view_solinx2.notNeeded = 1, 'Not Needed', view_solinx2.number) AS 'SOname', view_solinx2.dateEntered AS 'SoDate', view_solinx2.totalSOAmount AS 'SoTotal', view_invlinx2.invId AS 'InvId', IF(view_solinx2.notNeeded = 1, '------', view_invlinx2.`number`) AS 'InvName', view_invlinx2.dateEntered AS 'InvDate', view_invlinx2.amount AS 'InvTotal', view_polinx2.poId AS 'POId', IF(view_solinx2.notNeeded = 1, '------', view_polinx2.`number`) AS 'POName', view_polinx2.dateEntered AS 'PODate', view_polinx2.amount AS 'POTotal', (SELECT listsalesorders.number FROM listsalesorders WHERE listsalesorders.idx = autoassign) AS 'test', `listlineitems`.* FROM `listlineitems` LEFT JOIN `listUsers` ON `listlineitems`.`individualId` = `listUsers`.`idx` LEFT JOIN `listprojects` ON `listlineitems`.`parentProjectId` = `listprojects`.`idx` LEFT JOIN `listassets` ON `listlineitems`.`parentAssetId` = `listassets`.`idx` LEFT JOIN `listareas` ON `listlineitems`.`parentAreaId` = `listareas`.`idx` LEFT JOIN `listlocations` ON `listlineitems`.`parentLocationId` = `listlocations`.`idx` LEFT JOIN `listcustomers` ON `listlineitems`.`parentCustomerId` = `listcustomers`.`idx` LEFT JOIN `listactivities` ON `listactivities`.`idx` = `listlineitems`.`activityCode` LEFT JOIN `listexpenseentry` ON (`listexpenseentry`.`idx` = `listlineitems`.`itemId` AND `listlineitems`.`type` = 2) LEFT JOIN view_solinx2 ON view_solinx2.idx = listlineitems.idx LEFT JOIN view_polinx2 ON view_polinx2.idx = listlineitems.idx LEFT JOIN view_invlinx2 ON view_invlinx2.idx = listlineitems.idx GROUP BY `listlineitems`.`idx` ORDER BY `listlineitems`.`dateEntered` DESC LIMIT 10;
附加資訊:有客戶、位置、區域、資產、項目、dateEntered、itemId、lineitemtype 和其他一些我認為未使用的索引(它們是連接中未使用的列,如果我忽略索引為他們?)。
此外,如果知道有用的話,項目的客戶有他們自己的聯繫。項目有一個資產外鍵,資產有一個區域外鍵,區域有一個位置外鍵,位置有一個客戶外鍵,都是多對一的(一個客戶有很多位置,一個位置有很多區域等)。
非常感謝任何建議或攻擊計劃/要尋找的內容。有關數據庫結構的任何其他問題,請詢問。我已經為此工作了兩天,但沒有找到任何地方。
將評論變成答案……
首先:不同
LIMIT
的 s 幾乎沒有什麼變化是因為,所有收集和排序數據的艱苦工作都必須在應用限制之前完成。為了找到資源消耗的來源:
- 刪除
ORDER BY
(only) 和 (then)LEFT
從所有s中刪除JOIN
(一次一個)。- 檢查效果。
- (因為沒有使用聚合函式)考慮刪除
GROUP BY
(並可能使用 aWHERE
代替)。如果需要調整/進一步詳細資訊,請發表評論。