mysql - 在 MySQL 视图中,以 union 开头还是以 union 结尾更快?
问题描述
我的数据库有多个表,其中有一些匹配的列,但名称和顺序不同。
例如
Table1: FullName Grade Foo
Table2: Bar Rank WholeName
什么会更快:
1)1个视图,对每个表重复相同的查询
CREATE View Test AS
SELECT SUBSTRING_INDEX(SUBSTRING_INDEX(FullName, ' ', 1), ' ', -1) AS "First Name",
If (Grade<50, "Bad", "Good") AS "Type"
FROM table1
UNION
SELECT SUBSTRING_INDEX(SUBSTRING_INDEX(WholeName, ' ', 1), ' ', -1) AS "First Name",
If (Rank<50, "Bad", "Good") AS "Type"
FROM table2
或者
2) 2 个视图,一个用于纯合并,另一个用于操作
CREATE View Test1 AS
SELECT FullName AS "First Name", Grade AS "Type"
FROM table1
UNION
SELECT WholeName AS "First Name", Rank AS "Type"
FROM table2
CREATE View Test2 AS
SELECT SUBSTRING_INDEX(SUBSTRING_INDEX(`First Name`, ' ', 1), ' ', -1) AS "First Name",
If (Type<50, "Bad", "Good") AS "Type"
FROM Test1
显然 1) 更复杂,因为你必须重复每一个操作。如果你有 10 张桌子,那就意味着重复同样的操作 10 次。如果你有 10 个操作,那就意味着编写 100 个操作而不是 10 个操作。但如果它更快,我会接受。
http://www.sqlfiddle.com/#!9/48d531/1建议大致相同的时间,尽管在某些运行中它有利于 2)。
请记住,其中涉及大量数据,实际 SQL 非常复杂,并且涉及 LEFT JOIN。
解决方案
AVIEW
是语法糖——试试等效的SELECT
。
“糖”论点说,在解决了 Q2 之后是这样的VIEWs
:
SELECT SUBSTRING_INDEX(SUBSTRING_INDEX(`First Name`,
' ', 1), ' ', -1) AS "First Name",
If (Type<50, "Bad", "Good") AS "Type"
FROM ( SELECT .. UNION SELECT .. )
FROM ( ... )
称为“派生”表。它通常会变成一个临时表,从中执行其余的选择。这是 Q1 中避免的额外的、中等重量的步骤。
实际上,您可能不会注意到性能上的差异。
为了处理派生表(FROM 子句中的子查询)或视图引用,优化器可以将派生表或视图引用具体化到内部临时表或将其合并到外部查询块中。以前,派生表总是被物化,而等效的视图引用有时被物化,有时被合并。这种对等价查询的不一致处理可能会导致性能问题:不必要的派生表实现需要时间并阻止优化器将条件下推到派生表。
这意味着您的问题的答案取决于您使用的 MySQL 版本。
服务器不再为满足特定条件的 UNION 语句使用临时表。相反,它从临时表创建中只保留执行结果列类型转换所需的数据结构。该表没有完全实例化,没有行被写入或读取;行直接发送到客户端。结果是减少了内存和磁盘需求,并且在将第一行发送到客户端之前的延迟更小,因为服务器不需要等到最后一个查询块被执行。EXPLAIN 和优化器跟踪输出将更改:UNION RESULT 查询块将不存在,因为该块是从临时表中读取的部分。... 错误 #50674
推荐阅读
- mongodb - 我如何在 mongodb 中使用它的“键”过滤地图
- javascript - 试图在谷歌表上添加带有时间戳的列
- docker - 在 Docker 项目中更改 gem fork 会导致 GitHub CI 测试失败
- javascript - 在 Jest 上选择性地模拟一个函数
- javascript - 有没有办法隐藏确认框而不带标题
- delphi - 如何在 idTCPServer OnExecute 过程中从数据库和文件中获取数据是线程安全的?
- android - 有没有人知道在 Android 的 PayU 集成中做反向哈希
- java - 除了 return secondpass 之外,正确的 return 语句是什么?
- vb.net - 无法从数据库中检索数据以用作循环中的变量
- ios - 从 Fabric 迁移到 Firebase 时,我应该更改 dsym 文件上传脚本吗?