SQL 執行很快,Ado.net 的參數化查詢很慢的原因。


網上有這個問題:

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)

 

 

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM