SQL SERVER 2000中如何让union all构造出来的视图(view)利用到索引

[ 2006-04-28 22:50:13 | 作者: progame ]
文字大小: | |

?当我们把几个表的某些字段抽取出来,然后用union all创建出一个view时,我们总希望这些表的索引能够在针对视图的查询时有效。很久以前,我凭着对sql server的SQL自动优化的超级相信,想当然地以为它能够做到这点。但是sql2000让我失望并且痛苦了一回。

?假设我们有这样的两个表
?X(a,b) Y(a)
?在X上有分别针对a和b建立的索引IX_X_a,和IX_X_b,在Y上有索引IX_Y_a

接下来我们构造一个这样的 view(V)

select a,b from X
union all
select a,a from Y

然后我们对这样的两个查询进行分析:
1、select * from V where a = @s
2、select * from V where b = @s

看看执行计划,发现什么了吗? 对,在查询2中很悲惨地对Y表进行了全表扫描! 当Y表的数据越来越大,这个查询的速度就会越来越慢,缺少SEEK的下场可想而知。而据说,这个问题在sql2005中得到了解决,我们只能对现在仍不敢使用的2005再多一份期盼了。

那么在2000中我们无法去解决这个问题呢,放弃使用view?不行,这个view被大量多次地使用。使用分区视图?也不行,分区视图指的是这些用到的字段必须是相同。其实分区视图和2005的分区表是有些类似的。而此场景下的X,Y表完全是两个不同的东西(实际上X还有很多列,Y也还有很多列)。

我的解决方法就是对Y表增加一个b列,让它的值等于a,首当其冲的就是使用计算列了,formula为[a],再对视图查询看看,OK了,两个索引都会被利用到了。但是问题还是有的,在接下来的合并复制(Merge Replication)中,我遇到了意料不到的错误(此是后话,按下不表)!!! 所以我现在使用了trigger来做这件事,在insert时update b = a。

除了复制,这个视图仍然不够聪明,我实际上的视图大概是这样的:
select 'X' as type,a,b from X
union all
select 'Y' as type,a,b from Y

当我使用查询如下时
select * from V where type = 'X' and a = @s

SQL2000并不会聪明地只去对X表查询,它仍然对X,Y两个表都进行了索引上的SEEK操作,要知道,实际使用的这个V我union了8个表啊,这样操作时间就是8*T! 有人说了,在这个V上建立索引吧,这样可以时间减少到3+T了,事实上我尝试了这个操作,但后来我放弃了,VIEW上能够创建索引的前提条件太多了,我无法满足它,所以最终,我依然在8*T的日子中继续我的生活....

评论Feed 评论Feed: /feed.asp?q=comment&id=24

浏览模式: 显示全部 | 评论: 4 | 引用: 0 | 排序 | 浏览: 3085
引用 zero*
[ 2008-08-11 14:55:46 ]
哈哈哈哈哈哈哈
引用 htz
[ 2008-09-12 10:23:25 ]
我也遇到这个棘手的问题了。 [confused]

32个地市单位数据 用 SQL2000的数据同步复制 来做同步。
由于 SQL 有个非常 恶心的bug,就是如果 32 个地市都同步到同一个库中时 ,
那么从 第 3 个同步库开始会出现 “无法同步更新”的问题。
所以最后 把“每个单位的库”都同步到“中心的每个单位库”中,然后用 视图 构造了一个 视图库。

我所有的表结构都是一样的。但是现在很慢很慢,大概要5、6分钟。
同样的数据量,如果在一个库中只要 5-15秒。

不知道你是否有更好的解决办法。
引用 htz
[ 2008-09-12 11:10:32 ]
希望加msn聊,或QQ
引用 progame
[ 2008-09-12 19:36:25 ]
办法上面已经写了 我不和陌生人说话

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