【问题标题】:What indexes to improve performance of JOIN and GROUP BY什么索引可以提高 JOIN 和 GROUP BY 的性能
【发布时间】:2019-03-30 00:11:12
【问题描述】:

我已经设置了一些表并运行了一个查询。但是,在我的解释中,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`)
)

CartSplitData

    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

查询结果说明

【问题讨论】:

  • 您的查询没有意义。 group byselect 不兼容。
  • @GordonLinoff 是的......我现在可以看到......我的逻辑有缺陷,感谢您发现这一点。
  • 那你为什么不删除这个请求呢?
  • 下面的答案实际上确实达到了我想要的效果,很高兴我没有删除请求!

标签: mysql performance indexing group-by query-performance


【解决方案1】:

专业提示在性能敏感的查询中避免使用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 出现在 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 上的索引将有助于外部查询,创建的复合索引也将有助于 ^^^。

【讨论】:

  • 为了清楚起见,我通常避免使用 .* SELECTS,但在这种情况下我没有因为我很着急。但是,既然我知道它会影响性能,我将从此别名。
  • 非常感谢您提供的完整示例。我会执行你的建议。
猜你喜欢
  • 2018-02-14
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-09-04
相关资源
最近更新 更多