您的位置:首页 > 数据库

学习:SQL性能:强制索引(转)

2009-03-26 11:44 211 查看
MSSQL:SQL 性能 (二)

作者:刘帝勇

这两天遇到一个问题,比较奇怪,记录下来。问题描述如下:
在Sql Server 2005中,有表ITWORKITEMS,数据有100万行,WIREFID 字段上建有索引(非联合索引)。此表共有9个索引,无聚集索引。执行如下步骤:

1.

SQL code

SET STATISTICS TIME ON2.

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 分析和编译时间:
CPU 时间 = 0 毫秒,占用时间 = 315 毫秒。
SQL Server 执行时间:
CPU 时间 = 0 毫秒,占用时间 = 1 毫秒。
(102 行受影响)
SQL Server 执行时间:
CPU 时间 = 1485 毫秒,占用时间 = 22802 毫秒。

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 分析和编译时间:
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(@变量='值')) , 以使用特定值来生成执行计划来解决这个问题:

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 当然,也可以使用存储过程sp_executesql执行带参数的Sql语句。

----
后记:
2009.3.17,灵光乍现,大概觉得MSSQL为什么要将带参数以全表扫描作为执行计划了。因为Like后面的值不确定(参数),假设值是类似'%value%'这样的模式,那必然还是利用不上索引。这样想来,其以最坏情况来处理,也就是在情理之中了。

文章出自:http://photo.blog.sina.com.cn/blogpic/3f2ef1180100cf4p/3f2ef118g64c2c18298e9
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: