AskOverflow.Dev

AskOverflow.Dev Logo AskOverflow.Dev Logo

AskOverflow.Dev Navigation

  • 主页
  • 系统&网络
  • Ubuntu
  • Unix
  • DBA
  • Computer
  • Coding
  • LangChain

Mobile menu

Close
  • 主页
  • 系统&网络
    • 最新
    • 热门
    • 标签
  • Ubuntu
    • 最新
    • 热门
    • 标签
  • Unix
    • 最新
    • 标签
  • DBA
    • 最新
    • 标签
  • Computer
    • 最新
    • 标签
  • Coding
    • 最新
    • 标签
主页 / dba / 问题 / 176296
Accepted
Kevin3NF
Kevin3NF
Asked: 2017-06-15 09:48:05 +0800 CST2017-06-15 09:48:05 +0800 CST 2017-06-15 09:48:05 +0800 CST

T-SQL 优化

  • 772

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

我正在查看是否可以对其进行任何优化...它是更大的存储过程的一部分。CGCode是 varchar(50),Year并且Month是smallint,FEIN是char(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

实际执行计划的逻辑读取: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

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

sql-server sql-server-2014
  • 3 3 个回答
  • 161 Views

3 个回答

  • Voted
  1. Best Answer
    ypercubeᵀᴹ
    2017-06-15T10:06:25+08:002017-06-15T10:06:25+08:00

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

    datefromparts(cast(year as char(4)),cast(month as char(2)),'01') < getdate()
    

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

     ( year < year(getdate()) 
    or year = year(getdate()) and month <= month(getdate())
     )
    

    考虑到这些部分,重写将允许使用索引(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)
    
    • 8
  2. KumarHarsh
    2017-06-16T01:49:40+08:002017-06-16T01:49:40+08:00

    我将从 Group By 中删除 cgcode,因为我知道什么是 cgcode 而它不在范围内。因此删除 cgcode (varchar(60)) 将带来巨大的推动力。

    所以如果我是正确的,我的索引也会改变。

    使用变量代替 getdate()

    declare @CurDate date=getdate()
    declare @yr int=year(@CurDate ) 
    declare @month tinyint=month(@CurDate )
    declare @cg varchar(60)='123'
    
    select @cg cgcode,max(id)
    from Table
    where  cgcode = @cg
        ( year < @yr  
    or [year] = @yr and [month] <= @month
     )
        and totalcount > 0 
    group by year, month, fein
    

    从技术上讲,为什么totalcount will be covering indexAI 不理解选项中的原因,根据该逻辑它应该在索引组内或者option B是正确的。

    • 0
  3. Kevin3NF
    2017-06-21T05:28:13+08:002017-06-21T05:28:13+08:00

    找到了 :)

    clientid 正在作为 INT 传递...导致 CGCode 字段隐式转换为 varchar。

    select max(id)
    from Table
    where 1=1
        and cgcode = CAST(123 as varchar(50))  ---this fixed it
        and datefromparts(cast(year as char(4)),cast(month as char(2)),'01') < getdate()
        and totalcount > 0 
    group by cgcode, year, month, fein
    

    从 7-30 秒到 100 毫秒。我会接受的。

    • 0

相关问题

  • SQL Server - 使用聚集索引时如何存储数据页

  • 我需要为每种类型的查询使用单独的索引,还是一个多列索引可以工作?

  • 什么时候应该使用唯一约束而不是唯一索引?

  • 死锁的主要原因是什么,可以预防吗?

  • 如何确定是否需要或需要索引

Sidebar

Stats

  • 问题 205573
  • 回答 270741
  • 最佳答案 135370
  • 用户 68524
  • 热门
  • 回答
  • Marko Smith

    连接到 PostgreSQL 服务器:致命:主机没有 pg_hba.conf 条目

    • 12 个回答
  • Marko Smith

    如何让sqlplus的输出出现在一行中?

    • 3 个回答
  • Marko Smith

    选择具有最大日期或最晚日期的日期

    • 3 个回答
  • Marko Smith

    如何列出 PostgreSQL 中的所有模式?

    • 4 个回答
  • Marko Smith

    列出指定表的所有列

    • 5 个回答
  • Marko Smith

    如何在不修改我自己的 tnsnames.ora 的情况下使用 sqlplus 连接到位于另一台主机上的 Oracle 数据库

    • 4 个回答
  • Marko Smith

    你如何mysqldump特定的表?

    • 4 个回答
  • Marko Smith

    使用 psql 列出数据库权限

    • 10 个回答
  • Marko Smith

    如何从 PostgreSQL 中的选择查询中将值插入表中?

    • 4 个回答
  • Marko Smith

    如何使用 psql 列出所有数据库和表?

    • 7 个回答
  • Martin Hope
    Jin 连接到 PostgreSQL 服务器:致命:主机没有 pg_hba.conf 条目 2014-12-02 02:54:58 +0800 CST
  • Martin Hope
    Stéphane 如何列出 PostgreSQL 中的所有模式? 2013-04-16 11:19:16 +0800 CST
  • Martin Hope
    Mike Walsh 为什么事务日志不断增长或空间不足? 2012-12-05 18:11:22 +0800 CST
  • Martin Hope
    Stephane Rolland 列出指定表的所有列 2012-08-14 04:44:44 +0800 CST
  • Martin Hope
    haxney MySQL 能否合理地对数十亿行执行查询? 2012-07-03 11:36:13 +0800 CST
  • Martin Hope
    qazwsx 如何监控大型 .sql 文件的导入进度? 2012-05-03 08:54:41 +0800 CST
  • Martin Hope
    markdorison 你如何mysqldump特定的表? 2011-12-17 12:39:37 +0800 CST
  • Martin Hope
    Jonas 如何使用 psql 对 SQL 查询进行计时? 2011-06-04 02:22:54 +0800 CST
  • Martin Hope
    Jonas 如何从 PostgreSQL 中的选择查询中将值插入表中? 2011-05-28 00:33:05 +0800 CST
  • Martin Hope
    Jonas 如何使用 psql 列出所有数据库和表? 2011-02-18 00:45:49 +0800 CST

热门标签

sql-server mysql postgresql sql-server-2014 sql-server-2016 oracle sql-server-2008 database-design query-performance sql-server-2017

Explore

  • 主页
  • 问题
    • 最新
    • 热门
  • 标签
  • 帮助

Footer

AskOverflow.Dev

关于我们

  • 关于我们
  • 联系我们

Legal Stuff

  • Privacy Policy

Language

  • Pt
  • Server
  • Unix

© 2023 AskOverflow.DEV All Rights Reserve