簡體   English   中英

什么索引可以提高 JOIN 和 GROUP BY 的性能

[英]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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM