create table tb(a int,b int)create index ix_tb on tb(a,b)select * from tb where a=@a
--会使用索引
select * from tb where b=@b
--由于不包含该索引中的第一列所以不会使用索引select * from tb where a=@a or b=@b
--会使用索引,why? 迷惑为什么这个语句也能使用到索引,or b=@b 应该是等同于下一句:
select * from tb where a=@a --会用到索引
union
select * from tb where b=@b --不会用到索引
解决方案 »
- 请问二级导航查询怎么返回这样格式的数据呢?
- sql server数据库内的表内可以进行算法运算吗?比如一个表其中一列等于其他若干列之和。
- 求一个简单快捷的INSERT+UPDATE结合
- 如何在数据库中插入一条数据,数据的直通过一个已知的datetime找出后,这个datetime自身加1后得到
- 怎样把一字符串类型的字段折分为三个字段.如:'d2.1-2002-0226'
- SP4总是安装不上
- group by排序,在线等待
- 这个触发器应该怎样写,或者有没有其他更高效的方法来解决
- 再问排序???
- 这个问题,看来的解决难较大了!!!好几天了也没有好办法!!!
- SAN +RAID结构下还需要表分区吗?
- 困扰了好久的问题,没想到好的解决算法,请教高手~~
有时候不一定index scan 就比 table scan 快
--会使用索引,[color=#FF6600]why? 迷惑为什么这个语句也能使用到索引,or b=@b 应该是等同于下一句:
select * from tb where a=@a --会用到索引
union
select * from tb where b=@b --不会用到索引[/color]谁说的等同于这一句??????????
优化不但需要技术,还需要经验。
这就是dba为什么越老越值钱的原因了
这个应该是Index Scanselect * from tb where a=@a or b=@b
Seek和Scan是不同的.而且b也在索引里面,Scan索引也可以得到b,索引优化器选择index scan也不是不行
with index()
为什么OR就不能用索引呢?索引就像书的目录,为什么OR就不能用
也就是说就算 select * from tb where b=@b 也是索引扫描?等下我测试下。
两个结果是一样的,UNION会分成2个分别查询,还会有一个去处重复值的步骤
create table tb(a int,b int)create index ix_tb on tb(a,b)select * from tb where b=@b --由于不包含该索引中的第一列所以不会使用索引
--通过执行计划查看,上句为错误的,实际上能够用到索引,只不过是索引扫描而不是索引查找而已,索引SCAN 虽然也不理想,不过在很多情况下比全表扫描也要好的多。谢谢各位。
例如,如果将索引定义为 LastName、FirstName,则该索引在搜索条件为 WHERE LastName = 'Smith' 或 WHERE LastName = Smith AND FirstName LIKE 'J%' 时将很有用。不过,查询优化器不会将此索引用于基于 FirstName (WHERE FirstName = 'Jane') 而搜索的查询。--Ⅱ解释
①
当你建立一个复合索引(以LastName为Key Column),即是
CREATE INDEX IX_LastName_FirstName ON tbl_TestCSDN(LastName,FirstName)
时MS SQL会自动产生基于字段LastName的统计信息(Statistics).尽管是复合索引,MS SQL仅仅存放
主字段,复合索引的第一个字段的统计信息.所以复合索引的第一个字段选取很重要.②
索引的选取和Statistics关系很大.这个直方图似的统计信息会展现当前表的数据的稠密和分布情况.
③
同样你可以考虑覆盖索引中的INCLUDE方式.
CREATE INDEX IX_LastName_FirstName ON tbl_TestCSDN(LastName)INCLUDE(FirstName)④ ... ...
select * from tb where a=@a or b=@b --不会用到索引的
select * from tb where a=@a and b=@b --才会用到索引的
where只有包含a和b列或者只包含A列内容是才会应用索引。
关于Index Scan和Index Seek
其中Index Scan和Table Scan类似。也即是一行行的扫描,不过这里对有序的数据页和索引项扫描.
Index Scan和Table Scan常常发生在没有过滤条件的查询里或则没有合适的的Search Argument(SARG)
Index Scan比Table Scan相对快 是以为Index Scan是对一个索引项对应的数据项列表作为一个逻辑读
然而Table Scan则是对每条数据做一个逻辑读.而Index Seek则是对范围进行搜索CREATE TABLE Test_CSDN
(id int,
v_code varchar(32),
v_name varchar(32),
v_detail varcahr(32))CREATE CLUSTERE INDEX Test_CSDN_v_code ON Test_CSDN( v_code )如果查询如下:①SELECT * FROM Test_CSDN WHERE v_code = 'S0001'②SELECT * FROM Test_CSDN WHERE v_code LIKE 'S%' ...MS SQL多半会选择Clustered Index Seek。原因是Test_CSDN_v_code维护了Test_CSDN的物理顺序,
而且这里的过滤条件恰是聚集索引字段。Seek比Scan快的原因是Seek限定了查询索引项的范围,
比如查询②,其实等效于 SELECT * FROM Test_CSDN WHERE v_code > = 'S' AND v_code < 't'Test_CSDN_v_code会首先在索引项(Index key + Page number)中找到S开头的v_code对应的page number,
然后根据改number 到数据页去查找数据.因此相对Clustered Index Scan而言,Clustered Index Seek范围要小.当然也要看SARG的过滤程度了.同理可以分析非聚集Index.--Ⅱ关于复合索引的测试相关--打开执行计划文本格式
SET STATISTICS PROFILE ON
GOSELECT COUNT(*) FROM T1 --1000SELECT * FROM T1 WHERE 1 = 0
----
a b xCREATE INDEX T1_a_b ON T1 (a,b)点击对象浏览器(Object Explorer)
点看T1表下的Statistics
Column Statistics: _WA_Sys_00000001_0425A276
Index Statistics: T1_a_b--查询分析SELECT * FROM T1 WHERE a = 12--因未建立聚集索引,故这里是RID Lookup,显然这里是Index Seek
/*
SELECT * FROM [T1] WHERE [a]=@1
|--Nested Loops(Inner Join, OUTER REFERENCES:([Bmk1000]))
|--Index Seek(OBJECT:([TestingShen].[dbo].[T1].[T1_a_b]), SEEK:([TestingShen].[dbo].[T1].[a]=(12)) ORDERED FORWARD)
|--RID Lookup(OBJECT:([TestingShen].[dbo].[T1]), SEEK:([Bmk1000]=[Bmk1000]) LOOKUP ORDERED FORWARD)
*/SELECT * FROM T1 WHERE b = 20 --因Statistic仅仅建立在字段a上所以不能像上面那样定位b的范围 故为Index Scan
/*
SELECT * FROM [T1] WHERE [b]=@1
|--Nested Loops(Inner Join, OUTER REFERENCES:([Bmk1000]))
|--Index Scan(OBJECT:([TestingShen].[dbo].[T1].[T1_a_b]), WHERE:([TestingShen].[dbo].[T1].[b]=(20)))
|--RID Lookup(OBJECT:([TestingShen].[dbo].[T1]), SEEK:([Bmk1000]=[Bmk1000]) LOOKUP ORDERED FORWARD)
*/--同理可以分析--OR因为将查询的范围扩大,故不可以在a的范围内限定数据
SELECT * FROM T1 WHERE b = 20 OR a = 12
--
/*
SELECT * FROM T1 WHERE b = 20 OR a = 12
|--Nested Loops(Inner Join, OUTER REFERENCES:([Bmk1000]))
|--Index Scan(OBJECT:([TestingShen].[dbo].[T1].[T1_a_b]), WHERE:([TestingShen].[dbo].[T1].[b]=(20) OR [TestingShen].[dbo].[T1].[a]=(12)))
|--RID Lookup(OBJECT:([TestingShen].[dbo].[T1]), SEEK:([Bmk1000]=[Bmk1000]) LOOKUP ORDERED FORWARD)
*/--AND可以将查询的范围缩小,因索引字段为a和b 而且statistic会为a而建立,所以这里也是Index Seek
SELECT * FROM T1 WHERE b = 20 AND a = 12
--
/*
SELECT * FROM [T1] WHERE [b]=@1 AND [a]=@2
|--Nested Loops(Inner Join, OUTER REFERENCES:([Bmk1000]))
|--Index Seek(OBJECT:([TestingShen].[dbo].[T1].[T1_a_b]), SEEK:([TestingShen].[dbo].[T1].[a]=(12) AND [TestingShen].[dbo].[T1].[b]=(20)) ORDERED FORWARD)
|--RID Lookup(OBJECT:([TestingShen].[dbo].[T1]), SEEK:([Bmk1000]=[Bmk1000]) LOOKUP ORDERED FORWARD)
*/
楼主的意思就是seek算利用 scan不算。