zoukankan      html  css  js  c++  java
  • 学习: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
  • 相关阅读:
    安卓平台下ARM Mali OpenCL编程-GPU信息检测(转)
    Android 常用的性能分析工具详解:GPU呈现模式, TraceView, Systrace, HirearchyViewer(转)
    windows配置meld
    nginx的学习材料
    nginx+lua组合的web框架
    [转] Linux下防火墙iptables用法规则详及其防火墙配置
    转:关于知乎音视频学习入门的解答
    转: 在创业公司使用C++
    【转】 消息队列设计精要
    转: __asm__ __volatile__内嵌汇编用法简述
  • 原文地址:https://www.cnblogs.com/LeimOO/p/1422182.html
Copyright © 2011-2022 走看看