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

相关推荐
我就是妖怪1 分钟前
KMP全栈开发:从Android到AI Agent的技术演进与实践
android·人工智能
Blossom i25 分钟前
大数据预处理与采集实验一:使用Python操作MySQL数据库
数据库·mysql
InfinitePlus42 分钟前
Docker MySQL搭建一主一从
mysql·docker
心平气和量大福大1 小时前
android-实例-蒲公英-更新与安装-5-签名与生成APK
android·java·开发语言
雾时之林1 小时前
Linux--软件管理、源码包安装
linux·服务器·数据库
阿pin3 小时前
Android随笔-Serializable与Parcelable
android·serializable·parcelable
老纪的技术唠嗑局3 小时前
超级干货分享:中小企业使用 OceanBase 实践经验汇总
数据库
天空之城--3 小时前
Android 事件分发机制深度解析——原理、源码与实战综合总结
android
CLOUD ACE3 小时前
谷歌云代理|零售商Target 如何利用 Spanner Graph 提升零售发现体验并将数据库维护成本降低 50%
数据库·零售
AI大模型-小雄3 小时前
Codex写分页接口为什么越翻越慢?用Cursor Pagination解决重复与漏数据
大数据·数据库·elasticsearch·搜索引擎·chatgpt·后端开发·codex