我有两张桌子:
CREATE TABLE IF NOT EXISTS `products` (
`id` int(10) unsigned NOT NULL AUTO_INCREMENT,
`categoryId` int(10) unsigned DEFAULT NULL,
`parentId` int(10) unsigned DEFAULT NULL,
`barcode` varchar(255) DEFAULT NULL,
`code` varchar(255) DEFAULT NULL,
`name` varchar(255) DEFAULT NULL,
PRIMARY KEY (`id`),
KEY `fk_products_product_categories1_idx` (`categoryId`),
KEY `fk_products_products1_idx` (`parentId`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 AUTO_INCREMENT=71521 ;
CREATE TABLE IF NOT EXISTS `inventory` (
`id` int(10) unsigned NOT NULL AUTO_INCREMENT,
`depotId` int(10) unsigned NOT NULL,
`productId` int(10) unsigned NOT NULL,
`remain` int(11) DEFAULT NULL,
`remain2` int(10) unsigned DEFAULT NULL,
`updatedDateTime` datetime DEFAULT NULL,
PRIMARY KEY (`id`),
KEY `fk_inventory_depots1_idx` (`depotId`),
KEY `fk_inventory_products1_idx` (`productId`),
) ENGINE=InnoDB DEFAULT CHARSET=utf8 AUTO_INCREMENT=89291 ;
请帮我优化以下查询(应该添加什么索引来提高性能),查询耗时0.2578秒(MySQL使用索引fk_inventory_depots1_idx),当删除AND i.depotId = 3时查询耗时0.5484秒。 EXPLAIN查询显示Extra:使用where;使用临时;使用filesort
SELECT `p`.* , SUM(i.remain) AS `remain` , SUM(i.remain2) AS `remain2`
FROM `products` AS `p`
LEFT JOIN `inventory` AS `i` ON p.id = i.productId
WHERE remain != 0 AND i.depotId = 3
GROUP BY `p`.`id`
ORDER BY `p`.`id` DESC
LIMIT 50
答案 0 :(得分:0)
语句中使用的sum()
函数会考虑所有行(LIMIT
子句在最后一次计算时无效)。可能导致全表扫描,因为remain
,remain2
的所有值都已汇总
如果您希望获得最新sum()
使用的50 rows
SELECT
`p`.* ,
SUM(i.remain) AS `remain`,
SUM(i.remain2) AS `remain2`
FROM
(
SELECT `p`.*,
i.remain,
i.remain2
FROM
`products` AS `p`
JOIN `inventory` AS `i` ON p.id = i.productId << This should be a JOIN, as remain and depotId belong to inventory
WHERE
remain != 0
AND i.depotId = 3
GROUP BY
`p`.`id`
ORDER BY
`p`.`id` DESC
LIMIT 50 ) as t
答案 1 :(得分:0)
您的查询看起来没问题,但是,您将其作为LEFT-JOIN,但通过使用WHERE,保留!= 0和i.DepotID = 3强制它进入INNER-JOIN。如果你真的打算只有HAD非零剩余数量的条目,那么你没问题。但是,如果您想要库存产品,则必须将查询调整为
SELECT
`p`.* ,
SUM(i.remain) AS `remain` ,
SUM(i.remain2) AS `remain2`
FROM `
products` AS `p`
LEFT JOIN `inventory` AS `i`
ON p.id = i.productId
AND remain != 0
AND i.depotId = 3
GROUP BY
`p`.`id`
ORDER BY
`p`.`id` DESC
LIMIT 50
注意&#34; ON&#34;的细微差别。加入条件。这允许所有产品 - 无论匹配的库存记录如何。现在,那就是说,你现在从所有库存中获取,而不仅仅是你的&#34; DepotID = 3&#34;标准。
为了帮助您建立索引,我唯一建议的是多字段密钥。在这种情况下,您使用表中的大多数字段来表示JOIN或SUM()。如果字段是索引的一部分,则不必返回每条记录的实际数据页。小浪费,但可能会改善你的最终结果。
KEY fk_inventory_multiplefields_idx
(productid,depotid,remaining,remaining2),