SQL调优的示例分析
发表于:2025-01-24 作者:千家信息网编辑
千家信息网最后更新 2025年01月24日,这篇文章主要为大家展示了"SQL调优的示例分析",内容简而易懂,条理清晰,希望能够帮助大家解决疑惑,下面让小编带领大家一起研究并学习一下"SQL调优的示例分析"这篇文章吧。环境:Microsoft S
千家信息网最后更新 2025年01月24日SQL调优的示例分析
这篇文章主要为大家展示了"SQL调优的示例分析",内容简而易懂,条理清晰,希望能够帮助大家解决疑惑,下面让小编带领大家一起研究并学习一下"SQL调优的示例分析"这篇文章吧。
环境: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.LockedDatefrom 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存在大量多表连接,MSSQL引擎由于统计信息的算法单一,在处理大量级联连接时,实际数据可能严重偏离统计信息
连接中存在Actual Rows和Estimated Rows严重不一致的情况,随着连接表数目增加,该不一致更加严重:
经过分析,优化的目标是减少多表连接的统计信息不一致导致的执行计划错误并且对最终的排序操作进行外推。
优化的手法主要是利用临时表固化统计信息,外推排序:
最终优化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秒。
以上是"SQL调优的示例分析"这篇文章的所有内容,感谢各位的阅读!相信大家都有了一定的了解,希望分享的内容对大家有所帮助,如果还想学习更多知识,欢迎关注行业资讯频道!
分析
信息
统计
示例
一致
内容
篇文章
排序
学习
帮助
企业
实际
引擎
情况
手法
数据
数目
时间
易懂
更多
数据库的安全要保护哪些东西
数据库安全各自的含义是什么
生产安全数据库录入
数据库的安全性及管理
数据库安全策略包含哪些
海淀数据库安全审计系统
建立农村房屋安全信息数据库
易用的数据库客户端支持安全管理
连接数据库失败ssl安全错误
数据库的锁怎样保障安全
恕瑞玛服务器ip
桓台考勤管理oa软件开发公司
网页数据库图片
简单的眼镜行业软件开发
进口网络技术开发材料
金银天下网络技术有限公司
常州服务器机房搭建哪家好
方舟手机版如何创建多人服务器
怎么玩mc国际版的服务器
sql数据库管理 app
dell1u服务器
涉密网络安全保密风险评估
网页显示无法连接数据库
软件开发过程的类型
服务器是怎么做的
工行软件开发中心要求
软件开发适合哪些工作
个性化网络技术开发生产过程
软件开发经理任职资格
慈溪租车软件开发
网络安全法实施问题研究
兰州信息安全特训营网络安全培训
网络安全培训学校靠谱吗
上海企业软件开发定制要求
苏州c语言软件开发价位
朋友圈转发软件开发
网络安全月宣传画模板
江门市照片人脸识别软件开发
福州百纳网络技术有限公司
成都电信网络技术支持