SQL 执行很快,Ado.net 的参数化查询很慢的原因。
2012-10-12 18:26
369 查看
网上有这个问题:
/article/4805123.html
/article/5082431.html
但我使用的查询参数很简单:是 Int32 和数据库是一样的。 都设置为 可空。
ADO.Net 有问题的SQL:
ADO.Net 没有问题的脚本,而使用:
参数的生成方式相同, 应该不是网上所说参数的问题。
上述SQL 是从 Sql Profiler 中截获的,且在查询分析器中执行很快,所以不会是SQL 的问题。
把第一个SQL: Count(1) 改为 sum(1) , 则执行很快。
继续测试一下,count(*) 也很快。
count(主键) 也很快
count(0) 也很快
count(子查询) 也很快:
突然有一种想用 sum(1) 替换 count(1) 的冲动。
回头再看执行一次第一种SQL: count(1) 的性能,发现居然也很快了。
数据库: Sql 2008 R2 x64, 操作系统: windows 2008R2 x64 , 数据库在本机。 内存 4G
-----------------------------------------------------------------------------------------------------------
后来又发现了这个问题,且表现很不稳定。
测试代码:
三个时间值:
这个问题单独测试时,可以复现, 但放到页面中, 时有时无。
但可以得出这个结论:
[b]放大参数的 DbType 数据类型(数字类型),可以避免查询过慢的情况。[/b]
另外,根据以往的贴子,还要:
[b]对参数要设置正确的 DbType(varchar = AnsiString, nvarchar=String,char=AnsiStringFixedLength,nchar=StringFixedLength)[/b]
/article/4805123.html
/article/5082431.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(); [b]cmd.Command.Parameters[[/b][b]0].DbType = DbType.Int64; [/b]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
这个问题单独测试时,可以复现, 但放到页面中, 时有时无。
但可以得出这个结论:
[b]放大参数的 DbType 数据类型(数字类型),可以避免查询过慢的情况。[/b]
另外,根据以往的贴子,还要:
[b]对参数要设置正确的 DbType(varchar = AnsiString, nvarchar=String,char=AnsiStringFixedLength,nchar=StringFixedLength)[/b]
相关文章推荐
- ADO.NET 执行sql命令
- ado.net Oracle中一次执行多条sql语句
- ADO.NET出错原因:Dynamic SQL generation for the UpdateCommand is not Supported ……
- 使用ADO.NET下的SqlBulkCopy类执行批量复制操作
- 使用Ado.net执行SP很慢,而用SSMS执行很快
- 使用ADO.NET执行带参数的Sql语句
- ado.net EF与ado.net区别比较、在EF中使用执行sql语句
- 在执行Ado.net SqlDataAdapter 查询超时设置
- 使用Ado.net执行SP很慢,而用SSMS执行很快
- ADO.NET下的SqlBulkCopy类执行数据库间批量复制操作
- ADO.NET——Command(执行SQL) & DataReader(读取数据库)
- 如何在Oracle中一次执行多条sql语句【ado.net】
- Ado.net利用反射执行SQL得到实体
- ADO.NET——Command(执行SQL) & DataReader(读取数据库)
- Ado.Net执行SQL时,返回执行状态(进度)
- [VB.NET]ADO数据库处理-执行SQL代码
- 如何在Oracle中一次执行多条sql语句【ado.net】
- 使用ADO.NET执行SQL脚本
- 黑马程序员之ADO.NET学习笔记:通过SqlCommand对象执行SQL语句
- ADO.NET_第八篇_OracleCommand_执行多个SQL语句01