--创建表
if OBJECT_ID('news') is not null
drop table news
create table news
(
news_id bigint primary key,
news_content varchar(8000),
news_datetime datetime
)--为时间列建立索引
create index idx_datettime on news(news_datetime)
如上代码所示,创建一个新闻表news,其中有3列分别是ID,新闻内容,添加时间;其中news_id为默认的聚集索引,手动为“添加时间”列加上了非聚集索引;
我在书上看到非聚集索引只能返回索引关键列,也就是说我只查询时间列是高效的,如下:select news_datetime from news 
where news_datetime between '2010-08-18 16:03' and '2010-08-18 16:04'
如果我一次性查询所有的列用select *,SQL Server的执行计划会直接用聚集索引扫描所有的行,这个时候news_datetime的索引是不是就没什么效果了,下面是执行计划的IO情况:select * from news 
where news_datetime between '2010-08-18 16:03' and '2010-08-18 16:04'
表'news'。扫描计数1,逻辑读取23045 次,物理读取0 次,预读0 次,lob 逻辑读取0 次,lob 物理读取0 次,
因为非聚集所以默认情况下,都包含本表的聚集索引列,也就是说我用news_datetime作谓词查找,只查询news_id 是索引查找,而不是扫描,然后我突发奇想写下这样的SQL:select * from news where news_id in(
select news_id from news
where news_datetime between '2010-08-18 16:03' and '2010-08-18 16:04')表面上看多了个嵌套,但我惊奇的发现尽管这条SQL长,看似复杂,但是IO情况却比上面要好,如下:
表'news'。扫描计数2,逻辑读取19016 次,物理读取0 次,预读0 次,lob 逻辑读取0 次,lob 物理读取0 次,最后我看执行时间的确下面比上面的好快不少。虽然效率差别不大,但是心中有疑惑,还忘各位SQL大人帮忙看下;区别到底在哪里,他们内在的执行的机制和顺序有何不同!

解决方案 »

  1.   

    别灌水,最近被一个搞DBA的BS了,所以想好好的学习下SQL
      

  2.   

    两者的执行计划有明显差别SELECT * FROM [news] WHERE [news_datetime]>=@1 AND [news_datetime]<=@2
      |--Clustered Index Scan(OBJECT:([Northwind].[dbo].[news].[PK__news__4C27CCD84E88ABD4]), WHERE:([Northwind].[dbo].[news].[news_datetime]>='2010-08-18 16:03:00.000' AND [Northwind].[dbo].[news].[news_datetime]<='2010-08-18 16:04:00.000'))select * from news where news_id in(      select news_id from news          where news_datetime between '2010-08-18 16:03' and '2010-08-18 16:04')
      |--Nested Loops(Inner Join, OUTER REFERENCES:([Northwind].[dbo].[news].[news_id]))
           |--Index Seek(OBJECT:([Northwind].[dbo].[news].[idx_datettime]), SEEK:([Northwind].[dbo].[news].[news_datetime] >= '2010-08-18 16:03:00.000' AND [Northwind].[dbo].[news].[news_datetime] <= '2010-08-18 16:04:00.000') ORDERED FORWARD)
           |--Clustered Index Seek(OBJECT:([Northwind].[dbo].[news].[PK__news__4C27CCD84E88ABD4]), SEEK:([Northwind].[dbo].[news].[news_id]=[Northwind].[dbo].[news].[news_id]) ORDERED FORWARD)
      

  3.   

    再来看扫描Option
    PhysicalOp LogicalOp
    SELECT * FROM [news] WHERE [news_datetime]>=@1 AND [news_datetime]<=@2
    NULL NULL
    Clustered Index Scan Clustered Index Scanselect * from news where news_id in(      select news_id from news          where news_datetime between '2010-08-18 16:03' and '2010-08-18 16:04')
    PhysicalOp LogicalOp
    NULL NULL
    Nested Loops Inner Join
    Index Seek Index Seek
    Clustered Index Seek Clustered Index Seek
      

  4.   

    能使用聚集索引就尽量使用聚集索引,这句话跟我的情况完全不符啊第一条sql的执行计划是100%的聚集索引查找第二条是52%,非聚集索引1%,sort是22%,marge join是25%,
    但是第二条明细比第一条要快