【发布时间】:2011-05-04 23:54:41
【问题描述】:
我无法解决我在下面发布的查询的性能不佳问题。
这是我的问题:
如果我在 sql server managment studio 或使用 .NET sqlclient 中运行下面的确切查询,则查询平均需要 14 秒才能运行。
但是,如果在 .NET 中我取出这部分查询:
DECLARE @time_diff INT
DECLARE @start_date DATETIME
DECLARE @end_date DATETIME
SET @time_diff = 2
SET @start_date = '05/04/11 00:00:00 AM'
SET @end_date = '5/4/2011 11:59:59 PM'
并在代码中像这样使用参数:
sqlParameter = sqlCmd.Parameters.Add(New SqlParameter("@start_date", System.Data.SqlDbType.DateTime))
sqlParameter.Value = parameters.StartDate
sqlParameter = sqlCmd.Parameters.Add(New SqlParameter("@end_date", System.Data.SqlDbType.DateTime))
sqlParameter.Value = parameters.EndDate
那么查询运行大约需要 2 到 3 分钟。
另外,我注意到如果我用字符串日期常量替换参数值并在 .NET 或 SSMS 中运行,运行大约需要 2 - 3 分钟
--AND v.call_start_time BETWEEN @start_date AND @end_date
AND v.call_start_time BETWEEN '05/04/11' AND '5/4/2011 11:59:59 PM'
我发现这篇关于基数和查询优化器的文章http://msdn.microsoft.com/en-us/library/ms175933%28SQL.90%29.aspx,我认为这与我的问题有关,但在我的情况下似乎没有意义。 根据文章,在确定基数时应该执行强制转换。就我而言,这似乎没有发生。该文章还说使用参数代替局部变量 - 这也不适用于 .NET 参数。
关于使用存储过程: 我有可变数量的参数,我不知道效果如何。即使这是唯一的选择,我还是想知道到底是什么问题。
查询:
DBCC DROPCLEANBUFFERS
DBCC FREEPROCCACHE
SET STATISTICS IO ON
DECLARE @time_diff INT
DECLARE @start_date DATETIME
DECLARE @end_date DATETIME
SET @time_diff = 2
SET @start_date = '05/04/11 00:00:00 AM'
SET @end_date = '5/4/2011 11:59:59 PM'
--INSERT QUERY
SELECT * INTO ##tmp_15 FROM (-- PRI CALL RECORDINGS SEARCH QUERY:
SELECT DISTINCT
v.call_recording_id,
v.call_start_time,
v.call_source,
v.call_type,
IsNull(v.phone, '') AS phone,
d.call_duration_seconds AS pri_call_duration_seconds,
IsNull(cdr.extension, 'N/A') AS pri_extension,
IsNull(users.last_name, 'N/A') AS pri_last_name,
IsNull(users.first_name, 'N/A') AS pri_first_name,
NULL AS debtor_no,
NULL AS d_extension,
NULL AS d_last_name,
NULL AS d_first_name
FROM tbl_call_recordings AS v
JOIN tbl_pri_call_details AS d ON v.call_recording_id = d.call_recording_id
LEFT JOIN (
SELECT extension, phone, call_start_time
FROM tbl_pri_cdr_records
WHERE is_discard = 0
) AS cdr ON v.phone = cdr.phone AND
ABS(DATEDIFF(mi, v.call_start_time, cdr.call_start_time)) <= @time_diff
-- MATCH RECORDS TO USER INFO VIA EXTENSION
LEFT JOIN (
SELECT extension,
start_date,
IsNull(end_date, GETDATE()) AS end_date,
usr.user_id,
last_name,
first_name,
cr_user_id
FROM tbl_extensions AS ext
JOIN tbl_extension_users AS ext_usr ON ext.id = ext_usr.extension_id
JOIN tbl_users AS usr ON ext_usr.user_id = usr.user_id
) AS users ON cdr.extension = users.extension
AND v.call_start_time BETWEEN users.start_date AND users.end_date
WHERE 1 = 1
-- INSERT PRI SEARCH CONSTRAINTS HERE:
AND v.call_start_time BETWEEN @start_date AND @end_date
--AND v.call_start_time BETWEEN '05/04/11' AND '5/4/2011 11:59:59 PM'
UNION
-- DIALER RECORDINGS SEARCH QUERY:
SELECT
v.call_recording_id,
v.call_start_time,
v.call_source,
v.call_type,
IsNull(v.phone, '') AS phone,
NULL AS pri_call_duration_seconds,
NULL AS pri_extension,
NULL AS pri_last_name,
NULL AS pri_first_name,
d.debtor_no,
IsNull(users.extension, 'N/A') AS extension,
IsNull(users.last_name, 'N/A') AS last_name,
IsNull(users.first_name, 'N/A') AS first_name
FROM tbl_call_recordings AS v
JOIN tbl_dialer_call_details AS d ON v.call_recording_id = d.call_recording_id
-- MATCH RECORDS TO USER INFO VIA EXTENSION
LEFT JOIN (
SELECT extension,
start_date,
IsNull(end_date, GETDATE()) AS end_date,
last_name,
first_name,
cr_user_id
FROM tbl_extensions AS ext
JOIN tbl_extension_users AS ext_usr ON ext.id = ext_usr.extension_id
JOIN tbl_users AS usr ON ext_usr.user_id = usr.user_id
) as users ON d.agent = users.cr_user_id
AND v.call_start_time BETWEEN users.start_date AND users.end_date
WHERE 1 = 1
-- INSERT DIALER SEARCH CONSTRAINTS HERE:
AND v.call_start_time BETWEEN @start_date AND @end_date
--AND v.call_start_time BETWEEN '05/04/11' AND '5/5/2011'
)t
【问题讨论】:
-
因此,与有机会查看实际值相比,使用变量获得的性能更好?也许您需要更新该表的统计信息。
-
是的,我使用变量获得了更好的性能 - 但只有在 sql 中声明和设置时。在 .NET 中使用参数时,性能为 2-3 分钟而不是 15 秒。如果 .NET 参数没有执行,更新统计数据仍然有意义吗?
-
是的,我想是的。我认为这些的参数值仍然被嗅探。
-
@Martin - 效果很好,谢谢。现在一切平均为 15 秒。提交它作为答案,我会给你信用。
标签: .net vb.net sql-server-2005