简单联合的情况下的SQL查询性能

时间:2013-08-30 05:02:29

标签: sql performance sql-server-2008 view union

我有一个简单的查询调优问题,它是

我们可以改进定义为

的视图的性能

SELECT * FROM A UNION ALL SELECT * FROM B

这表现得非常糟糕,以至于6.5k记录需要12秒

感谢任何帮助。

3 个答案:

答案 0 :(得分:4)

这样的union视图的问题是优化器无法通过视图访问表的原始列,所以当您使用时,这样的视图:< / p>

select * from myview where foo = 5

where子句是视图提供的整个行集上的过滤器,因此 all 处理来自两个表的行 之后的联合,因此不会使用任何索引。

为了对性能有任何希望,你必须以某种方式获得你希望视图中的条件并应用于每个表,但保持变量以便你可以申请使用它时的标准不同。

我找到了解决这个问题的方法。它有点hacky,并不适用于并发使用,但它的工作原理!试试这个:

 create table myview_criteria(val int);
 insert into myview_criteria values (0); -- it should have exactly one row

 create view myview as
 SELECT * FROM A
 WHERE foo = (select val from myview_criteria)
 UNION ALL
 SELECT * FROM B
 WHERE foo = (select val from myview_criteria);

然后使用它:

update myview_criteria set val = 5;
select * from myview;

假设foo上有索引,将使用该索引。

这里要小心,因为很明显,当同时执行多个执行时,这种技术不起作用。

答案 1 :(得分:1)

有没有理由你把这两个不在同一张桌子里,无论你做什么,最终都会很糟糕。如果可能,请考虑迁移到一个表。如果没有,您可以通过将它们全部插入同一个内容来“实现视图”。


话虽如此,你不会在联盟上选择*,如果视图顶部有特定条件,则可以通过索引该列来提高性能。

如果你告诉大家这是什么特定的数据库会有所帮助。

答案 2 :(得分:0)

我最好的建议是将源表中返回的数量或记录限制为您真正需要的数量,并确保您的数据被正确编入索引。

不要使用*,除非它是一个临时脚本(即使这样,列出列仍然会更好)只包含您手头任务真正需要的列。

根据最常用的查询使用正确的索引。删除所有未使用的索引删除所有重复的索引。

Pluralsight有一个关于MS SQL Server查询性能调优的精彩课程。 http://www.pluralsight.com/training/Courses/TableOfContents/query-tuning-introduction

该课程由Vinod Kumar和Pinal Dave提出,他们是两位非常杰出的人。

您还可以查看Pinal关于SQL Server性能的文章,以帮助指出您可能没有想过的领域。

http://blog.sqlauthority.com/sql-server-performance-tuning/