MSSQL:SQL 性能 (二)
作者:刘帝勇
这两天遇到一个问题,比较奇怪,记录下来。问题描述如下:
在Sql Server 2005中,有表ITWORKITEMS,数据有100万行,WIREFID 字段上建有索引(非联合索引)。此表共有9个索引,无聚集索引。执行如下步骤:
1.
结果:
SQL Server 分析和编译时间:
CPU 时间 = 0 毫秒,占用时间 = 315 毫秒。
SQL Server 执行时间:
CPU 时间 = 0 毫秒,占用时间 = 1 毫秒。
(102 行受影响)
SQL Server 执行时间:
CPU 时间 = 1485 毫秒,占用时间 = 22802 毫秒。
3.
4.
SQL Server 分析和编译时间:
CPU 时间 = 0 毫秒,占用时间 = 283 毫秒。
SQL Server 执行时间:
CPU 时间 = 0 毫秒,占用时间 = 1 毫秒。
SQL Server 执行时间:
CPU 时间 = 0 毫秒,占用时间 = 1 毫秒。
(102 行受影响)
SQL Server 执行时间:
CPU 时间 = 0 毫秒,占用时间 = 436 毫秒。
对比两种方式,其实并没有差别。猜想应该是【方式一】并没有利用到索引。查看一下执行计划:
果不其然,【方式一】是全表扫描。原因大概在于SQL Server会计算不同plan的cost,然后选择小的来执行。有些时候SQL Server选择的plan对有些值不是最优的。 因此,我们需要采用WITH(INDEX(index_name)) 强制使用索引或者通过 OPTION(OPTIMIZE FOR(@变量='值')) , 以使用特定值来生成执行计划来解决这个问题:
当然,也可以使用存储过程sp_executesql执行带参数的Sql语句。
----
后记:
2009.3.17,灵光乍现,大概觉得MSSQL为什么要将带参数以全表扫描作为执行计划了。因为Like后面的值不确定(参数),假设值是类似'%value%'这样的模式,那必然还是利用不上索引。这样想来,其以最坏情况来处理,也就是在情理之中了。
文章出自:http://photo.blog.sina.com.cn/blogpic/3f2ef1180100cf4p/3f2ef118g64c2c18298e9
1.
- SQL code
-
SET STATISTICS TIME ON
- SQL code(方式一)
-
DECLARE @Process_Instance_Id nVarChar(48)
-
SET @Process_Instance_Id = 'nvevrqt6e25wzpvhpa95htn4h2.%'
-
SELECT 1
-
FROM ITWORKITEMS I
-
WHERE I.WIREFID LIKE @Process_Instance_Id
-
ORDER BY I.WISTART DESC, I.PRINSTUID DESC, I.WIID DESC
结果:
SQL Server 分析和编译时间:
SQL Server 执行时间:
(102 行受影响)
SQL Server 执行时间:
3.
- SQL code
-
DBCC FREEPROCCACHE
-
DBCC DROPCLEANBUFFERS
-
CHECKPOINT
4.
- SQL code(方式二)
-
DECLARE @Process_Instance_Id nVarChar(48)
-
SET @Process_Instance_Id = 'nvevrqt6e25wzpvhpa95htn4h2.%'
-
SELECT 1 FROM ITWORKITEMS I
-
WHERE I.WIREFID LIKE 'nvevrqt6e25wzpvhpa95htn4h2.%'
-
ORDER BY I.WISTART DESC, I.PRINSTUID DESC, I.WIID DESC
SQL Server 分析和编译时间:
SQL Server 执行时间:
SQL Server 执行时间:
(102 行受影响)
SQL Server 执行时间:
-
DECLARE @Process_Instance_Id nVarChar(48)
-
SET @Process_Instance_Id = 'nvevrqt6e25wzpvhpa95htn4h2.%'
-
SELECT 1
-
FROM ITWORKITEMS I
-
WHERE I.WIREFID LIKE @Process_Instance_Id
-
ORDER BY I.WISTART DESC, I.PRINSTUID DESC, I.WIID DESC
-
OPTION (OPTIMIZE FOR(@Process_Instance_Id = 'nvevrqt6e25wzpvhpa95htn4h2.%' )
- 或者
-
DECLARE @Process_Instance_Id nVarChar(48)
-
SET @Process_Instance_Id = 'nvevrqt6e25wzpvhpa95htn4h2.%'
-
SELECT 1
-
FROM ITWORKITEMS I WITH(INDEX(IX9_WORKITEMS))
-
WHERE I.WIREFID LIKE @Process_Instance_Id
-
ORDER BY I.WISTART DESC, I.PRINSTUID DESC, I.WIID DESC
----
后记:
文章出自:http://photo.blog.sina.com.cn/blogpic/3f2ef1180100cf4p/3f2ef118g64c2c18298e9