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 视图如何工作?的主要内容,如果未能解决你的问题,请参考以下文章