Mysql 优化从销售表中购买的每个客户的选择产品详细信息
我有4张桌子、客户、产品、销售和销售项目。我使用下面的查询从中提取数据Mysql 优化从销售表中购买的每个客户的选择产品详细信息,mysql,sql,performance,select,Mysql,Sql,Performance,Select,我有4张桌子、客户、产品、销售和销售项目。我使用下面的查询从中提取数据 SELECT ( SELECT c.name FROM Customers c WHERE s.customer_id=c.id ) customer ,( Select group_concat(description) FROM ( SELECT si.id
SELECT (
SELECT c.name
FROM Customers c
WHERE s.customer_id=c.id
) customer
,(
Select group_concat(description)
FROM (
SELECT si.id
,si.sale_id
,concat("x", si.Qty, " ", p.name, " ",(si.total)) description
FROM Sale_Items si
LEFT JOIN Products p ON p.id = si.product_id
) p
where s.id = Sale_ID
GROUP BY Sale_ID
) detail,
s.total
FROM Sales s
查询生成结果,但速度变慢,只有2000条记录(完成需要114秒)
我怎样才能使它更快
在这里进行了一次尝试
如果我们想继续使用相关子查询,我们可以取消内联视图
p
对于从Sales
检索到的每一行,这都将具体化。外部查询中WHERE
子句中的谓词不会被“推”到视图中。因此,物化视图(或MySQL术语中的“派生表”)将是一个完整的集合,我们将从中挑选出几行。我们将在Sales
中的每一行重复这一点
解开这个派生表应该会给我们带来一些性能上的好处。对于从Sales
返回的少量行,这是一种合理的方法,并定义了合适的索引。也就是说,如果我们使用WHERE
子句限制外部查询检查的行数。对于大量的行,这些相关的子查询将降低性能
SELECT ( SELECT c.name
FROM Customers c
WHERE c.id = s.customer_id
) AS customer
, ( SELECT GROUP_CONCAT(CONCAT('x',si.Qty,' ',p.name,' ',si.total) ORDER BY p.name SEPARATOR '\r\n')
FROM Sale_Items si
LEFT
JOIN Products p
ON p.id = si.product_id
WHERE si.sale_id = s.id
) AS detail
, s.total
FROM Sales s
WHERE ...
ORDER
BY ...
如果查询返回来自Sales
的所有行,并且我们正在执行整个bloomin集,那么我倾向于避免相关子查询。(这是因为外部查询返回的每一行都会执行子查询。就性能而言,这些子查询将吃掉我们的午餐,因为返回了大量行。)
假设id
在customers
中是唯一的,我们通常使用连接操作会更好
SELECT c.name AS customer
, d.detail
, s.total
FROM Sales s
LEFT
JOIN Customers c
ON c.id = s.customer_id
LEFT
JOIN ( SELECT si.sale_id
, GROUP_CONCAT(CONCAT('x',si.Qty,' ',p.name,' ',si.total) ORDER BY p.name SEPARATOR '\r\n') AS detail
FROM Sale_Items si
LEFT
JOIN Products p
ON p.id = si.product_id
GROUP
BY si.sale_id
) d
ON d.sale_id = s.id
ORDER
BY ...
内联视图
d
对于大型集合来说会很昂贵;但至少我们只做了一次查询,将结果具体化为一个“派生表”。然后可以运行外部查询,并从派生表中检索行。考虑处理应用程序代码中的数据显示问题。我怀疑生成的查询会更简单、更快。当我们为销售返回的每一行执行内联视图时,实现内联视图p
的成本会很高。外部查询中的谓词不会被推送到视图定义中(这可能在较新版本的MySQL中有所改变)。
SELECT c.name AS customer
, d.detail
, s.total
FROM Sales s
LEFT
JOIN Customers c
ON c.id = s.customer_id
LEFT
JOIN ( SELECT si.sale_id
, GROUP_CONCAT(CONCAT('x',si.Qty,' ',p.name,' ',si.total) ORDER BY p.name SEPARATOR '\r\n') AS detail
FROM Sale_Items si
LEFT
JOIN Products p
ON p.id = si.product_id
GROUP
BY si.sale_id
) d
ON d.sale_id = s.id
ORDER
BY ...