MySQL的Union和OR查询

这里写目录标题

      • [**1. 创建表和索引**](#1. 创建表和索引)
      • [**2. 编写 `UNION` 查询**](#2. 编写 UNION 查询)
      • [**3. 使用 `EXPLAIN` 分析查询**](#3. 使用 EXPLAIN 分析查询)
      • [**4. 分析 `EXPLAIN` 结果**](#4. 分析 EXPLAIN 结果)
      • [**5. 验证索引合并**](#5. 验证索引合并)
      • **总结**
      • [**1. `UNION` 操作的分析**](#1. UNION 操作的分析)
      • [2. `OR` 条件的分析](#2. OR 条件的分析)
      • [3. `UNION` 和 `OR` 的区别](#3. UNIONOR 的区别)
      • **总结**

在 MySQL 中, UNION 操作通常用于合并两个查询的结果集。为了测试 UNION 操作是否会使用索引合并(Index Merge)功能,还是仅使用单列索引,可以按照以下步骤进行测试和分析。


1. 创建表和索引

根据表结构,为 phoneemail 列创建单列索引:

sql 复制代码
CREATE INDEX idx_phone ON tb_user(phone);
CREATE INDEX idx_email ON tb_user(email);

2. 编写 UNION 查询

编写一个 UNION 查询,分别基于 phoneemail 列进行查询:

sql 复制代码
SELECT * FROM tb_user WHERE phone = '12345678901'
UNION
SELECT * FROM tb_user WHERE email = 'example@example.com';

3. 使用 EXPLAIN 分析查询

使用 EXPLAIN 命令查看查询的执行计划,判断是否使用了索引合并功能:

sql 复制代码
EXPLAIN
SELECT * FROM tb_user WHERE phone = '12345678901'
UNION
SELECT * FROM tb_user WHERE email = 'example@example.com';

4. 分析 EXPLAIN 结果

EXPLAIN 的输出中,重点关注以下字段:

  • type :访问类型,ref 表示使用了索引。
  • key:使用的索引名称。
  • Extra :额外信息,如果出现 Using unionUsing index merge,则表示使用了索引合并。
可能的结果分析
  1. 仅使用单列索引

    • 每个子查询的 typerefkeyidx_phoneidx_email
    • Extra 中没有 Using index merge
    • 说明每个子查询分别使用了 phoneemail 的单列索引。
  2. 使用了索引合并

    • typeindex_merge
    • key 可能显示 idx_phone,idx_email
    • Extra 中显示 Using union(idx_phone,idx_email)
    • 说明 MySQL 使用了索引合并功能。

5. 验证索引合并

如果 EXPLAIN 结果显示没有使用索引合并,可以尝试强制使用索引合并:

sql 复制代码
SELECT * FROM tb_user WHERE phone = '12345678901' OR email = 'example@example.com';

然后再次使用 EXPLAIN 分析:

sql 复制代码
EXPLAIN
SELECT * FROM tb_user WHERE phone = '12345678901' OR email = 'example@example.com';

观察是否使用了索引合并。

type:index_merge


总结

  • 使用 EXPLAIN 分析查询计划。
  • 如果 EXPLAINExtra 字段显示 Using index merge,则使用了索引合并功能。
  • 如果每个子查询分别使用了单列索引,则说明没有使用索引合并。

通过以上方法,可以测试并判断 UNION 操作是否使用了索引合并功能。

实操之后

sql 复制代码
mysql> EXPLAIN
-> SELECT * FROM tb_user WHERE phone = '12345678901'
-> UNION
-> SELECT * FROM tb_user WHERE email = 'example@example.com';
+----+--------------+------------+------------+------+---------------+-----------+---------+-------+------+----------+-----------------+
| id | select_type | table | partitions | type | possible_keys | key | key_len | ref | rows | filtered | Extra |
+----+--------------+------------+------------+------+---------------+-----------+---------+-------+------+----------+-----------------+
| 1 | PRIMARY | tb_user | NULL | ref | idx_phone | idx_phone | 35 | const | 1 | 100.00 | NULL |
| 2 | UNION | tb_user | NULL | ref | idx_email | idx_email | 303 | const | 1 | 100.00 | NULL |
| NULL | UNION RESULT | <union1,2> | NULL | ALL | NULL | NULL | NULL | NULL | NULL | NULL | Using temporary |
+----+--------------+------------+------------+------+---------------+-----------+---------+-------+------+----------+-----------------+

EXPLAIN 的结果可以看出,UNION 操作和 OR 条件的执行计划有所不同。以下是详细解释:


1. UNION 操作的分析

UNION 操作的执行计划分为三个部分:

  • 第一部分SELECT * FROM tb_user WHERE phone = '12345678901'
    • type : ref,表示使用了索引。
    • key : idx_phone,表示使用了 phone 列的单列索引。
    • Extra: 无额外信息。
  • 第二部分SELECT * FROM tb_user WHERE email = 'example@example.com'
    • type : ref,表示使用了索引。
    • key : idx_email,表示使用了 email 列的单列索引。
    • Extra: 无额外信息。
  • 第三部分UNION RESULT
    • type : ALL,表示需要扫描所有行。
    • Extra : Using temporary ,表示使用了临时表来存储 UNION 的结果。
为什么使用临时表?

UNION 操作会将两个查询的结果集合并,并自动去除重复的行。为了实现这一点,MySQL 会将两个查询的结果存储在一个临时表中,然后对临时表进行去重操作。因此,UNION 操作通常会使用临时表。


2. OR 条件的分析

对于 OR 条件,MySQL 可能会使用索引合并(Index Merge)功能。例如:

sql 复制代码
EXPLAIN
SELECT * FROM tb_user WHERE phone = '12345678901' OR email = 'example@example.com';

执行计划可能如下:

  • type : index_merge,表示使用了索引合并。
  • key : idx_phone,idx_email,表示同时使用了 phoneemail 列的单列索引。
  • Extra : Using union(idx_phone,idx_email); Using where ,表示 MySQL 使用了索引合并功能,并通过 WHERE 条件过滤结果。
为什么使用索引合并?

OR 条件需要同时满足两个条件中的任意一个。MySQL 会分别使用 phoneemail 列的单列索引,然后将结果合并(Using union),最后通过 WHERE 条件过滤结果。


3. UNIONOR 的区别

特性 UNION OR
结果集 合并两个查询的结果,并去重 合并两个条件的结果,不去重
索引使用 分别使用单列索引 可能使用索引合并(Index Merge)
临时表 使用临时表存储结果 不使用临时表
性能 可能较慢,因为需要去重和临时表操作 通常更快,因为不需要去重

总结

  • UNION
    • 分别使用单列索引。
    • 使用临时表存储结果并去重。
    • 适合需要合并并去重的场景。
  • OR
    • 可能使用索引合并(Using union)。
    • 不需要临时表,性能通常更好。
    • 适合需要同时满足多个条件的场景。

根据实际需求选择合适的查询方式。如果需要去重,使用 UNION;如果不需要去重,使用 OR

相关推荐
小马哥编程5 分钟前
【软件架构】数据库系统与缓存设计:五种缓存一致性方案
数据库·缓存
DemonAvenger24 分钟前
Redis持久化策略对比:RDB与AOF的最佳实践与场景选择
数据库·redis·性能优化
新手小白*35 分钟前
Redis Sentinel哨兵集群
数据库·redis·sentinel
一 乐38 分钟前
商城推荐系统|基于SprinBoot+vue的商城推荐系统(源码+数据库+文档)
前端·数据库·vue.js·spring boot·后端·商城推荐系统
羑悻的小杀马特1 小时前
从零搭建群晖私有影音库:NasTool自动化追剧全流程拆解与远程访问协议优化实践
运维·数据库·自动化
游戏开发爱好者82 小时前
iOS 26 iPhone 使用记录分析 多工具组合构建全方位设备行为洞察体系
android·ios·小程序·uni-app·cocoa·iphone·webview
TDengine (老段)3 小时前
杨凌美畅用 TDengine 时序数据库,支撑 500 条产线 2 年历史数据追溯
大数据·数据库·物联网·时序数据库·tdengine·涛思数据
葛小白16 小时前
C#数据类型:string简单使用
服务器·数据库·c#
污斑兔6 小时前
MongoDB的$sample是啥?
数据库·mongodb
马丁的代码日记8 小时前
MySQL InnoDB 行锁与死锁排查实战演示
数据库·mysql