7

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

我们可以提高定义为的视图的性能吗

SELECT * FROM A UNION ALL SELECT * FROM B

这表现太差了,6.5k 条记录需要 12 秒

任何帮助表示赞赏。

4

3 回答 3

7

像这样的视图的问题union是优化器无法通过视图访问表的原始列,因此当您使用这样的视图时:

select * from myview where foo = 5

where 子句是视图传递的整个行集的过滤器,因此两个表中的所有行都在联合之后处理,因此不会使用索引。

为了对性能抱有任何希望,您必须以某种方式在视图中获取所需的条件并将其应用于每个表,但要使其保持可变,以便在使用时可以应用不同的标准。

我找到了一种解决方法。它有点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,将使用该索引。

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

于 2013-08-30T06:03:01.163 回答
1

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


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

如果你告诉每个人这是什么特定的数据库,这将有所帮助。

于 2013-08-30T05:21:23.233 回答
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/

于 2013-08-30T05:29:12.910 回答