SQL Server 中的 SQL 查询优化

Posted

技术标签:

【中文标题】SQL Server 中的 SQL 查询优化【英文标题】:SQL query optimization in SQL Server 【发布时间】:2016-12-29 13:43:10 【问题描述】:

在 SQL Server 中,查询执行计划,两个操作(并行和哈希匹配)分别占总成本的 30% 和 45%。

并行和哈希匹配是什么意思?

对于并行度,我检查了on this link 并行度数会影响查询的性能,我如何检查服务器的并行度数是多少?

如何降低这个成本?我不知道如何才能降低此成本。

我的查询返回 4200 万行并连接 5 个表;没有where 条件,没有group byorder by 子句。

我在连接列上有非聚集索引。

我的查询是:

SELECT
    [INV].SKU AS [INV_SKU],
    [INV].LOCATION_ID AS [INV_LOCATION_ID],
    [INV].DATE AS [INV_BALANCE_DATE],
    [INV].COST AS INV_COST,
    [ITEM].ITEM_ID,
    [ITEM].ITEM_NAME,
    [SPITEM].ITEMNumber As SP_ITEMID,
    [SPITEM].NAME,
    [SPITEM_DEPT].[SKEY],
    [SPITEM_DEPT].[DEPT_NAME],
    [Time].[DATE] AS [CAL_DATE],
    [Time].[CAL_NAME] AS [CAL_NAME],
    [Time].[YEAR_NAME] AS [YEAR_NAME],
    [Time].[YEAR_NUM] AS [YEAR_NUM],
    [Time].[YEAR_START_DT] AS [YEAR_START_DT],
    ISNUL(convert(INT, convert(varchar, [Time].[WEEK_END_DT], 112)), 0) AS [WEEK_END_DT_SKEY],
    CASE
       WHEN [ITEM].DEPARTMENT IS NULL
          THEN (CASE 
                   WHEN [SPITEM_DEPT].SPITEM_DEPT_NAME = 'UNSPECIFIED' 
                      THEN 0 
                   ELSE [SPITEM_DEPT].SPITEM_DEPT_NAME 
                END)
       ELSE [ITEM].DEPARTMENT 
    END AS [DEPARTMENTNUM],
    CASE 
       WHEN [ITEM].[DEPARTMENT_DESCRIPTION] IS NULL
          THEN [SPITEM_DEPT].[DESCRIPTION]   
          ELSE [ITEM].[DEPARTMENT_DESCRIPTION] 
    END AS [ITEM_DEPARTMENT_DESC],
    [LOCATION].LOCATION_NAME,
    [LOCATION].COUNTRY,
    [LOCATION].CURRENCY,
    [CURRENCY].BASE_CURRENCY
FROM 
    [dbo].[Table1] [INV]
LEFT JOIN 
    dbo.Table2 AS [ITEM] ON ([INV].SKU = [ITEM].SKU )
LEFT JOIN 
    dbo.Table3 AS [LOCATION] ON ([INV].LOCATION_ID = [LOCATION].LOCATION_ID)
INNER JOIN 
    dbo.Table4 [Time] ON ([INV].DATE = [Time].DATE)
LEFT JOIN 
    dbo.Table5 [SPITEM] ON ([INV].SKU = SPITEM.NAME)
LEFT JOIN 
    [dbo].[Table6] [SPITEM_DEPT] ON ([SPITEM].[WS_KPI_ITEM_MERCHANDISE_DEPARTMENT_SKEY] = [SPITEM_DEPT].[SKEY])
LEFT JOIN 
    [dbo].[Table7] [CURRENCY] ON ([INV].DATE BETWEEN [CURRENCY].BEGIN_DT AND [CURRENCY].END_DT AND [LOCATION].CURRENCY= [CURRENCY].LOCAL_CURRENCY)

我们在连接列上也有非聚集索引。

请提出可能的解决方案,我可以试试。

我是 SQL Server 查询优化的新手。

【问题讨论】:

返回 4200 万行需要花费大量时间,即使查询本身非常快。你应该问问自己你需要这些行来做什么...... 能否提供您查询的执行计划? 使用brentozar.com/pastetheplan分享您的执行计划 不要掉入直接跳到 MAXDOP 的陷阱,过度并行通常是索引问题的症状。 请使用COALESCE()ISNULL() 而不是CASE WHEN ??? IS NULL THEN ... ;)。 【参考方案1】:

行数很大,对我来说,主要问题是你没有任何 where 条件,即使你有索引但没有谓词也是一个糟糕的场景。并行度数由你的DBA设置,表示算子的阈值是并行还是串行。

https://technet.microsoft.com/es-es/library/ms181007%28v=sql.105%29.aspx?f=255&MSPPError=-2147217396

我建议您阅读 Grant Fritchey 的这本关于执行计划的免费书籍: https://www.red-gate.com/library/sql-server-execution-plans-2nd-edition

不过,我的建议是: 1) 在查询中添加过滤器 (Where) 2) 审查您的索引策略

【讨论】:

【参考方案2】:

用这些索引做一些测试(不是一次全部)。

首先关注较大的桌子。

同样在您加入 table7 中尝试将您的 BETWEEN 语句更改为下面的示例

[INV].DATE >= [CURRENCY].BEGIN_DT 
AND 
[INV].DATE <= [CURRENCY].END_DT



CREATE NONCLUSTERED INDEX idx1 ON [dbo].[Table1](SKU)
CREATE NONCLUSTERED INDEX idx2 ON [dbo].[Table1](LOCATION_ID)
CREATE NONCLUSTERED INDEX idx3 ON [dbo].[Table1](DATE) INCLUDE(COST)

CREATE NONCLUSTERED INDEX idx1 ON [dbo].[Table2](SKU) INCLUDE(ITEM_ID,ITEM_NAME,DEPARTMENT,DEPARTMENT_DESCRIPTION)

CREATE NONCLUSTERED INDEX idx1 ON [dbo].[Table3](LOCATION_ID,CURRENCY) INCLUDE(LOCATION_NAME,COUNTRY)

CREATE NONCLUSTERED INDEX idx1 ON [dbo].[Table4](DATE) INCLUDE(CAL_NAME,YEAR_NAME,YEAR_NUM,YEAR_START_DT,WEEK_END_DT)

CREATE NONCLUSTERED INDEX idx1 ON [dbo].[Table5](NAME,WS_KPI_ITEM_MERCHANDISE_DEPARTMENT_SKEY) INCLUDE(ITEMNumber)

CREATE NONCLUSTERED INDEX idx1 ON [dbo].[Table6](SKEY) INCLUDE(DEPT_NAME,SPITEM_DEPT_NAME,DESCRIPTION)

CREATE NONCLUSTERED INDEX idx1 ON [dbo].[Table7](LOCAL_CURRENCY,BEGIN_DT,END_DT) INCLUDE(BASE_CURRENCY)

如果您已经用尽了所有可能的索引选项,那么您始终可以通过在查询的基础上使用 MAXDOP 选项来限制查询使用的处理器数量。 我不喜欢这个,因为你的系统会随着时间而改变,你必须相应地关注它。

有趣的是,如果 HASH MATCH 实际数据与估计数据有很大差异,这可能意味着您的统计数据已过时,您现有的索引需要重建。

【讨论】:

以上是关于SQL Server 中的 SQL 查询优化的主要内容,如果未能解决你的问题,请参考以下文章

SQL Server 中的 SQL 查询优化

WHERE 子句中的 SQL 查询子选择优化 (SQL Server)

SQL Server基础优化

SQL Server调优系列基础篇(并行运算总结)

有关 SQL Server 中的 SQL 查询提示的详细信息

SQL Server 中的查询优化