下面是mysql select语句,后跟解释输出。
我尝试过添加我认为合适但没有额外速度的索引。
'explain'输出中有2行突出(id 7和8,行数超过35,000) 。
我认为sql需要重组,但我不知道如何更改它。任何帮助,将不胜感激。
EXPLAIN SELECT wo.JobStatusID
,wo.JobNo
,ql.RackCode
,ql.Description
,c.CustName
,s.ShipDate
,s.Qty
,pl.PrepLocation
,wl.WeldLocation
,line.WeldLine
,pm.Initials
,pqty.ShipTotal
,pqty.POTotal
,po.POCount
,s2.Notes
,bm.UnitQty
,labour.AssemblyLabour
,labour.WeldLabour
,labour.TotalGUTLabour + labour.TotalGUTSetUp / pqty.POTotal AS GUTLabour
,labour.TotalPrepLabour + labour.TotalPrepSetUp / pqty.POTotal AS PrepLabour
,pqty.POTotal
FROM WorkOrders wo
JOIN (
SELECT JobNo
,MasterJobNo AS RelevantJobNo
FROM WorkOrders
WHERE MasterJobNo != 0
UNION
SELECT JobNo
,JobNo AS RelevantJobNo
FROM WorkOrders
WHERE MasterJobNo = 0
) AS r
ON r.JobNo = wo.JobNo
LEFT JOIN QuoteLog ql
ON ql.QuoteID = wo.QuoteID
AND wo.FOCPlayArea = 0
LEFT JOIN Customer c
ON c.CustID = ql.CustID
LEFT JOIN WOSchedule s
ON s.JobNo = wo.JobNo
AND s.ObsoleteInd = 0
LEFT JOIN (
SELECT JobNo
,Notes
FROM WOSchedule
ORDER BY ShipDate DESC
) AS s2
ON s2.JobNo = wo.JobNo
LEFT JOIN PrepLocation pl
ON pl.PrepLocationID = wo.PrepLocationID
LEFT JOIN WeldLocation wl
ON wl.WeldLocationID = wo.WeldLocationID
LEFT JOIN ProgramManager pm
ON pm.ProgramManagerID = wo.ProgramManagerID
LEFT JOIN (
SELECT JobNo
,SUM(POQty) AS POTotal
,SUM(ShipQty) AS ShipTotal
FROM WOOrderDetails wod
JOIN WODetailType wodt
ON wodt.DetailTypeID = wod.DetailTypeID
AND wodt.ReleaseModeID = 1
AND wodt.Inactive = 0
WHERE wod.ObsoleteInd = 0
GROUP BY wod.JobNo
) AS pqty
ON pqty.JobNo = wo.JobNo
LEFT JOIN (
SELECT Jobno
,COUNT(*) AS POCount
FROM WOPOs
GROUP BY JobNo
) AS po
ON po.JobNo = wo.JobNo
LEFT JOIN BOMMaterialList bm
ON bm.JobNo = r.RelevantJobNo
LEFT JOIN WeldLine line
ON wo.WeldLineID = line.WeldLineID
LEFT JOIN (
SELECT x.JobNo
,x.BOMDetailID
,SUM(x.TotalPrepLabour) AS TotalPrepLabour
,SUM(x.TotalPrepSetUp) AS TotalPrepSetUp
,SUM(x.TotalGUTLabour) AS TotalGUTLabour
,SUM(x.TotalGUTSetUp) AS TotalGUTSetUp
,SUM(x.WeldLabour * x.WeldEfficiency) AS WeldLabour
,SUM(AssemblyLabour * AssemblyEfficiency * UnitQty) AS AssemblyLabour
FROM (
SELECT bm.JobNo
,bm.BOMDetailID
,bm.UnitQty
,SUM(bm.UnitQty * pl.HitTime * pl.NoHits * pl.NoMen) AS TotalPrepLabour
,SUM(pl.SetUp) AS TotalPrepSetUp
,SUM(bm.UnitQty * gl.HitTime * gl.NoHits * gl.NoMen) AS TotalGUTLabour
,SUM(gl.SetUp) AS TotalGUTSetUp
,bm.WeldLabour
,bm.WeldEfficiency
,bm.AssemblyLabour
,bm.AssemblyEfficiency
FROM BOMMaterialList bm
LEFT JOIN BOMPrepLabour pl
ON pl.BOMDetailID = bm.BOMDetailID
LEFT JOIN BOMGUTLabour gl
ON gl.BOMDetailID = bm.BOMDetailID
GROUP BY BOMDetailID
) AS x
GROUP BY x.JobNo
) AS labour
ON bm.BOMDetailID = labour.BOMDetailID
WHERE ( wo.JobStatusID = 1
OR wo.JobStatusID = 2
OR wo.JobStatusID = 3
)
GROUP BY wo.JobNo
ORDER BY wo.JobStatusID
,wl.WeldLocation
,line.WeldLine
,wo.JobNo;
id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY <derived2> ALL NULL NULL NULL NULL 1418 "Using temporary; Using filesort"
1 PRIMARY wo eq_ref PRIMARY,IDX_1 PRIMARY 4 r.JobNo 1 "Using where"
1 PRIMARY ql eq_ref PRIMARY PRIMARY 4 sbpdf3_custom014.wo.QuoteID 1
1 PRIMARY c eq_ref PRIMARY PRIMARY 2 sbpdf3_custom014.ql.CustID 1
1 PRIMARY s ref PRIMARY,IDX_2 PRIMARY 4 r.JobNo 28
1 PRIMARY <derived4> ALL NULL NULL NULL NULL 2884
1 PRIMARY pl eq_ref PRIMARY PRIMARY 4 sbpdf3_custom014.wo.PrepLocationID 1
1 PRIMARY wl eq_ref PRIMARY PRIMARY 4 sbpdf3_custom014.wo.WeldLocationID 1
1 PRIMARY pm eq_ref PRIMARY PRIMARY 4 sbpdf3_custom014.wo.ProgramManagerID 1
1 PRIMARY <derived5> ALL NULL NULL NULL NULL 1244
1 PRIMARY <derived6> ALL NULL NULL NULL NULL 1310
1 PRIMARY bm ref IDX1 IDX1 4 r.RelevantJobNo 19
1 PRIMARY line ref PRIMARY PRIMARY 4 sbpdf3_custom014.wo.WeldLineID 1
1 PRIMARY <derived7> ALL NULL NULL NULL NULL 1102
7 DERIVED <derived8> ALL NULL NULL NULL NULL 35736 "Using temporary; Using filesort"
8 DERIVED bm index NULL PRIMARY 4 NULL 35268
8 DERIVED pl ref PRIMARY PRIMARY 4 sbpdf3_custom014.bm.BOMDetailID 1
8 DERIVED gl ref PRIMARY PRIMARY 4 sbpdf3_custom014.bm.BOMDetailID 1
6 DERIVED WOPOs index NULL IDX_1 4 NULL 1804 "Using index"
5 DERIVED wod ref IDX_1 IDX_1 1 1660 "Using where; Using temporary; Using filesort"
5 DERIVED wodt eq_ref PRIMARY PRIMARY 2 sbpdf3_custom014.wod.DetailTypeID 1 "Using where"
4 DERIVED WOSchedule ALL NULL NULL NULL NULL 2884 "Using filesort"
2 DERIVED WorkOrders range IDX_2 IDX_2 4 NULL 15 "Using where; Using index"
3 UNION WorkOrders ref IDX_2 IDX_2 4 689 "Using index"
NULL "UNION RESULT" <union2,3> ALL NULL NULL NULL NULL NULL
答案 0 :(得分:2)
这里有很多东西要看,但我确实发现了这个子查询:
SELECT JobNo
,MasterJobNo AS RelevantJobNo
FROM WorkOrders
WHERE MasterJobNo != 0
UNION
SELECT JobNo
,JobNo AS RelevantJobNo
FROM WorkOrders
WHERE MasterJobNo = 0
我认为可以像这样重写:
SELECT JobNo
,CASE WHEN MasterJobNo != 0
THEN MasterJobNo
ELSE JobNo END AS RelevantJobNo
FROM WorkOrders
一旦我们以这种方式重写它,我们想知道它为什么需要成为子查询,而不是简单地加入表。然后我再看一遍,看到我们已经在查询中使用了这个表,因此我们可以完全消除该连接,并将CASE表达式包含在适当的位置。此外,此表达式仅用于我可以发现的一个位置(连接到BOMMaterialList)。
我也注意到了这个子查询:
SELECT JobNo
,Notes
FROM WOSchedule
ORDER BY ShipDate DESC
我认为我们也可以消除这种情况。当用作派生表时,没有LIMIT的ORDER BY在此处没有任何意义,并且:此表已经包含在另一个地方的查询中。提供此s2
子查询和先前s
表的数据之间的唯一区别是对ObsoleteInd字段的检查,s2
中唯一使用的地方数据是{{1 select子句中的字段。 Notes
表仅用于ShipDate和Qty项的选择列表。
所以我可以告诉我们,这应该会有所改善:
s
可能还有一些其他改进可能,但我怀疑大多数改进都来自检查您的索引使用。