高效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 操作,但实际情况是:

高效SQL查询之索引(I)_第1张图片

高效SQL查询之索引(I)_第2张图片

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 了。

原创地址:

     http://www.cnblogs.com/cn_wpf/archive/2007/08/03/841911.html

你可能感兴趣的:(sql,IO,pig,table,sqlserver,insert)