5.6.2 视图对性能的影响

5.6.2  视图对性能的影响

Performance Implications of Views

许多人都不认为视图可以改进性能,但是它确实可以提高性能,也可以用它来支持其他提高性能的方式。例如,利用视图重构数据库架构的某一阶段,可以在更改它访问的表的同时,使代码继续工作。

一些应用程序为每一个用户使用一个表,这通常是为了实现行级别安全性。一个和前面例子类似的视图能够在表内实现类似的安全性,并且打开表的次数会更少,这有助于提高性能。被很多用户使用的许多开源工程已经累积了上百万张表,它们可以从这种方式得益。下面有一个假想的博客系统数据库:

 
  
  1. CREATE VIEW blog_posts_for_user_1234 AS 
  2.     SELECT * FROM blog_posts WHERE user_id = 1234  
  3.     WITH CHECK OPTION;  

可以使用视图实现列级权限,但是却没有实际创建这些权限的开销。列级权限也会阻止查询被缓存。视图可以限制访问想要的列,但却不会导致这些问题:

 
  
  1. CREATE VIEW public.employeeinfo AS 
  2.     SELECT firstname, lastname -- but not socialsecuritynumber  
  3.     FROM private.employeeinfo;  
  4. GRANT SELECT ON public.* TO public_user; 

有时可以使用伪临时视图取得好的效果。这不用创建一个只在当前连接中存在的真正临时视图,而是用一种特殊的方式,比如在特定的数据库中,创建一个视图,在使用完之后就可以把它删除。接下来就可以在FROM子句中使用这个视图,就像在FROM子句中使用子查询一样。这两种方式在理论上是一样的,但是MySQL对视图有不同的代码库(Codebase),所以通过临时视图可能会得到更好的性能。下面是一个例子:

 
  
  1. -- Assuming 1234 is the result of CONNECTION_ID( )  
  2. CREATE VIEW temp.cost_per_day_1234 AS 
  3.     SELECT DATE(ts) AS daysum(cost) AS cost  
  4.     FROM logs.cost  
  5. GROUP BY day;  
  6.  
  7. SELECT c.day, c.cost, s.sales  
  8. FROM temp.cost_per_day_1234 AS c  
  9. INNER JOIN sales.sales_per_day AS s USING(day);  
  10.  
  11. DROP VIEW temp.cost_per_day_1234; 

要注意到使用了连接ID作为唯一的后缀,以避免名字冲突。这种方式在应用程序崩溃并无法删除临时视图时可以比较方便地进行清理。请查看第394页的"丢失的临时表"了解更多细节。

使用了临时表算法的视图性能可能会很差(尽管它们比没有使用视图的同样查询性能会好一些)。MySQL在优化外部查询的时候就使用递归的步骤执行了它,这时外部查询的优化还没有完成,所以它没有得到完全的优化。构造临时表的查询不会从外部查询中得到WHERE条件,并且临时表没有索引。下面仍然使用temp.cost_per_ day_1234举一个例子:

 
  
  1. mysql> SELECT c.day, c.cost, s.sales  
  2.      -> FROM temp.cost_per_day_1234 AS c  
  3.      ->     INNER JOIN sales.sales_per_day AS s USING(day)  
  4.      ->     WHERE day BETWEEN '2007-01-01' AND '2007-01-31'

在服务器执行这个视图,把结果放到临时表,然后联接sales_per_day表的过程中,到底发生了什么呢?WHERE子句中的BETWEEN限制没有被"推送"到视图中,所以视图会为表中的所有日期创建结果,这不会有什么问题,因为服务器将会把临时表排在联接的第一位,所以联接就可以使用sales_per_day表的索引。但是,如果将这样的两个视图进行联接,那么就不会有任何索引的优化了。

如果想用视图来提高性能,那么总是要进行测试,至少也应该进行分析。甚至合并视图也会增加开销,并且很难预测视图如何影响性能。如果有性能问题,永远也不要猜测,一定要进行测量。

视图引入了一些并非只有MySQL才有的问题。视图会误导开发人员,认为它非常简单,但实际上它非常复杂。某些查询看上去是反复查询一个表,但实际是查询一个代价很高的视图,一个不理解它潜在复杂性的开发人员会对这个现象无动于衷。我们曾经看到过一个很简单的查询在解释器中输出了上百条记录,因为其中某些表其实是视图,而它们又引用了很多其他的表和视图。

转自:http://book.51cto.com/art/201001/181019.htm

你可能感兴趣的:(MySql)