【发布时间】:2014-03-30 08:16:00
【问题描述】:
我有一些表现出低性能的嵌套程序。为了找到瓶颈,我在 t-sql 代码中插入了一些调试标记,以测量我怀疑性能低下的代码块的性能。这个调试标记看起来像:
select @start_point = GETDATE() -- start measuring point
---
open @session_license_fee_cur -- suspected chunk of code
---
select @end_point = GETDATE()-- end measuring point
select @duration = datediff(ms, @start_point, @end_point)
select @log_info_total = 'Opening cursor license_fee (bills_supp_create_license_fee) (@class_id = ' + cast(@class_id as nvarchar) + ')';
exec bills_supp_save_calculation_log @duration, @log_info_total, @house_id, @account_id, @log_level -- procedure for creating log (simple insert into log table pes_bl_bills_calculation_log_total)
运行程序后,我从pes_bl_bills_calculation_log_total 表运行查询以查找性能最低的代码。看起来是这样的
set @session_license_fee_cur = cursor static for
select activity_id
, addendum_id
, service_id
, active_from
, active_to
from dbo.bills_supp_get_activate_license_fee_for_sessions_by_house(@active_from, @active_to, @house_id)
select @start_point = GETDATE()
---
open @session_license_fee_cur
---
select @end_point = GETDATE()
select @duration = datediff(ms, @start_point, @end_point)
select @log_info_total = 'Opening cursor license_fee (bills_supp_create_license_fee) (@class_id = ' + cast(@class_id as nvarchar) + ')';
exec bills_supp_save_calculation_log @duration, @log_info_total, @house_id, @account_id, @log_level
换句话说,打开 @session_license_fee_cur 工作非常缓慢(大约 501980 毫秒)。
我正在尝试在 SQL Server Management Studio 中使用给定参数运行这段代码,以查看查询计划并尝试对其进行优化。我是这样运行的
declare @active_from date = '01.03.2014'
declare @active_to date = '01.04.2014'
declare @house_id integer = 11927
select activity_id
, addendum_id
, service_id
, active_from
, active_to
from dbo.bills_supp_get_activate_license_fee_for_sessions_by_house(@active_from, @active_to, @house_id)
但它的工作速度非常快(在大约 0(零)秒内返回 3000 条记录)。 在程序中打开光标有什么区别
open @session_license_fee_cur
并在 SQL Server Management Studio 中运行它?
declare @active_from date = '01.03.2014'
declare @active_to date = '01.04.2014'
declare @house_id integer = 11927
select activity_id
, addendum_id
, service_id
, active_from
, active_to
from dbo.bills_supp_get_activate_license_fee_for_sessions_by_house(@active_from, @active_to, @house_id)
我的瓶颈在哪里?
【问题讨论】:
-
主要差异是引擎不需要处理光标。您可以尝试使用 FAST_FORWARD 提示该游标,但通常最好的方法是避免使用游标。顺便说一句,使用 sysdatetime() 而不是 getdate()
-
谢谢琼。看来我发现了问题。函数 bills_supp_get_activate_license_fee_for_sessions_by_house 中的子查询有一个导致降级的完整扫描查询。但有一件事我没有得到。为什么这个在 SQL Management Studio 中没有游标的查询的工作时间约为 0 秒,但在查询中它的工作时间超过 5 分钟。为什么会有这样的差异?
-
你必须看到生成的查询计划,这可以给你一些线索(包括关于全表扫描)。也许游标正在分配大量内存/临时数据库。尝试监控 CPU、内存和 IO,看看游标声明做错了什么。
标签: sql-server performance tsql