正文

SQL SERVER 2000中如何让union all构造出来的视图(view2006-07-24 14:46:00

【评论】 【打印】 【字体: 】 本文链接:http://blog.pfan.cn/Csharpsky/16791.html

分享到:

当我们把几个表的某些字段抽取出来,然后用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的日子中继续我的生活....

阅读(4428) | 评论(0)


版权声明:编程爱好者网站为此博客服务提供商,如本文牵涉到版权问题,编程爱好者网站不承担相关责任,如有版权问题请直接与本文作者联系解决。谢谢!

评论

暂无评论
您需要登录后才能评论,请 登录 或者 注册