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



    MSSQL:SQL 性能 (二)
    作者:刘帝勇

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

    1.
    SQL code
    SET STATISTICS TIME ON
    2.
    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
  • 相关阅读:
    多表查询
    Java基础
    group by 和 having 用法
    多态
    修改用户权限
    集成测试过程
    系统测试
    软件验收测试通过准则
    性能测试、负载测试、压力测试的区别
    白盒测试
  • 原文地址:https://www.cnblogs.com/LeimOO/p/1422182.html
Copyright © 2020-2023  润新知