MySQL 视图如何工作?

Posted

技术标签:

【中文标题】MySQL 视图如何工作?【英文标题】:How do MySQL views work? 【发布时间】:2011-02-22 02:56:06 【问题描述】:

当我创建一个视图时,我基本上是在创建一个新表,当它连接的其中一个表中的数据发生变化时,它将自动进行事务处理;对吗?

另外为什么我不能在我的视图中使用子查询?

【问题讨论】:

【参考方案1】:

视图的工作原理类似于表格,但它不是表格。它永远不存在;它只是在您引用视图名称时运行的准备好的 SQL 语句。即:

CREATE VIEW foo AS
  SELECT * FROM bar

SELECT * FROM foo

...相当于运行:

SELECT x.* 
  FROM (SELECT * FROM bar) x

mysqlDump 永远不会包含要插入到视图中的行...

另外为什么我不能在我的视图中使用子查询????

遗憾的是,这是(尽管有问题)设计的。 MySQL 视图有许多限制,记录在案:http://dev.mysql.com/doc/refman/5.0/en/create-view.html

那么,如果它只是一个虚构的表/准备好的语句,这是否意味着它在理论上具有与普通表/查询相同(甚至更低)的性能?


没有。 一个表可以有关联的索引,这可以使数据检索更快(插入/更新需要一些成本)。一些数据库支持“物化”视图,即可以应用索引的视图 - 鉴于有限的视图功能(仅从 v5 开始,MySQL 不支持这不足为奇) IIRC,游戏很晚)。

由于视图是派生表,因此视图的性能仅与构建它的查询一样好。如果该查询很糟糕,性能问题只会滚雪球......也就是说,在查询视图时 - 如果 WHERE 子句中的视图列引用未包含在函数中(即:WHERE v.column LIKE ...not WHERE LOWER(t.column) LIKE ...),优化器可能会将条件(称为谓词)推送到原始查询中 - 使其更快。

【讨论】:

不知道 MySQL 不能做子查询...很高兴知道。 @Slokun:MySQL 视图不能使用子查询——在典型的 SQL 语句中子查询是可以的。 那么,如果它只是一个虚构的表/准备好的语句,这是否意味着它在理论上具有与普通表/查询相同(甚至更低)的性能? 是的,我说错了。以前在 MySQL 中完成过子查询,但我认为我不需要在其中创建视图。 @Slokun:不用担心 - 我只是迂腐,因为过去有误解。【参考方案2】:

我也遇到了同样的问题(令我惊讶的是,因为我的搜索似乎表明 Oracle 和 MS 确实支持它)。

我通过为我的最终视图创建两个额外的视图来绕过这个限制(至少现在,直到证明不可用)。

例子:

CREATE VIEW Foo1 AS
    SELECT * FROM t ORDER BY ID, InsertDate DESC

CREATE VIEW Foo2 AS
    SELECT * FROM Foo1 GROUP BY ID

CREATE VIEW Foo AS
    SELECT * FROM Foo2 ORDER BY ID

上面的例子基本上有一个表't',它是一个包含所有修订的临时表。我的“Foo”(视图)基本上是一个简单视图,仅包含我对每条记录的最新修订。现在似乎可以正常工作!

更新:

我不知道这是否是 MySQL 5.1 中的另一个错误,但上面的示例实际上不起作用! “Foo1”按预期工作,但“Foo2”似乎在分组之前忽略了顺序,所以我的最终结果不是预期的。如果我将“ASC”的“DESC”更改为“ASC”,我什至会得到相同的结果(令人惊讶)。

此外,如果您阅读了 17.5.1。查看语法部分,它明确指出:

“视图可以由多种 SELECT 语句创建。它可以引用基表或其他视图。它可以使用连接、UNION 和子查询。”

我将把我的数据库更新到 5.6,然后再试一次!

【讨论】:

结论是,似乎没有 MySQL 可以修复视图中的分组错误。所以出于这个原因,没有任何效果,我尝试了几乎所有我能拿到的该死的版本。这对 MySQL 来说是可悲的......真的期待更多!【参考方案3】:

区别在于:

对于视图,您只能在 where - 部分有子查询,而不是在 from - 部分,所以一个

CREATE VIEW v AS SELECT * FROM foo WHERE id IN (SELECT id FROM bar) 

会工作 - 但同时你会得到一个只读视图......单个表上的简单视图将允许“通过”视图更新到基础表

【讨论】:

我也有一个带有左连接的子查询

以上是关于MySQL 视图如何工作?的主要内容,如果未能解决你的问题,请参考以下文章

在读提交的事务隔离级别下,MVCC 机制是如何工作的?

MySQL视图存储过程与存储引擎

SwiftUI - 如何关闭工作表视图,同时关闭该视图

MySQL必知应会-第22章-使用视图

在 Laravel 4 中通过迁移脚本创建 MySQL 视图

Alamofire 完成工作后如何加载视图?