日期:2014-05-18  浏览次数:20505 次

求高手指导:一条sql语句引发的诸多疑问
SQL code
SELECT TOP 10 * FROM tgongwen WHERE gid > (SELECT MAX(gid) FROM (SELECT TOP 20 gid FROM tgongwen) AS T)

这是我的sql语句,表tgongwen 循环插入了1000万条数据,我在列gid上建立了非聚集索引,在另外一列(日期列)上建立了非聚集索引,gid列是以步长为1自增的。我上面的语句是想查询出gid从21到30的10条记录,执行后,问题出现了,返回的结果集为空,我特意执行了SELECT TOP 20 gid FROM tgongwen这个子查询返回的gid从1到20,但执行SELECT MAX(gid) FROM (SELECT TOP 20 gid FROM tgongwen) AS T这一句时返回的不是20,却是整个表中gid的最大值,所以导致最终返回的是空结果集。但为什么会这样呢?我始终弄不明白,求高手解答!
  另外,在这条语句的基础上,我又产生了其他疑问,也不知其所以然,问题如下:
  1、如果我直接执行整条语句,执行时间很慢,差不多有一分钟,但是如果改为:
SELECT TOP 10 gid FROM tgongwen WHERE gid > (SELECT MAX(gid) FROM (SELECT TOP 20 gid FROM tgongwen) AS T),执行效率就很快了。前后对比,gid列上的索引有没有起作用,或者说至查询出索引列和查询出所有列之间有什么区别?
  2、WHERE 条件中直接改为WHERE gid>(gid最大值)后,无论是查询出所有列还是只查询出gid列,两者的效率都相差不大,并且都很快。说明gid列上的索引起作用了,但为什么最上面语句的查询却很慢了?
  3、另外一条语句:select distinct fariqi from tgongwen,日期列fariqi上建立了聚集索引,当使用distinct查询时的消耗在6s左右,但去掉distinct后消耗的时间远远大于使用distinct消耗的时间,用了一分四十几秒,这没道理啊!同样是查询索引列,而且distinct开销更大,不使用distinct应该要比使用distinct开销要小得多,现在为什么反过来了?
  由于是新手,刚接触索引,上面是我做测试的时候遇到的一些问题,我尝试查看sql的执行计划,也没能找出合理的解释,还望高手帮忙解答,小弟先谢谢了!

------解决方案--------------------
SQL code

SELECT TOP 10
        *            --如果是gid的话,走索引了,就会快的
FROM    tgongwen
WHERE   gid > ( SELECT  MAX(gid)             --如果直接给出一个值的话,也会走索引,Ctrl+L 看一下执行计划便知
                FROM    ( SELECT TOP 20      --没有排序的话这个top 20 是哪20个呢?
                                    gid
                          FROM      tgongwen
                        ) AS T
              )

------解决方案--------------------
SQL code

但执行SELECT MAX(gid) FROM (SELECT TOP 20 gid FROM tgongwen) AS T这一句时返回的不是20,却是整个表中gid的最大值,所以导致最终返回的是空结果集。但为什么会这样呢?

--是因为GID上的索引造成的。SQLSERVER直接对表执行了索引查找而非你产生的临时结果集查找。如果去掉索引就没有问题了。

------解决方案--------------------
SQL code
set showplan_all on
go
SELECT MAX(gid) FROM (SELECT TOP 20 gid FROM tgongwen) AS T

看看你的执行计划你就会理解了

------解决方案--------------------
SQL code
先解决你的问题
SELECT TOP 10 * FROM tgongwen WHERE gid > (SELECT MAX(gid) FROM (SELECT TOP 20 gid FROM tgongwen order by gid asc) AS T 
--这样可以得到你想要的结果。