案例:
数据表有EmployeeCode(varchar(8))字段,数据大约七百万行,已在EmployeeCode上创建非聚集索引。程序编译环境Visual Studio 2003、.NET 1.1string sql = "SELECT COUNT(1) FROM Article WHERE EmploeeCode = @EmployeeCode";
SqlParameter[] args = new SqlParameter[]
{
new SqlParameter("@EmployeeCode", txtEmployeeCode.Text)
};
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;
SqlParameter[] args = new SqlParameter[]
{
new SqlParameter("@EmployeeCode", SqlDbType.VarChar, 8)
};
args[0].Value = txtEmployeeCode.Text;
结论:
1、强烈建议传参时指定参数类型。2、数据库性能出现问题后,除了优化数据结构外,还需要跟踪SQL性能监视器,找到影响效率的瓶颈所在。把主要精力放在经常执行而又比较耗时的操作。
备注:
在.NET 2.0中,可能对以上方式有稍许改进,但也存在类似的问题。所以还是显示指定参数类型比较好。==============================================
对于.NET这个性能杀手,幕后主使……有时……就是我们自己。

浙公网安备 33010602011771号