广告
返回顶部
首页 > 资讯 > 数据库 >SQL Server一次SQL调优案例
  • 375
分享到

SQL Server一次SQL调优案例

2024-04-02 19:04:59 375人浏览 独家记忆
摘要

环境:Microsoft SQL Server 2016 (SP2-CU3)企业版 问题sql: select  RowNumber = ROW_NUMBER()

环境:Microsoft SQL Server 2016 (SP2-CU3)企业版

问题sql

select 
	RowNumber = ROW_NUMBER() OVER 
	( 
		-- This ordering is from the various Fulfillment Map sort orders to match the fulfillment app's row order.
		ORDER BY 
			htly.LicenseYear, 
			mht.Name, 
			h.HuntFirstOpenDate, 
			h.DisplayOrder,
			h.HuntCode,
			ci_orderby.LastName,
			ci_orderby.FirstName,
			fmu.FulfillmentMailingUnitID
	),
	ShippingName = ISNULL(fism_aot.ShippingName,  dbo.udf_GetCustomerName(c.CustomerID)),
	FulfillmentMailingUnitID = fmu.FulfillmentMailingUnitID,
	GoID = goid.IdentityValue,
	MailingZip = ISNULL(fism_zc.ZipCode, zc.ZipCode),
	TransactionID = fism_th.TransactionID,
	TransactionHeaderID = fism_th.TransactionHeaderID,
	HuntDate = h.HuntFirstOpenDate,
	HuntCode = h.HuntCode,
	-- Header info
	BatchNumber = fmulg.FulfillmentMailingUnitLockGroupID,
	PrintedByUserName = au.UserName,
	LockedDate = fmulg.LockedDate
from
	dbo.FulfillmentMailingUnitLockGroup fmulg
	cross join dbo.Enum_IdentityType eit
	cross join dbo.Enum_LicenseActionType elat
	inner join dbo.FulfillmentMailingUnitLock fmul
		on fmulg.FulfillmentMailingUnitLockGroupID = fmul.FulfillmentMailingUnitLockGroupID
	inner join dbo.FulfillmentMailingUnit fmu
		on fmul.LockedFulfillmentMailingUnitID = fmu.FulfillmentMailingUnitID
	inner join dbo.ApplicationUser au
		on fmulg.LockedByApplicationUserID = au.ApplicationUserID
	-- Getting to the Transaction Header by FulfillmentInternetSalesMap OR FulfillmentDrawIssuanceMap
	left join dbo.FulfillmentInternetSalesMap fism
		on fmu.FulfillmentMailingUnitID = fism.FulfillmentMailingUnitID
	left join dbo.FulfillmentDrawIssuanceMap fdim
		on fmu.FulfillmentMailingUnitID = fdim.FulfillmentMailingUnitID
		left join dbo.TransactionHeader th	
			on fism.TransactionHeaderID = th.TransactionHeaderID
				or fdim.TransactionHeaderID = th.TransactionHeaderID
	left join dbo.TransactionHeader fdim_th
		on fdim.TransactionHeaderID = fdim_th.TransactionHeaderID
	-- Getting to License from FulfillmentDrawNotificationMap
	left join dbo.FulfillmentDrawNotificationMap fdnm
		on fmu.FulfillmentMailingUnitID = fdnm.FulfillmentMailingUnitID
		left join dbo.DrawTicketLicense fdnm_dtl
			on fdnm.DrawTicketLicenseID = fdnm_dtl.DrawTicketLicenseID 
		left join dbo.License fdnm_l
			on fdnm_dtl.LicenseID = fdnm_l.LicenseID
		left join dbo.DrawTicket fdnm_dt
			on fdnm_dtl.DrawTicketID = fdnm_dt.DrawTicketID
		left join dbo.DrawTicketHuntChoice fdnm_dthc
			on 
				fdnm_dt.DrawTicketID = fdnm_dthc.DrawTicketID
				and
				(
					-- If the draw ticket is a winner, link to the hunt choice that won.
					(fdnm_dt.WasDrawn = 1 and fdnm_dthc.WasDrawn = 1)
					-- Else if the draw ticket was not a winner, link to the first hunt choice since
					-- Losing and Alternate notifications are not valid for multi-choice hunts
					or (fdnm_dt.WasDrawn = 0 and fdnm_dthc.OrderIndex = 1)
				)
		left join dbo.TransactionDetail fdim_td
			on fdim.TransactionHeaderID = fdim_td.TransactionHeaderID
		left join dbo.LicenseAction fdim_la
			on fdim_td.TransactionDetailID = fdim_la.TransactionDetailID
				-- This might be silly since it should only be Issued for issuance... (currently it's sold in the stored proc that issues tags)
				and (fdim_la.LicenseActionTypeID = elat.Sold or fdim_la.LicenseActionTypeID = elat.Issued or fdim_la.LicenseActionTypeID = elat.Duplicated)
		left join dbo.License fdim_l
			on fdim_la.LicenseID = fdim_l.LicenseID
		
		left join dbo.Hunt h
			on fdnm_dthc.HuntID = h.HuntID
				or fdim_l.HuntID = h.HuntID
		left join dbo.HuntTypeLicenseYear htly
			on h.HuntTypeLicenseYearID = htly.HuntTypeLicenseYearID
		left join dbo.MasterHuntType mht
			on htly.MasterHuntTypeID = mht.MasterHuntTypeID
	left join dbo.Customer c
		on fdnm_l.CustomerID = c.CustomerID
			or th.CustomerID = c.CustomerID
	left join dbo.CustomerIndividual ci
		on c.CustomerID = ci.CustomerID
	left join dbo.CustomerIdentity goid
		on c.CustomerID = goid.CustomerID
			and goid.IdentityTypeID = eit.GOID
			and goid.[Status] = 1
	left join dbo.AddressDetail ad
		on c.MailingAddressID = ad.AddressID
			and ad.IsActive = 1
	left join dbo.ZipCode zc
		on ad.ZipCodeID = zc.ZipCodeID
	left join dbo.CustomerIndividual ci_orderby
		on fdnm_l.CustomerID = ci_orderby.CustomerID
			or fdim_th.CustomerID = ci_orderby.CustomerID
	
	left join dbo.TransactionHeader fism_th	
		on fism.TransactionHeaderID = fism_th.TransactionHeaderID
	left join dbo.ActiveOutdoorsTransaction fism_aot
		on fism_aot.TransactionID = fism_th.TransactionID
	left join dbo.AddressDetail fism_ad 
		on fism_aot.ShippingAddressID = fism_ad.AddressID
			and fism_ad.IsActive = 1
	left join dbo.ZipCode fism_zc
		on fism_ad.ZipCodeID = fism_zc.ZipCodeID
	where
		fmulg.FulfillmentMailingUnitLockGroupID = @FulfillmentMailingUnitLockGroupID

该SQL执行192s后出记录,分析一下sql的执行计划:

分析一:

最终的排序消耗了大量的cost:

SQL Server一次SQL调优案例

分析二:

该SQL存在大量多表连接,MSSQL引擎由于统计信息的算法单一,在处理大量级联连接时,实际数据可能严重偏离统计信息

连接中存在Actual Rows和Estimated Rows严重不一致的情况,随着连接表数目增加,该不一致更加严重:

SQL Server一次SQL调优案例

经过分析,优化的目标是减少多表连接的统计信息不一致导致的执行计划错误并且对最终的排序操作进行外推。

优化的手法主要是利用临时表固化统计信息,外推排序:

最终优化SQL:

select 
	fmu.FulfillmentMailingUnitID
	,elat.Sold
	,elat.Issued
	,elat.Duplicated
	,fmulg.FulfillmentMailingUnitLockGroupID
	,au.UserName
	,fmulg.LockedDate
	,eit.GOID
	into #temp
	from 
	dbo.FulfillmentMailingUnitLockGroup fmulg
	cross join dbo.Enum_IdentityType eit
	cross join dbo.Enum_LicenseActionType elat
	inner join dbo.FulfillmentMailingUnitLock fmul
		on fmulg.FulfillmentMailingUnitLockGroupID = fmul.FulfillmentMailingUnitLockGroupID
	inner join dbo.FulfillmentMailingUnit fmu
		on fmul.LockedFulfillmentMailingUnitID = fmu.FulfillmentMailingUnitID
	inner join dbo.ApplicationUser au
		on fmulg.LockedByApplicationUserID = au.ApplicationUserID
	where
		fmulg.FulfillmentMailingUnitLockGroupID = @FulfillmentMailingUnitLockGroupID
	select 
		fdnm_l.CustomerID fdnm_l_CustomerID,
		th.CustomerID th_CustomerID,
		fdim_th.CustomerID fdim_th_CustomerID,
		t.FulfillmentMailingUnitID,
		h.HuntFirstOpenDate,
		h.HuntCode,
		t.FulfillmentMailingUnitLockGroupID,
		t.UserName,
		LockedDate,
		t.GOID,
		htly.LicenseYear, 
		mht.Name, 
		h.DisplayOrder,
		--ci_orderby.LastName,
		--ci_orderby.FirstName,
		fism.TransactionHeaderID
		into #temp1
		from #temp t
	
		-- Getting to the Transaction Header by FulfillmentInternetSalesMap OR FulfillmentDrawIssuanceMap
		left join dbo.FulfillmentInternetSalesMap fism
			on t.FulfillmentMailingUnitID = fism.FulfillmentMailingUnitID
		left join dbo.FulfillmentDrawIssuanceMap fdim
			on t.FulfillmentMailingUnitID = fdim.FulfillmentMailingUnitID
		left join dbo.TransactionHeader th	
			on fism.TransactionHeaderID = th.TransactionHeaderID
				or fdim.TransactionHeaderID = th.TransactionHeaderID
		left join dbo.TransactionHeader fdim_th
			on fdim.TransactionHeaderID = fdim_th.TransactionHeaderID
		-- Getting to License from FulfillmentDrawNotificationMap
		left join dbo.FulfillmentDrawNotificationMap fdnm
			on t.FulfillmentMailingUnitID = fdnm.FulfillmentMailingUnitID
		left join dbo.DrawTicketLicense fdnm_dtl
			on fdnm.DrawTicketLicenseID = fdnm_dtl.DrawTicketLicenseID 
		left join dbo.License fdnm_l
			on fdnm_dtl.LicenseID = fdnm_l.LicenseID
		left join dbo.DrawTicket fdnm_dt
			on fdnm_dtl.DrawTicketID = fdnm_dt.DrawTicketID
		left join dbo.DrawTicketHuntChoice fdnm_dthc
			on 
				fdnm_dt.DrawTicketID = fdnm_dthc.DrawTicketID
				and
				(
					-- If the draw ticket is a winner, link to the hunt choice that won.
					(fdnm_dt.WasDrawn = 1 and fdnm_dthc.WasDrawn = 1)
					-- Else if the draw ticket was not a winner, link to the first hunt choice since
					-- Losing and Alternate notifications are not valid for multi-choice hunts
					or (fdnm_dt.WasDrawn = 0 and fdnm_dthc.OrderIndex = 1)
				)
		left join dbo.TransactionDetail fdim_td
			on fdim.TransactionHeaderID = fdim_td.TransactionHeaderID
		left join dbo.LicenseAction fdim_la
			on fdim_td.TransactionDetailID = fdim_la.TransactionDetailID
				-- This might be silly since it should only be Issued for issuance... (currently it's sold in the stored proc that issues tags)
				and (fdim_la.LicenseActionTypeID = t.Sold or fdim_la.LicenseActionTypeID = t.Issued or fdim_la.LicenseActionTypeID = t.Duplicated)
		left join dbo.License fdim_l
			on fdim_la.LicenseID = fdim_l.LicenseID
	
		left join dbo.Hunt h
			on fdnm_dthc.HuntID = h.HuntID
				or fdim_l.HuntID = h.HuntID
		left join dbo.HuntTypeLicenseYear htly
			on h.HuntTypeLicenseYearID = htly.HuntTypeLicenseYearID
		left join dbo.MasterHuntType mht
			on htly.MasterHuntTypeID = mht.MasterHuntTypeID
	--set statistics io on
	--set statistics time on
	select 
		t1.LicenseYear,
		t1.Name, 
		t1.DisplayOrder,
		c.CustomerID,
		t1.FulfillmentMailingUnitID,
		t1.GOID,
		zc.ZipCode,
		t1.HuntFirstOpenDate,
		t1.HuntCode,
		t1.FulfillmentMailingUnitLockGroupID,
		t1.UserName,
		t1.LockedDate,
		t1.fdnm_l_CustomerID,
		t1.fdim_th_CustomerID,
		t1.TransactionHeaderID
	 into #temp2
	 from #temp1 t1
	
		-- Getting to Cusotmer from the joined transaction header or the license from the DrawTicketLicense
		left join dbo.Customer c
			on t1.fdnm_l_CustomerID = c.CustomerID
				or t1.th_CustomerID = c.CustomerID
		left join dbo.CustomerIndividual ci
			on c.CustomerID = ci.CustomerID
		
		left join dbo.AddressDetail ad
			on c.MailingAddressID = ad.AddressID
				and ad.IsActive = 1
		left join dbo.ZipCode zc
			on ad.ZipCodeID = zc.ZipCodeID
		
	select 
		t2.LicenseYear,
		t2.Name, 
		t2.DisplayOrder,
		ci_orderby.LastName,
		ci_orderby.FirstName,
		ShippingName = ISNULL(fism_aot.ShippingName,  dbo.udf_GetCustomerName(t2.CustomerID)),
		FulfillmentMailingUnitID = t2.FulfillmentMailingUnitID,
		GoID = goid.IdentityValue,
		MailingZip = ISNULL(fism_zc.ZipCode, t2.ZipCode),
		TransactionID = fism_th.TransactionID,
		TransactionHeaderID = fism_th.TransactionHeaderID,
		HuntDate = t2.HuntFirstOpenDate,
		HuntCode = t2.HuntCode,
		-- Header info
		BatchNumber = t2.FulfillmentMailingUnitLockGroupID,
		PrintedByUserName = t2.UserName,
		LockedDate = t2.LockedDate 
	into #temp3
	from #temp2 t2
			left join dbo.CustomerIdentity goid
				on t2.CustomerID = goid.CustomerID
				and goid.IdentityTypeID = t2.GOID 
				and goid.[Status] = 1
			left join dbo.CustomerIndividual ci_orderby
				on t2.fdnm_l_CustomerID = ci_orderby.CustomerID
					or t2.fdim_th_CustomerID = ci_orderby.CustomerID
	
			left join dbo.TransactionHeader fism_th	
				on t2.TransactionHeaderID = fism_th.TransactionHeaderID
			left join dbo.ActiveOutdoorsTransaction fism_aot
				on fism_aot.TransactionID = fism_th.TransactionID
			left join dbo.AddressDetail fism_ad 
				on fism_aot.ShippingAddressID = fism_ad.AddressID
					and fism_ad.IsActive = 1
			left join dbo.ZipCode fism_zc
				on fism_ad.ZipCodeID = fism_zc.ZipCodeID
	select	RowNumber = ROW_NUMBER() OVER 
		( 
			-- This ordering is from the various Fulfillment Map sort orders to match the fulfillment app's row order.
			ORDER BY 
				t3.LicenseYear, 
				t3.Name, 
				t3.HuntDate, 
				t3.DisplayOrder,
				t3.HuntCode,
				t3.LastName,
				t3.FirstName,
				t3.FulfillmentMailingUnitID
		),
		ShippingName,
		FulfillmentMailingUnitID,
		GoID,
		MailingZip,
		TransactionID,
		TransactionHeaderID,
		HuntDate,
		HuntCode,
		-- Header info
		BatchNumber,
		PrintedByUserName,
		LockedDate
	from #temp3 t3
	drop table #temp
	drop table #temp1
	drop table #temp2
	drop table #temp3

经过测试,执行时间由192秒降低到2秒。

您可能感兴趣的文档:

--结束END--

本文标题: SQL Server一次SQL调优案例

本文链接: https://www.lsjlt.com/news/47623.html(转载时请注明来源链接)

有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

本篇文章演示代码以及资料文档资料下载

下载Word文档到电脑,方便收藏和打印~

下载Word文档
猜你喜欢
  • SQL Server一次SQL调优案例
    环境:Microsoft SQL Server 2016 (SP2-CU3)企业版 问题SQL: select  RowNumber = ROW_NUMBER()...
    99+
    2022-10-18
  • 通过案例学调优之--SQL Profile
    通过案例学调优之--SQL Profile一、什么是SQL Profile(概要)        SQL Profile在性能优化中占有一个重要的位置。&n...
    99+
    2022-10-18
  • Oracle性能优化-SQL优化(案例一)
    Oracle 性能优化 -SQL 优化 ( 案例一 ) 环境: OS:Red Hat Enterprise Linux AS release 4 DB:Oracle 10.2.0.1.0 ...
    99+
    2022-10-18
  • 如何调优SQL Server查询
    这期内容当中小编将会给大家带来有关如何调优SQL Server查询,文章内容丰富且以专业的角度为大家分析和叙述,阅读完这篇文章希望大家可以有所收获。在今天的文章里,我想给你展示下,当你想对特定查询创建索引设...
    99+
    2022-10-19
  • SQL server高并发生成唯一订单号的案例
    这篇文章给大家分享的是有关SQL server高并发生成唯一订单号的案例的内容。小编觉得挺实用的,因此分享给大家做个参考,一起跟随小编过来看看吧。一、场景再现在一个erp进销存系统或0A等其他系统中,如果多...
    99+
    2022-10-18
  • sql server性能调优 I/O开销的示例分析
    这篇文章主要介绍sql server性能调优 I/O开销的示例分析,文中介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们一定要看完!一.概述IO 内存是sql server最重要的资源,数据从磁盘加载到...
    99+
    2022-10-18
  • 一次夜维SQL的性能优化
    最近单位搬家,从国家会议中心,搬往空气清新的顺义后沙峪,搬迁之前的完结上线中,碰见了一些棘手的问题,有一些值得借鉴的地方。   这是一个夜维程序的优化。这个夜维的目的,是每日删除30+张...
    99+
    2022-10-18
  • 8个sql优化的案例
    SQL语句的执行顺序: 1、LIMIT 语句 分页查询是最常用的场景之一,但也通常也是最容易出问题的地方。比如对于下面简单的语句,一般 DBA 想到的办法是在 type、 name、 create_...
    99+
    2023-09-01
    sql 数据库 mysql
  • SQL优化之多表关联查询-案例一
    慢SQL日志里看到一个三张表的关联查询,如下: SELECT COUNT(1)  FROM refund_order_item i, artis...
    99+
    2022-10-18
  • SQL调优的示例分析
    这篇文章主要为大家展示了“SQL调优的示例分析”,内容简而易懂,条理清晰,希望能够帮助大家解决疑惑,下面让小编带领大家一起研究并学习一下“SQL调优的示例分析”这篇文章吧。环境:Microsoft SQL Server 2016 (SP2-...
    99+
    2023-06-05
  • SQL Server作业报错特殊案例分析
    发现问题 一个作业报错,报错信息如下,从错误信息根本看不出为什么出错,手工运行作业又成功了。一时不清楚什么原因导致作业出错。 Message Executed as user: NT SERVICE\SQ...
    99+
    2022-10-18
  • SQL Server批量插入数据案例详解
    在SQL Server 中插入一条数据使用Insert语句,但是如果想要批量插入一堆数据的话,循环使用Insert不仅效率低,而且会导致SQL一系统性能问题。下面介绍SQL Serv...
    99+
    2022-11-12
  • 记一次SQL优化的实战记录
    目录前言1. 创建表2. 需求3. 给表插入数据4. 开始根据需求写SQL4.1 第一版4.2 第二版4.3 第三版总结前言 昨天(2022-7-22)上线了我的一个功能,测试环境数据量较小,问题不大,但是上生产之后,直...
    99+
    2022-07-24
    sql优化最佳实践 SQL优化技巧 数据库SQL优化
  • Mysql基础编写sql案例(一)
    数据库里面的数据库sql文件:https://blog.csdn.net/GongmissYan/article/details/102937816 #基础查询 # 查询单个字段 select last_name f...
    99+
    2021-04-12
    Mysql基础编写sql案例(一)
  • 记一次MySQL的优化案例
    一  背景       有赞的每个OLTP数据库实例上会设置一个sql-killer进程用于kill 掉执行时间超过一定阈值的sql。下午开发接收到sql被kill的报错,一起...
    99+
    2022-05-16
    MySQL 优化 MySQL 优化案例
  • sql server 百万级数据库优化方案
    对查询进行优化,应尽量避免全表扫描,首先应考虑在 where 及 order by 涉及的列上建立索引。2.应尽量避免在 where 子句中对字段进行 null 值判断,否则将导致引擎放弃使用索引而进行全表...
    99+
    2017-09-04
    sql server 百万级数据库优化方案
  • Oracle性能优化-SQL优化(案例四)
    Oracle 性能优化 -SQL 优化 ( 案例四 ) 环境: DB:Oracle 11.2.0.1.0 问题: ERP 薪资发放节点计算时间耗时 较长,需要15 分钟左右; ...
    99+
    2022-10-18
  • SQL Server之SELECT INTO 和 INSERT INTO SELECT案例详解
    做数据库开发的过程中难免会遇到有表数据备份的,而SELECT INTO……和INSERT INTO SELECT…… 这两种语句就是用来进行表数据复制,下面简单的介绍下: 1...
    99+
    2022-11-12
  • 数栈SQL优化案例:OR条件优化
    ...
    99+
    2017-04-17
    数栈SQL优化案例:OR条件优化
  • oracle的sql调优的示例分析
    oracle的sql调优的示例分析,很多新手对此不是很清楚,为了帮助大家解决这个难题,下面小编将为大家详细讲解,有这方面需求的人可以来学习下,希望你能有所收获。 查询某个session造成lmode为3的...
    99+
    2022-10-19
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作