MySQL视图是如何工作的?
当我创建一个视图时,我基本上是在创建一个新表,当它所连接的其中一个表中的数据发生变化时,该表将自动进行事务处理;对吗 还有,为什么不能在视图中使用子查询?视图的工作原理类似于表,但它不是表。它从不存在;它只是在引用视图名称时运行的准备好的SQL语句。即:MySQL视图是如何工作的?,sql,mysql,sql-view,Sql,Mysql,Sql View,当我创建一个视图时,我基本上是在创建一个新表,当它所连接的其中一个表中的数据发生变化时,该表将自动进行事务处理;对吗 还有,为什么不能在视图中使用子查询?视图的工作原理类似于表,但它不是表。它从不存在;它只是在引用视图名称时运行的准备好的SQL语句。即: CREATE VIEW foo AS SELECT * FROM bar SELECT * FROM foo …相当于运行: SELECT x.* FROM (SELECT * FROM bar) x MySQLDump永远不会
CREATE VIEW foo AS
SELECT * FROM bar
SELECT * FROM foo
…相当于运行:
SELECT x.*
FROM (SELECT * FROM bar) x
MySQLDump永远不会包含要插入到视图中的行
还有,为什么我不能在视图中使用子查询
可悲的是,这是出于(尽管值得怀疑)设计。MySQL视图有很多限制,有文档记录:
那么,如果它只是一个虚构的表/准备好的语句,这是否意味着它在理论上具有与普通表/查询相同的性能(甚至更低)?
否。
一个表可以有相关联的索引,这可以使数据检索更快(插入/更新需要付出一定的代价)。一些数据库支持“物化”视图,即可以应用索引的视图-鉴于视图功能有限(仅从v5 IIRC开始,游戏进行得很晚),MySQL不支持也就不足为奇了
因为视图是一个派生表,所以视图的性能仅与它所基于的查询一样好。如果这个查询糟糕透顶,那么性能问题就会越滚越大。。。也就是说,当查询视图时-如果WHERE子句中的视图列引用未包装在函数中(即:
WHERE v.column LIKE…
,notWHERE LOWER(t.column)LIKE…),优化器可能会推送条件(称为谓词)我也遇到了同样的问题(令我惊讶的是,因为我的搜索似乎表明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中的另一个bug,但上面的例子实际上不起作用!“Foo1”按预期工作,但“Foo2”似乎忽略了分组前的顺序,因此我的最终结果不是预期的结果。如果我将“DESC”改为“ASC”,我甚至会得到同样的结果(令人惊讶)
此外,如果您阅读17.5.1。查看语法部分,它清楚地说明:
视图可以由多种SELECT语句创建。它可以引用基表或其他视图。它可以使用联接、联合和子查询
我要将我的数据库更新到5.6,然后再试一次 区别在于:
对于视图,只能在where-part中有子查询,而不能在from-part中有子查询
CREATE VIEW v AS SELECT * FROM foo WHERE id IN (SELECT id FROM bar)
可以-但同时您可以获得只读视图。。。单个表上的简单视图将允许“通过”视图更新到底层表不知道MySQL无法执行子查询。。。很高兴知道。@Slokun:MySQL视图不能使用子查询-子查询在典型的SQL语句中很好。因此,如果它只是一个虚构的表/准备好的语句,这是否意味着它在理论上具有与普通表/查询相同的性能(甚至更低)?是的,我说错了。以前在MySQL中做过子查询,但我认为我从来没有必要在其中创建视图。@Slokun:不用担心,我只是学究,因为过去有过误解。结论是,似乎没有MySQL能够修复视图中的分组错误。所以,由于这个原因,什么都不管用,我几乎尝试了我能得到的每一个该死的版本。这是MySQL的悲哀。。。真的期待更多!我也有一个左连接的子查询