Mysql查询速度需要50秒

时间:2017-08-21 10:54:02

标签: mysql sql

我有下面的查询需要大约50秒才能运行,有没有办法让它更快?我还没有做任何索引,并会在不久的将来尝试这样做,但我仍然是新的。问题不是使用索引。

   Select stock.StockID As StockID,
  stock.BinLocation As BinLocation,
  stock.StockCode As StockCode,
  stock.Descr As Descr,
  stock.Currency As Currency,
  stock.Notes As Notes,
  stocklocations.Quantity As Quantity,
  stocklocations.SLNID As SLNID,
  stock.ConditionA As ConditionA,
  stocklocationsname.SLN As SLN,
  stock.DateAdded As DateAdded,
  (Case When (stock.Currency = 'Euro') Then (1.05 * stock.unitprice)
    When (stock.Currency = 'GBP') Then (1.24 * stock.unitprice)
    When (stock.Currency = 'USD') Then (1 * stock.unitprice) End) As unitprice,
  stock.DepName As DepName,
  stockhistory.POID As POID,
  stock.POID As POID1,
  stock.PartNumber As PartNumber,
  vender.VendorName As VendorName,
  equiptype.EQName As EQName,
  groupname.Name As Name
From ((((((stock
  Join stocklocations On stock.StockID = stocklocations.StockID)
  Join stocklocationsname On stocklocations.SLNID = stocklocationsname.SLNID)
  Left Join stockhistory On stockhistory.SHID = (Select Min(stockhistory.SHID)
    From stockhistory Where stockhistory.StockID = stock.StockID))
  Left Join po On stockhistory.POID = po.POID)
  Left Join vender On po.Vender = vender.VendorID)
  Left Join equiptype On stock.EquipType = equiptype.EquipTypeID)
  Left Join groupname On stock.GroupNameID = groupname.GroupNameID
Where stocklocations.Quantity > 0 And stock.Status <> 'obsolete'

4 个答案:

答案 0 :(得分:1)

1)删除unuseful()并避免嵌套左连接

2)不要使用左连接中涉及的fo列,因为这种方式变成了内连接

3)而不是subselect尝试使用与stockhistory中的stockid相关的最小值的连接

  Select 
    stock.StockID As StockID,
    stock.BinLocation As BinLocation,
    stock.StockCode As StockCode,
    stock.Descr As Descr,
    stock.Currency As Currency,
    stock.Notes As Notes,
    stocklocations.Quantity As Quantity,
    stocklocations.SLNID As SLNID,
    stock.ConditionA As ConditionA,
    stocklocationsname.SLN As SLN,
    stock.DateAdded As DateAdded,
    Case When stock.Currency = 'Euro' Then 1.05 * stock.unitprice
          When stock.Currency = 'GBP' Then 1.24 * stock.unitprice
          When stock.Currency = 'USD' Then 1 * stock.unitprice End As unitprice,
  stock.DepName As DepName,
  stockhistory.POID As POID,
  stock.POID As POID1,
  stock.PartNumber As PartNumber,
  vender.VendorName As VendorName,
  equiptype.EQName As EQName,
  groupname.Name As Name
From  stock
  Join stocklocations On stock.StockID = stocklocations.StockID 
        and stocklocations.Quantity > 0 
            And stock.Status <> 'obsolete'
  Join stocklocationsname On stocklocations.SLNID = stocklocationsname.SLNID
  Left Join ( 
      Select stockhistory.StockID, Min(stockhistory.SHID)
      From stockhistory 
      group by stockhistory.StockID )  t_h on t_h StockID = stockhistory.StockID
  Left Join po On stockhistory.POID = po.POID
  Left Join vender On po.Vender = vender.VendorID
  Left Join equiptype On stock.EquipType = equiptype.EquipTypeID
  Left Join groupname On stock.GroupNameID = groupname.GroupNameID

确保您对加入

中涉及的表和列也有适当的索引

答案 1 :(得分:1)

您应该在stockhistory.StockID上有一个索引:

ALTER TABLE stockhistory ADD INDEX (StockID);

这应该加快stockhistory上的子查询。或者,由于您正在检索SHID的最小值,因此您也可以在索引中包含该列:

ALTER TABLE stockhistory ADD INDEX (StockID, SHID);

添加索引不会创建任何限制或逻辑约束(唯一索引除外)。但是,正如MySQL文档中8.3 Optimization and Indexes中所述:

  

虽然为查询中使用的每个可能列创建索引很有吸引力,但不必要的索引会浪费空间并浪费时间让MySQL确定要使用的索引。索引还会增加插入,更新和删除的成本,因为必须更新每个索引。您必须找到适当的平衡,以使用最佳索引集实现快速查询。

确定要创建的索引是一门艺术。一个好的开始是使用EXPLAIN调查查询执行情况,如8.8.1 Optimizing Queries with EXPLAIN

中所述

答案 2 :(得分:0)

尝试不使用您在连接和FROM中写入的括号。

Select stock.StockID As StockID,
stock.BinLocation As BinLocation,
stock.StockCode As StockCode,
stock.Descr As Descr,
stock.Currency As Currency,
stock.Notes As Notes,
stocklocations.Quantity As Quantity,
stocklocations.SLNID As SLNID,
stock.ConditionA As ConditionA,
stocklocationsname.SLN As SLN,
stock.DateAdded As DateAdded,
(Case When (stock.Currency = 'Euro') Then (1.05 * stock.unitprice)
  When (stock.Currency = 'GBP') Then (1.24 * stock.unitprice)
  When (stock.Currency = 'USD') Then (1 * stock.unitprice) End) As unitprice,
stock.DepName As DepName,
stockhistory.POID As POID,
stock.POID As POID1,
stock.PartNumber As PartNumber,
vender.VendorName As VendorName,
equiptype.EQName As EQName,
groupname.Name As Name
From stock
Join stocklocations On stock.StockID = stocklocations.StockID
Join stocklocationsname On stocklocations.SLNID = stocklocationsname.SLNID
Left Join stockhistory On stockhistory.SHID = (Select Min(stockhistory.SHID) From stockhistory Where stockhistory.StockID = stock.StockID)
Left Join po On stockhistory.POID = po.POID
Left Join vender On po.Vender = vender.VendorID
Left Join equiptype On stock.EquipType = equiptype.EquipTypeID
Left Join groupname On stock.GroupNameID = groupname.GroupNameID
Where stocklocations.Quantity > 0 And stock.Status <> 'obsolete'

答案 3 :(得分:0)

没有它需要多长时间才能执行?

Left Join stockhistory On stockhistory.SHID = (Select Min(stockhistory.SHID)
    From stockhistory Where stockhistory.StockID = stock.StockID))

如果需要5-6秒,那么您应该将StockID的最小SHID组转换为视图,然后首先加入视图,然后使用stockhistory本身来获取stockhistory.POID