![](/img/trans.png)
[英]Alternative to a self join containing max() and GROUP BY to improve performance
[英]What indexes to improve performance of JOIN and GROUP BY
我已經設置了一些表並運行了一個查詢。 但是,在我的解釋中,SQL 結果會出現在生成的臨時表中(我認為這是因為 GROUP BY)
我添加了一些索引來加速查詢,但想知道是否有辦法停止使用臨時表,是否還有其他方法可以使用索引加快查詢速度?
購物車數據
CREATE TABLE `cartdata` (
`IDCartData` INT(11) NOT NULL AUTO_INCREMENT,
`CartOrderref` VARCHAR(25) NOT NULL DEFAULT '',
`UserID` INT(11) NOT NULL DEFAULT '0',
`LastUpdate` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE
CURRENT_TIMESTAMP,
`ManualContactName` VARCHAR(100) NOT NULL DEFAULT '',
`ManualOrderConfirmationEmail` VARCHAR(100) NOT NULL DEFAULT '',
PRIMARY KEY (`IDCartData`),
INDEX `CartOrderref` (`CartOrderref`)
)
購物車拆分數據
CREATE TABLE `cartsplitdata` (
`IDCartSupplierData` INT(11) NOT NULL AUTO_INCREMENT,
`IDCartData` INT(11) NOT NULL DEFAULT '0',
`supplierid` INT(11) NOT NULL DEFAULT '0',
`DeliveryDate` DATE NOT NULL DEFAULT '2000-01-01',
`AccountNumber` VARCHAR(50) NOT NULL DEFAULT '',
`ManualOrderref` VARCHAR(50) NOT NULL DEFAULT '',
`lastupdate` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
PRIMARY KEY (`IDCartSupplierData`),
INDEX `cartdatasupplierid` (`IDCartData`, `supplierid`)
)
我的示例查詢
EXPLAIN SELECT max(CartData.idCartDATA) AS idCartDATA , CartData.*, CartSplitData.*
FROM CartData
JOIN CartSplitData ON CartSplitData.IDCartDATA = CartDATA.IDCartData
WHERE CartData.CartOrderref = 'XXXXXXXXX'
group by CartSplitData.SUPPLIERID
專業提示避免在性能敏感查詢中使用SELECT *
或SELECT table.*
。 而是按名稱選擇您實際需要使用的列
專業提示MySQL 對GROUP BY
有一個臭名昭著的非標准擴展,您正在使用它,並且可能被濫用。 讀這個。 https://dev.mysql.com/doc/refman/8.0/en/group-by-handling.html如果您遵循第一個專業提示,那么遵循第二個會容易得多。
專業提示避免“投入”大量單列索引,以期加速您的查詢。 相反,創建索引,通常是復合索引,以滿足您實際查詢的需要。 閱讀此https://use-the-index-luke.com 。
專業提示Using temporary; using filesort
Using temporary; using filesort
出現在 EXPLAIN 輸出中的文件排序不一定是壞事。 它只是意味着查詢引擎必須在返回之前緩存部分結果集。 temporary
東西不是一個實際的表,它是一個 RAM 結構。 如果它太大以至於淹沒 RAM,MySQL 會將其溢出到磁盤。 但你的不是。
說了這么多,讓我們重構您的查詢。 我猜您想為每個CartSplitData.SUPPLIERID
檢索具有最大idCartDATA
值的行。
所以讓我們把它寫成一個子查詢。
SELECT max(IDCartDATA) AS IDCartDATA, SUPPLIERID
FROM CartSplitData
GROUP BY SUPPLIERID
通過在 CartSplitData: (SUPPLIERID, IDCartDATA)
上放置復合索引,可以顯着加快此查詢的速度。
接下來,讓我們重寫您的主查詢以查找與該子查詢中的 id 匹配的行。
SELECT CartData.* /* * hammers performance */
CartSplitData.* /* * hammers performance */
FROM CartData
JOIN CartSplitData ON CartSplitData.IDCartDATA = CartDATA.IDCartData
JOIN (
SELECT max(IDCartDATA) AS IDCartDATA, SUPPLIERID
FROM CartSplitData
GROUP BY SUPPLIERID
)x ON x.SUPPLIERID = CartSplitData.SUPPLIERID
AND x.IDCartData = CartSplitData.IDCartData
WHERE CartData.CartOrderref = 'XXXXXXXXX'
您在CartData.CartOrderref
上的CartData.CartOrderref
將有助於此外部查詢,創建的復合索引也是如此 ^^^。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.