SQL Server 2008 上的查询优化

Posted

技术标签:

【中文标题】SQL Server 2008 上的查询优化【英文标题】:Query Optimization on SQL server 2008 【发布时间】:2015-05-26 08:32:56 【问题描述】:

我有一个在 SQL Server 2008 上运行的小型 sql 查询。它使用以下表格及其行数:

dbo.date_master - 245424
dbo.ers_hh_forecast_consumption - 436061472
dbo.ers_hh_forecast_file - 15105
dbo.ers_ed_supply_point - 8485

我对 SQL Server 世界很陌生,并且正在学习。请指导我如何优化此查询以更快地运行。

如果有人可以提及我的错误以及我正在做的事情导致查询结果表需要很长时间,我将非常高兴。

WITH CTE_CONS AS
(
    SELECT T2.CONVERTED_DATE
          ,T1.FORECAST_FILE_ID
          ,SUM(T1.FORECAST_CONSUMPTION) AS TOTAL
    FROM dbo.ers_hh_forecast_consumption AS T1
    LEFT JOIN dbo.date_master AS T2 ON T1.UTC_DATETIME=T2.STRDATETIME
    WHERE T2.CONVERTED_DATE>='2015-01-01' AND T2.CONVERTED_DATE<='2015-06-01'
    GROUP BY T2.CONVERTED_DATE, T1.FORECAST_FILE_ID, T1.FORECAST_CONSUMPTION
),
CTE_MPAN AS
(
    SELECT T2.FORECAST_FILE_ID
          ,T2.MPAN_CORE
    FROM CTE_CONS AS T1
    LEFT JOIN dbo.ers_hh_forecast_file AS T2 ON T1.FORECAST_FILE_ID=T2.FORECAST_FILE_ID
),
CTE_GSP AS
(
    SELECT T2.MPAN_CORE
          ,T2.GSP_GROUP_ID
    FROM CTE_MPAN AS T1
    LEFT JOIN dbo.ers_ed_supply_point AS T2 ON T1.MPAN_CORE=T2.MPAN_CORE
)

SELECT T1.CONVERTED_DATE
      ,T1.TOTAL
      ,T2.MPAN_CORE
      ,T1.TOTAL
FROM CTE_CONS AS T1
LEFT JOIN CTE_MPAN AS T2 ON T1.FORECAST_FILE_ID=T2.FORECAST_FILE_ID
LEFT JOIN CTE_GSP AS T3 ON T2.MPAN_CORE=T3.MPAN_CORE

【问题讨论】:

由于表“ers_hh_forecast_consumption”有大量记录,最好使用过滤条件将需要的记录插入到临时表中,并在CTE中使用该临时表。 您在任何表上是否有任何索引,例如预测消耗表的UTC_DATETIME 上的索引。显示表定义和索引将帮助您得到一个体面的答案。 当我们不知道存在哪些索引时,很难给出建议。同时,您可以使用 SSMS 查看查询的执行计划以识别优化。 【参考方案1】:

基本上,如果不查看实际的表设计和索引,就很难准确说出您需要更改的所有内容。但对于初学者,您绝对可以考虑两件事:

    在您的CTE_CONS 查询中,您正在对Datetime 字段进行左连接。除非您在该字段上有某种索引,否则这绝对不是一个好主意。如果还没有索引,我强烈建议您创建索引。

    CREATE NONCLUSTERED INDEX IX_UTC_DATETIME ON dbo.ers_hh_forecast_consumption 
    (UTC_DATETIME ASC) INCLUDE (
     FORECAST_FILE_ID
    ,FORECAST_CONSUMPTION
     );
    

    您可以考虑做的另一件事是将您的表分区dbo.ers_hh_forecast_consumption。这样一来,您在表格上的读取就会少得多,并且检索记录也变得更快。这是How To Decide if You Should Use Table Partitioning.的快速指南

希望这会有所帮助!

【讨论】:

感谢新秀。我会尝试两个。【参考方案2】:

除了您需要提供更多信息让我们了解正在发生的事情之外,我想我在这里发现您的查询存在一些问题:

WITH CTE_CONS AS
(
    SELECT T2.CONVERTED_DATE
          ,T1.FORECAST_FILE_ID
          ,SUM(T1.FORECAST_CONSUMPTION) AS TOTAL
    FROM dbo.ers_hh_forecast_consumption AS T1
    LEFT JOIN dbo.date_master AS T2 ON T1.UTC_DATETIME=T2.STRDATETIME
    WHERE T2.CONVERTED_DATE>='2015-01-01' AND T2.CONVERTED_DATE<='2015-06-01'
    GROUP BY T2.CONVERTED_DATE, T1.FORECAST_FILE_ID, T1.FORECAST_CONSUMPTION
)

第一次尝试SUM() T1.FORECAST_CONSUMPTION 每个T2.CONVERTED_DATE ,T1.FORECAST_FILE_ID 组合的值。但是,在GROUP BY 中您还添加了T1.FORECAST_CONSUMPTION 吗?这将与在三个字段上执行DISTINCT 具有完全相同的效果。要么从GROUP BY 中删除你正在使用SUM() 的字段,要么使用DISTINCT 并去掉SUM()GROUP BY;取决于你追求什么效果。

无论如何,您能否在您的问题中添加以下内容:

EXEC sp_helpindex &lt;table_name&gt; 用于所有涉及的表。 如果可能,请提供Execution Plan 的屏幕截图(来自 SSMS 或 SQL Sentry Plan Explorer)。

【讨论】:

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

优化 SQL Server 2008 查询

sql server 2000/2008 查询优化

SQL Server 2008 R2:优化查询性能

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

SQL Server调优系列基础篇(联合运算符总结)

SQL Server调优系列基础篇