【问题标题】:How to do Query optimization in SQL Sever?如何在 SQL Server 中进行查询优化?
【发布时间】:2017-05-16 13:37:53
【问题描述】:

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

TransactionEntry 有 200 万条记录

事务表有 50 亿条记录

这是我的查询,如果我删除 TotalPrice 列,我会在 10sec

得到结果
--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

Transaction Table 的一个索引

`Time,TransactionNumber,StoreID`

Item Table 的一个索引

`ID`

执行计划

TransactionEntry 的聚集索引需要 59% 的成本。那个 column_Name 是AutoID

【问题讨论】:

  • 在哪种数据库中,Transaction 的行数是 TransactionEntry 的 2,500 倍?
  • @GordonLinoff 来自Transaction Table 的一个交易号将在TransactionEntry 中拥有许多产品。

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


【解决方案1】:

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

此外,既然您从[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

【讨论】:

  • 子查询与 CTE 对查询性能没有任何影响。
  • 同意。但根据他的评论,子查询不会影响性能。
  • @GopakumarN.Kurup 您的查询没有任何区别。在我更改了 Abishek 提到的索引后,它在 22 秒内执行。当我运行您的查询时,它需要 32 秒。
【解决方案2】:

这是您的查询,经过简化和格式化(子查询没有区别):

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) 上建立索引。

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

【讨论】:

  • 不明白为什么我们需要 LEFT JOIN 在这里。那有什么用呢?
  • @GordonLinoff 数量和价格不是来自 ITEM 表。我必须从 Transaction Entry 表中执行Quantity * Price。那么为什么要在 ITEM 中创建数量和价格的索引呢?
  • @Gordon Linoff - 关于建议的索引我有一些疑问,以下建议的索引与您建议的索引TransactionEntry(TransactionNumber, StoreId, ItemId) INCLUDE(Quantity,Price)Item(ID) INCLUDE (ItemLookupCode) 是否有任何不同。另外我猜Item 上的索引建议可能有问题。
  • @Abhishek 您的索引是正确的。在我创建之后。它在 22 秒内执行。但我还需要一点。
  • @Abhishek 。 . .你是对的。我的列在错误的表中。您可以include select 中的列或将它们用作键。
【解决方案3】:

这个查询花费了很多时间,因为该条目被插入到临时表中的三倍,这增加了时间。如果我们将记录插入到另一个表中,然后调用它或将其设置为 cte。它降低了成本。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2013-08-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-07-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多