金锣软件开发组

团队、合作、共享

  博客园 :: 首页 :: 博问 :: 闪存 :: 新随笔 :: 联系 :: 订阅 订阅 :: 管理 ::

案例:

数据表有EmployeeCode(varchar(8))字段,数据大约七百万行,已在EmployeeCode上创建非聚集索引。程序编译环境Visual Studio 2003、.NET 1.1
string sql = "SELECT COUNT(1) FROM Article WHERE EmploeeCode = @EmployeeCode";
SqlParameter[] args 
= new SqlParameter[]
{
    
new SqlParameter("@EmployeeCode", txtEmployeeCode.Text)
};

但它实际执行起来效率很差,需要10秒左右。而在查询分析器中直接执行“SELECT COUNT(1) FROM Article WHERE EmploeeCode = '01020304'”执行时间不到1秒。

分析:

在SQL SERVER中创建跟踪,发现它执行的是以下SQL语句:
exec sp_executesql N'SELECT COUNT(1) FROM Article WHERE EmploeeCode = @EmployeeCode', N'@EmployeeCode nvarchar(4000)'@EmployeeCode = N'01020304'

问题就出在参数定义N'@EmployeeCode nvarchar(4000)'上。由于我们的字段定义是varchar(8),而参数是nvarchar(4000),这就造成了字段类型不匹配。推测SQL SERVER此时是将字段转化为nvarchar然后匹配查询结果,导致查询效率很低。这种情况下,传参方式比SQL拼接语句方式效率要低很多(当然SQL拼接语句方式更不推荐,SQL缓存命中率低,还有臭名昭著的SQL注入问题)。

指定参数类型后,问题解决:
string sql = "SELECT COUNT(1) FROM Article WHERE EmploeeCode = @EmployeeCode";
SqlParameter[] args 
= new SqlParameter[]
{
    
new SqlParameter("@EmployeeCode", SqlDbType.VarChar, 8)
};
args[
0].Value = txtEmployeeCode.Text;


结论:

1、强烈建议传参时指定参数类型。
2、数据库性能出现问题后,除了优化数据结构外,还需要跟踪SQL性能监视器,找到影响效率的瓶颈所在。把主要精力放在经常执行而又比较耗时的操作。  

备注:

在.NET 2.0中,可能对以上方式有稍许改进,但也存在类似的问题。所以还是显示指定参数类型比较好。

==============================================
对于.NET这个性能杀手,幕后主使……有时……就是我们自己。

 

posted on 2008-05-19 16:13  新程金锣  阅读(433)  评论(0)    收藏  举报