Sql Server 2005 还真是聪明了很多

[ 2007-06-25 17:22:44 | 作者: progame ]
文字大小: | |
表Test 只有一个字段 name 为主键
有这样的一个查询, 因为是自动生成的, 看上去稍为有点晕:
SELECT [name] FROM (SELECT * FROM [Test] WHERE 1=0 OR (1=1 AND (1=0 OR ([name] IN ('A','B')) OR ([name] IN ('C'))) AND NOT ([name]='B')) OR (1=1 AND (1=0 OR ([name] IN ('C','D'))) AND NOT ([name] IN ('E')))) AS [Test]

其实它就是要查: (( A or B or C ) and not B) or (( C or D ) and not E)
在 sql2000 中, 执行计划是这样的, 做 cluster index scan, 然后自然在scan时要有一个 predicate:
(((([Test].[name]='B' OR [Test].[name]='A') OR [Test].[name]='C') AND [Test].[name]<>'B') OR (([Test].[name]='D' OR [Test].[name]='C') AND [Test].[name]<>'E')))

1=0 1=1 这些没必要的东西过滤掉了, 看上去似乎让人很满意了

但是, 再拿到 sql2005 中试一下, 高下立判:
Clustered Index Seek(OBJECT:([TBP].[dbo].[test].[PK_TEST]), SEEK:([TBP].[dbo].[test].[name]=N'A' OR [TBP].[dbo].[test].[name]=N'C' OR [TBP].[dbo].[test].[name]=N'D') ORDERED FORWARD)

预处理显得要"聪明"太多了, 直接已经提取出了最后的过滤表达式, 从而可以直接进行 SEEK, 要知道 SEEK 和 Scan 的速度可是天差地别, 尤其是在大数据量情况下, 演示表我只有5条记录, 然后看 Sql2000 中对于原始 sql 和2005实际执行的 sql 速度差别吧: 执行时间分别是91.98%和8.02%

在 MySQL 中同样试了一下执行计划:
id  select_type  table  type  possible_keys  key  key_len  ref  rows  Extra
1  PRIMARY  <derived2>  ALL  \N  \N  \N  \N  3  
2  DERIVED  <derived3>  ALL  \N  \N  \N  \N  3  Using where
3  DERIVED  Test  range  PRIMARY  PRIMARY  767  \N  3  Using where

结果还是很令人满意的, 在第一个字查询中成功地利用了索引只扫描了需要的3行数据
评论Feed 评论Feed: /feed.asp?q=comment&id=851

这篇日志没有评论.

发表
表情图标
[smile] [confused] [cool] [cry]
[eek] [angry] [wink] [sweat]
[lol] [stun] [razz] [redface]
[rolleyes] [sad] [yes] [no]
[heart] [star] [music] [idea]
UBB代码
转换链接
表情图标
悄悄话
用户名:   密码:   (非注册用户不需要输入密码) 注册?
验证码(不区分大小写) * 请输入验证码