我很難解決我在下面發佈的問題。基數估計問題?日期時間參數vs cast?
這裏是我的問題:
如果我在SQL Server同治工作室運行下面的確切查詢或利用.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分鐘跑步。
另外,我注意到,大約需要2 - 3分鐘跑,如果我用繩子日期常量替換參數值,並在.NET或SSMS運行
--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
所以你得到更好的** **比當有機會看看實際值的變量的表現?也許你需要更新該表的統計數據。 – 2011-05-05 00:08:04
是的,我使用變量獲得了更好的性能 - 但只有在sql中聲明並設置時。在.NET中使用參數時,性能是2-3分鐘而不是15秒。如果.NET參數沒有執行,更新統計信息是否仍然有意義? – 2011-05-05 00:27:25
是的,我認爲是。我認爲這些參數值仍然被嗅探。 – 2011-05-05 01:22:04