高效SQL查询之索引(I)

 

大型系统的生产环境,一般情况下,我们评价一条查询是否有效率,更多的是关注逻辑 IO( 至于为什么,回头补一篇 ) 。我们常说,“要建彪悍的索引”、“要写高效的 SQL ”,其实最终目的就是在相同结果集情况下,尽可能减少逻辑 IO 。

1.1      where 条件的列上都得有统计信息。

没统计信息 SQLServer 就无法估算不同查询计划开销优劣,而只能采用最稳妥的 Scan (不管是 table scan 还是 clustered index scan )。一般情况下我们不会犯这种错误—— where 条件里不使用非索引列是个常识。索引上的统计信息是无法删除的。

1.2      尽量不使用不等于( != )或者 NOT 逻辑运算符。

这条规则被广为传颂,原因据联机文档和百敬同学的书讲,也是 SQLServer 无法评估不同查询计划开销的优劣。但是 SqlServer2k5 聪明了很多,试验发现尽管用了 != 或者 not ,查询还是会被优化。如下:

create table tb1

(

    col1 int identity ( 1, 1) primary key ,

    col2 int not null,

    col3 varchar ( 64) not null

)

create index ix_tb1_col2 on tb1

(

    col2

)

create index ix_tb1_col3 on tb1

(

    col3

)

declare @f int

set @f = 0

while @f < 9999

begin

    insert into tb1 ( col2, col3) values ( 1, 'ssdd' )

    set @f = @f + 1

end

insert into tb1 ( col2, col3) values ( 0, 'aadddd' )

insert into tb1 ( col2, col3) values ( 2, 'bbddd' )

insert into tb1 ( col2, col3) values ( 3, 'bbaaddddddaa' )

通过上述代码,各位可以看到数据分布。 col2 值为 1 的有 9999 条; col2 值为 0 、 2 、 3 的分别有 1 条。

按照本条规则, != 和 NOT 带来的应该是个 scan 操作,但实际情况是:

 

SQL2k5 很聪明,它依据统计信息分析得出来,应该采用 index seek 而不是 index scan 。(稍微解释解释 index seek 和 index scan :索引是一颗 B 树, index seek 是查找从 B 树的根节点开始,一级一级找到目标行。 index scan 则是从左到右,把整个 B 树遍历一遍。假设唯一的目标行位于索引树(假设是非聚集索引,树深度 2 ,叶节点占用 k 页物理存储)最右的叶节点上(如上例)。 index seek 引起的 IO 是 4 ,而 index scan 引起的 IO 是 K ,性能差别巨大。关于索引,可以仔细读读联机文档关于物理数据库体系结构部分 )。

1.3      查询条件中不要包含运算

这些运算包括字符串连接(如: select * from Users where UserName + ‘pig’ = ‘ 张三 pig’ ),通配符在前面的 Like 运算(如: select * from tb1 where col4 like ‘%aa’ ),使用其他用户自定义函数、系统内置函数、标量函数等等(如: select * from UserLog where datepart(dd, LogTime) = 3 )。

         SQLServer 在处理以上语句时,一样没办法估算开销。最终结果当然是 clustered index scan 或者 table scan 了。

1.4      查询条件中不要包含同一张表内不同列之间的运算

所谓的“运算”包括加减乘除或通过一些 function (如: select * from tb where col1 – col2 = 1997 ),也包括比较运算(如: select * from tb where col1 > col2 )。这种情况下, SQLServer 一样没办法估算开销。不论 col1 、 col2 上都有索引还是创建了 col1 、 col2 上的覆盖索引还是创建了 col1 include col2 的索引。

但是这种查询有解决办法,可以在表上多创建一个计算字段,其值设置为你的“运算”结果,再在该字段上创建一个索引,就 Ok 了。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值