T-SQL 优化

Kev*_*3NF 3 performance sql-server sql-server-2014 query-performance

如果答案是“不”,我可以接受...

我想看看这是否可以优化......它是更大的存储过程的一部分。CGCode是 varchar(50),Year并且MonthsmallintFEINchar(9)

select max(id)
from Table
where 1=1
    and cgcode = 123
    and datefromparts(cast(year as char(4)),cast(month as char(2)),'01') < getdate()
    and totalcount > 0 
group by cgcode, year, month, fein
Run Code Online (Sandbox Code Playgroud)

实际执行计划的逻辑读取:1,566,473

源表原始数据 3200万+条记录

估计行数:640K,实际 55K,在 Group By 开始之前

上的隐式转换警告Year/Month/CGCode(作为bigint

执行时间大约为 7.5 秒,执行非聚集索引查找:

在此处输入图片说明

最终结果集是 114 行(为此,CGCode我们测试...其他各不相同)

Prod 的性能在比 Dev box 明显更好的硬件上大致相同。随着时间的推移,这只会变得更糟,因为它会提取比当前月份更旧的所有内容,以在 UI 中填充历史图表。

我还能提供哪些其他信息?

粘贴计划

当前使用的索引:

CREATE NONCLUSTERED INDEX [COIX_Table_TotalCount] ON [dbo].[Table]
(
    [TotalCount] ASC
)
INCLUDE (   [ID],
    [CGCode],
    [Year],
    [Month],
    [FEIN]) 
WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, SORT_IN_TEMPDB = OFF, DROP_EXISTING = OFF, 
        ONLINE = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
GO
Run Code Online (Sandbox Code Playgroud)

CGCode限制数据最多...281 个值。 year只有 3-4 年的数据,month当然只有 12 个选项。 TotalCountbigint3200 万条记录中的 17K 个不同值。不知道TotalCount列的目的是什么。

ype*_*eᵀᴹ 8

首先,我会重写这个条件。事实上,它不能有效地使用任何索引。:

datefromparts(cast(year as char(4)),cast(month as char(2)),'01') < getdate()
Run Code Online (Sandbox Code Playgroud)

重写它,以便没有应用于列的函数或计算:

 ( year < year(getdate()) 
or year = year(getdate()) and month <= month(getdate())
 )
Run Code Online (Sandbox Code Playgroud)

考虑到零件,重写将允许使用索引(cgcode, year, month)- 或者甚至更好的索引。(cgcode, year, month, fein)GROUP BY

接下来,如果totalcount始终是WHERE子句的一部分或totalcount > 0始终使用特定条件,则可以通过将其添加到INCLUDE部分或使用更有针对性的过滤索引来提高效率:

-- option A
index (cgcode, year, month, fein, id) 
      include (totalcount)

-- option B
index (cgcode, year, month, fein, id)
      where (totalcount > 0)
Run Code Online (Sandbox Code Playgroud)