use*_*794 2 mysql indexing performance group-by query-performance
我已经设置了一些表并运行了查询。然而,在我的解释中,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`)
)
Run Code Online (Sandbox Code Playgroud)
购物车分割数据
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`)
)
Run Code Online (Sandbox Code Playgroud)
我的示例查询
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
Run Code Online (Sandbox Code Playgroud)
专家提示避免在性能敏感的查询中使用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。
EXPLAIN 输出中出现的专业提示 Using temporary; using filesort并不一定是坏事。它只是意味着查询引擎必须在返回部分结果集之前对其进行缓存。这个temporary东西不是一个实际的表,而是一个 RAM 结构。如果它太大以至于淹没了 RAM,MySQL 会将其溢出到磁盘。但你的不是。
话虽如此,让我们重构您的查询。我猜你想检索idCartDATA每个行中具有最大值的行CartSplitData.SUPPLIERID。
因此,让我们将其写为子查询。
SELECT max(IDCartDATA) AS IDCartDATA, SUPPLIERID
FROM CartSplitData
GROUP BY SUPPLIERID
Run Code Online (Sandbox Code Playgroud)
通过在 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'
Run Code Online (Sandbox Code Playgroud)
您的索引CartData.CartOrderref将有助于此外部查询,创建的复合索引也将有所帮助^^^。