如何在SQL Sever中进行查询优化?

时间:2017-01-02 12:34:27

标签: sql sql-server sql-server-2012 query-optimization

我正在努力加快执行时间。我的查询有什么问题。什么是更好的查询优化方法。

TransactionEntry有2百万条记录

交易表有50亿条记录

以下是我的查询,如果我删除了 TotalPrice 列,我的结果是 10秒

--Total Quantity
SELECT 
    items.ItemLookupCode,sum(transactionsEntry.Quantity) Quantity,sum(transactionsEntry.Quantity*transactionsEntry.Price) TotalPrice

into 
    ##temp_TotalPrice
FROM
    (
    SELECT 
        TransactionNumber,StoreID,Time
    FROM   
        [HQMatajer].[dbo].[Transaction]
    WHERE 
        Time>=CONVERT(datetime,'2015-01-01 00:00:00',102) and Time<=CONVERT(datetime,'2015-12-31 23:59:59',102)
    ) transactions

left join [HQMatajer].[dbo].[TransactionEntry] transactionsEntry
ON transactionsEntry.TransactionNumber=transactions.TransactionNumber and transactionsEntry.StoreID=transactions.StoreID

Left join [HQMatajer].[dbo].[Item] items
ON transactionsEntry.ItemID=items.ID

Group By items.ItemLookupCode
Order by items.ItemLookupCode

如果我执行此(上面一个)查询,它会在 22秒中生成结果。它太长了

当我单独执行子查询时(下面一个)。这需要11秒

(
SELECT 
    TransactionNumber,StoreID,Time
FROM 
    [HQMatajer].[dbo].[Transaction]
WHERE 
    Time>=CONVERT(datetime,'2015-01-01 00:00:00',102) and Time<=CONVERT(datetime,'2015-12-31 23:59:59',102)
) transactions
  

我为TransactionEntry Table创建了一个

的索引      
      
  1. TransactionNumber,StoreID,ItemID,Quantity,Price
  2.         

    Transaction Table

    的一个索引
    `Time,TransactionNumber,StoreID`
    
         

    Item Table

    的一个索引
    `ID`
    

执行计划 Execution Plan Image

  

TransactionEntry的Clustured Index需要花费59%的成本。该column_Name为AutoID

3 个答案:

答案 0 :(得分:1)

假设这是针对SQL 2005或更高版本的。如果它用于SQL 2000,那么您可以使用具有适当索引的CTE表而不是temp

此外,由于您从[HQMatajer].[dbo].[TransactionEntry][HQMatajer].[dbo].[Item]获取了值,为什么要使用左连接? 避免子查询。我已经重新构建了查询。请检查并告诉我它是否改善了性能

;WITH transactions
AS
(
    SELECT 
        TransactionNumber,StoreID,Time
    FROM   
        [HQMatajer].[dbo].[Transaction]
    WHERE 
        Time>=CONVERT(datetime,'2015-01-01 00:00:00',102) and Time<=CONVERT(datetime,'2015-12-31 23:59:59',102)
)
SELECT 
    items.ItemLookupCode,sum(transactionsEntry.Quantity) Quantity,sum(transactionsEntry.Quantity*transactionsEntry.Price) TotalPrice
into 
    ##temp_TotalPrice
FROM [HQMatajer].[dbo].[Item] items INNER JOIN [HQMatajer].[dbo].[TransactionEntry] transactionsEntry
ON transactionsEntry.ItemID=items.ID
WHERE EXISTS (SELECT 1 FROM transactions WHERE transactionsEntry.TransactionNumber=transactions.TransactionNumber and transactionsEntry.StoreID=transactions.StoreID)
Group By items.ItemLookupCode
Order by items.ItemLookupCode

答案 1 :(得分:1)

这是您的查询,简化并格式化了一点(子查询没有区别):

select i.ItemLookupCode,
       sum(te.Quantity) as quantity,
       sum(te.Quantity * te.Price) as TotalPrice
into ##temp_TotalPrice
from [HQMatajer].[dbo].[Transaction] t left join
     [HQMatajer].[dbo].[TransactionEntry] te
     on te.TransactionNumber = t.TransactionNumber and
        te.StoreID = t.StoreID left join
     [HQMatajer].[dbo].[Item] i
     on te.ItemID = i.ID
where t.Time >= '2015-01-01' and
      t.Time < '2016-01-01'
group by i.ItemLookupCode
order by i.ItemLookupCode;

对于此查询,您需要Transaction(Time, TransactionNumber, StoreId)TransactionEntry(TransactionNumber, StoreId, ItemId, Quantity, Price)和Item(Id,ItemLookupCode)上的索引`。

即使使用正确的索引,这也会处理大量数据,因此如果将时间缩短到几秒钟,我会感到惊讶。

答案 2 :(得分:0)

这个查询花费了很多时间,因为三次将条目插入临时表中会增加时间。如果我们将记录插入另一个表中并将其调用或将其作为cte。它降低了成本。