问小白 wenxiaobai
资讯
历史
科技
环境与自然
成长
游戏
财经
文学与艺术
美食
健康
家居
文化
情感
汽车
三农
军事
旅行
运动
教育
生活
星座命理

FULL OUTER JOIN和UNION ALL:MySQL里这俩怎么选?

创作时间:
作者:
@小白创作中心

FULL OUTER JOIN和UNION ALL:MySQL里这俩怎么选?

引用
网易
1.
https://www.163.com/dy/article/JQ28DPK705567OCA.html

在MySQL中,FULL OUTER JOIN和UNION ALL是两种常用的数据合并方式,但它们在使用场景和性能上存在显著差异。本文将深入探讨这两种方法的优缺点、适用场景以及性能优化技巧,帮助开发者在实际项目中做出更合适的选择。

FULL OUTER JOIN的模拟实现

MySQL原生不支持FULL OUTER JOIN,但我们可以用UNION来模拟。简单来说,FULL OUTER JOIN会把两个表的所有数据都拿出来,哪怕有一方匹配不到,也会用NULL填充。

假设我们有两个表,一个是orders存订单,一个是users存用户,现在要把两张表里的数据合并,看看哪些订单没有匹配到用户,哪些用户没有订单。

SELECT * FROM (
    SELECT users.*, orders.*
    FROM users
    LEFT JOIN orders ON users.id = orders.user_id
    UNION
    SELECT users.*, orders.*
    FROM users
    RIGHT JOIN orders ON users.id = orders.user_id
) AS combined

这样,所有订单和所有用户都会被展示出来,没匹配到的地方用NULL填充。

UNION ALL的使用场景

如果你只是想把两个表的数据合并,但不在乎有没有重复数据,那UNION ALL就很合适。

UNION ALL不会去重,查询速度比UNION快得多,适用于数据量大、不需要去重的场景,比如日志数据合并、历史记录查询等。

SELECT * FROM users
UNION ALL
SELECT * FROM orders

如果你是想模拟FULL OUTER JOIN的效果,想要把所有数据都展示出来,还要填充NULL,就用UNION模拟。如果只是把两个表数据合起来,不在乎重复,就用UNION ALL,速度快,SQL语句也简单。

可能遇到的问题和优化方案

1. 查询慢?加索引!

如果数据量大,FULL OUTER JOIN模拟查询会很慢,因为UNION需要遍历两次数据。加上索引可以提升性能:

CREATE INDEX idx_user_id ON users(id);
CREATE INDEX idx_order_user_id ON orders(user_id);

这样MySQL查询时会用索引加速匹配。

2. NULL太多?用IFNULL()填充默认值!

有些地方匹配不到会变成NULL,如果不想看到一堆空值,可以用IFNULL()设置默认值:

SELECT IFNULL(users.name, 'Unknown') AS user_name, orders.*
FROM users
LEFT JOIN orders ON users.id = orders.user_id
UNION
SELECT IFNULL(users.name, 'Unknown') AS user_name, orders.*
FROM users
RIGHT JOIN orders ON users.id = orders.user_id

这样查询出来的数据就不会出现NULL,看起来更直观。

性能对比:FULL OUTER JOIN(模拟) vs. UNION ALL

因为 MySQL 原生不支持 FULL OUTER JOIN,所以我们只能用 LEFT JOIN + RIGHT JOIN + UNION 来模拟。这种方式的核心逻辑是:

  • LEFT JOIN 取出左表的所有数据,并匹配右表,匹配不到的地方用 NULL 填充。
  • RIGHT JOIN 取出右表的所有数据,并匹配左表,匹配不到的地方用 NULL 填充。
  • UNION 合并两次查询的结果,去掉重复数据。

JOIN 操作的代价:这个查询执行了两次 JOIN,MySQL 需要先执行 LEFT JOIN 和 RIGHT JOIN,然后再 UNION,合并数据、去重。

去重(DISTINCT)的代价:UNION 默认会去重,因此 MySQL 在执行时会使用 TEMPORARY 表和 FILESORT,如果数据量大,可能会触发磁盘 IO,导致查询变慢。

索引优化:如果 customers.id 和 orders.customer_id 没有索引,查询性能会进一步下降。

如果你不需要去重,只想把两张表的数据简单合并,UNION ALL 是最快的选择,因为它:

  • 不需要 JOIN,只需简单地把两张表的结果合并。
  • 不需要去重,避免了 TEMPORARY 表和 FILESORT 操作。

总结

  • 要完整匹配两张表,就用FULL OUTER JOIN(用UNION模拟)
  • 要直接合并数据,不关心重复,就用UNION ALL
  • 数据量大,记得加索引,提高查询速度
  • NULL太多,IFNULL()处理一下。

FULL OUTER JOIN 适合需要数据匹配的场景,但 MySQL 需要用 UNION 模拟,性能相对较慢。

UNION ALL 更快,更适合简单数据合并,但会包含重复数据,不适用于数据匹配场景。

优化技巧:加索引、避免 UNION 造成的去重开销、用 COALESCE 处理 NULL 值。如果还有不清楚的地方,欢迎留言讨论。

© 2023 北京元石科技有限公司 ◎ 京公网安备 11010802042949号