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 = '[email protected]';

3. 使用 EXPLAIN 分析查询

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

sql 复制代码
EXPLAIN
SELECT * FROM tb_user WHERE phone = '12345678901'
UNION
SELECT * FROM tb_user WHERE email = '[email protected]';

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 = '[email protected]';

然后再次使用 EXPLAIN 分析:

sql 复制代码
EXPLAIN
SELECT * FROM tb_user WHERE phone = '12345678901' OR email = '[email protected]';

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

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 = '[email protected]';
+----+--------------+------------+------------+------+---------------+-----------+---------+-------+------+----------+-----------------+
| 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 = '[email protected]'
    • 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 = '[email protected]';

执行计划可能如下:

  • 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 分钟前
redis分布式锁
数据库·redis·分布式
Bug.Remove()7 分钟前
PostgreSQL数据类型使用
数据库·postgresql
快乐觉主吖29 分钟前
Unity的日志管理类
android·unity·游戏引擎
明月看潮生37 分钟前
青少年编程与数学 01-011 系统软件简介 06 Android操作系统
android·青少年编程·操作系统·系统软件·编程与数学
snetlogon2040 分钟前
JDK17 Http Request 异步处理 源码刨析
android·网络协议·http
逝水如流年轻往返染尘41 分钟前
MySQL中的内置函数
数据库·mysql
咖啡啡不加糖1 小时前
深入理解MySQL死锁:从原理、案例到解决方案
java·数据库·mysql
文牧之1 小时前
PostgreSQL 的扩展pageinspect
运维·数据库·postgresql
要努力啊啊啊1 小时前
使用 Python + SQLAlchemy 创建知识库数据库(SQLite)—— 构建本地知识库系统的基础《一》
数据库·人工智能·python·深度学习·自然语言处理·sqlite
KENYCHEN奉孝1 小时前
Django CMS 的 Demo
数据库·sqlite