学习: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
作者:刘帝勇
这两天遇到一个问题,比较奇怪,记录下来。问题描述如下:
在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
相关文章推荐
- 学习:sql 利用索引优化性能(转)
- 学习动态性能表第三篇-(2)-V$SQL_PLAN
- Oracle SQL性能优化系列学习二
- 提高DB2数据库SQL存储过程性能学习笔记
- sql 利用索引优化性能
- 强制sql使用一个索引
- sql学习一 主键,联合主键,外键、索引 ,分区
- sql 学习之二(sql常见性能优化总结)
- SQL学习之路(二)——索引
- oracle 强制索引学习
- SQL 入门(利用索引改善性能)
- 高级sql学习--sql性能优化!!!
- SQL优化(SQL TUNING)可大幅提升性能的实战技巧之一——让计划沿着索引跑
- .NET深入学习笔记(1):DataSet和SqlDataReader性能差异深入剖析与测试(2)
- SQL索引学习-聚集索引
- PL/SQL学习笔记-索引
- oracle10g sql性能调优时,索引的使用
- Oracle性能优化学习笔记之共享Sql语句
- Oracle SQL性能优化系列学习三
- 数据库学习一---------数据库查询索引和记录数,监控数据库性能