網上有這個問題:
http://www.cnblogs.com/bluedoctor/archive/2011/03/04/1970866.html
http://www.cnblogs.com/fxwdl/archive/2008/07/31/1257409.html
但我使用的查詢參數很簡單:是 Int32 和數據庫是一樣的。 都設置為 可空。
ADO.Net 有問題的SQL:
exec sp_executesql N'select count(1) As [Cou] From [dbo].[TF_FeesReceipts] As [TfFeesReceipts] left join [dbo].[TM_Customer] As [TmCustomer] on ([TfFeesReceipts].[CommID] = [TmCustomer].[CommID] And [TfFeesReceipts].[CustID] = [TmCustomer].[CustID]) left join [dbo].[T_USER] As [TUser] on ([TfFeesReceipts].[UserCode] = [TUser].[USER_CODE]) where [TfFeesReceipts].[CommID] = @CommID_1',N'@CommID_1 int',@CommID_1=100005
ADO.Net 沒有問題的腳本,而使用:
exec sp_executesql N'select count(1) As [Cou] From (select [TfFeesReceipts].[ReceID] As [ReceID],[TfFeesReceipts].[PaidAmount] As [BillsAmount],[TfFeesReceipts].[BillsSign] As [BillsSign],[TfFeesReceipts].[BillsDate] As [BillsDate],[TfFeesReceipts].[ChargeMode] As [ChargeMode],[TmCustomer].[CustName] As [CustName],[TUser].[USER_NAME] As [UserName] From [dbo].[TF_FeesReceipts] As [TfFeesReceipts] left join [dbo].[TM_Customer] As [TmCustomer] on ([TfFeesReceipts].[CommID] = [TmCustomer].[CommID] And [TfFeesReceipts].[CustID] = [TmCustomer].[CustID]) left join [dbo].[T_USER] As [TUser] on ([TfFeesReceipts].[UserCode] = [TUser].[USER_CODE]) where [TfFeesReceipts].[CommID] = @CommID_) As [__SubQuery__]',N'@CommID_ int',@CommID_=100005
參數的生成方式相同, 應該不是網上所說參數的問題。
上述SQL 是從 Sql Profiler 中截獲的,且在查詢分析器中執行很快,所以不會是SQL 的問題。
把第一個SQL: Count(1) 改為 sum(1) , 則執行很快。
繼續測試一下,count(*) 也很快。
count(主鍵) 也很快
count(0) 也很快
count(子查詢) 也很快:
exec sp_executesql N'select count(1) As [Cou] From (select count(1) As [Cou] From [dbo].[TF_FeesReceipts] As [TfFeesReceipts] left join [dbo].[TM_Customer] As [TmCustomer] on ([TfFeesReceipts].[CommID] = [TmCustomer].[CommID] And [TfFeesReceipts].[CustID] = [TmCustomer].[CustID]) left join [dbo].[T_USER] As [TUser] on ([TfFeesReceipts].[UserCode] = [TUser].[USER_CODE]) where [TfFeesReceipts].[CommID] = @CommID_) As [__SubQuery__]',N'@CommID_ int',@CommID_=100005
突然有一種想用 sum(1) 替換 count(1) 的沖動。
回頭再看執行一次第一種SQL: count(1) 的性能,發現居然也很快了。
數據庫: Sql 2008 R2 x64, 操作系統: windows 2008R2 x64 , 數據庫在本機。 內存 4G
-----------------------------------------------------------------------------------------------------------
后來又發現了這個問題,且表現很不穩定。
測試代碼:
public ActionResult QuerySlowlyTest() { var sl = new StringLinker(); using (var scope = new MyOqlConfigScope(ReConfigEnum.SkipCache | ReConfigEnum.SkipLog | ReConfigEnum.SkipPower)) { var st = Stopwatch.StartNew(); dbr.View.VmFeesChangeFilter .Select(o => new Columns(o.UserCode, o.UserName)) .Distinct() .Where(o => o.CommID == 100005 & o.UserName != null) .ToMyOqlSet(); sl += ("普通參數化查詢:" + st.ElapsedMilliseconds) + Environment.NewLine; st.Restart(); var cmd = dbr.View.VmFeesChangeFilter .Select(o => new Columns(o.UserCode, o.UserName)) .Distinct() .Where(o => o.CommID == 100005 & o.UserName != null) .ToCommand(); cmd.Command.Parameters[0].DbType = DbType.Int64; var da = new System.Data.SqlClient.SqlDataAdapter(cmd.Command as System.Data.SqlClient.SqlCommand); using (var conn = new System.Data.SqlClient.SqlConnection( System.Configuration.ConfigurationManager.ConnectionStrings["pm"].ConnectionString )) { conn.Open(); var ds = new DataSet() ; da.Fill(ds); } sl += ("自定義參數查詢:" + st.ElapsedMilliseconds) + Environment.NewLine; st.Restart(); dbo.ToDataTable("pm", @"select distinct usercode, user_name from vm_feeschange_filter where commid = 100005 and user_name is not null order by user_name"); sl += ("SQL查詢:" + st.ElapsedMilliseconds) + Environment.NewLine; } return Content("<pre>" + sl.ToString() + "</pre>"); }
三個時間值:
普通參數化查詢:201213 自定義參數查詢:1087 SQL查詢:1826
這個問題單獨測試時,可以復現, 但放到頁面中, 時有時無。
但可以得出這個結論:
放大參數的 DbType 數據類型(數字類型),可以避免查詢過慢的情況。
另外,根據以往的貼子,還要:
對參數要設置正確的 DbType(varchar = AnsiString, nvarchar=String,char=AnsiStringFixedLength,nchar=StringFixedLength)