news 2026/10/28 18:21:07

SQL查询性能优化 - EXISTS、IN

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
SQL查询性能优化 - EXISTS、IN

从客户表(c1)中,找出所有状态为“2”的客户,并且要求存在另一个状态也为“2”、邮箱包含'customer'、手机号以'138'开头的同名客户。

将所有状态为“2”且满足存在性检查的最终结果,按照客户姓名 (c1.name)进行排序,然后为其分配一个连续的组序号 (group_seq)。

原sql

SELECT DENSE_RANK() OVER (ORDER BY c1.name) AS group_seq, c1.customer_id, c1.name, c1.email, c1.phone, c1.registration_date, c1.credit_limit, c1.status, c1.created_at FROM study_test.customers c1 WHERE c1.status = 2 AND c1.name in ( SELECT c2.name FROM study_test.customers c2 WHERE c2.status = 2 AND c2.email LIKE '%customer%' AND c2.phone LIKE '138%' AND c2.name = c1.name ) ORDER BY group_seq, c1.customer_id

优化后

优化后的 SQL 使用EXISTS,这通常比IN更有性能优势,特别是当子查询能利用索引时。

SELECT DENSE_RANK() OVER (ORDER BY c1.name) AS group_seq, c1.customer_id, c1.name, c1.email, c1.phone, c1.registration_date, c1.credit_limit, c1.status, c1.created_at FROM study_test.customers c1 WHERE c1.status = 2 AND EXISTS ( SELECT 1 FROM study_test.customers c2 WHERE c2.status = 2 AND c2.email LIKE '%customer%' AND c2.phone LIKE '138%' AND c2.name = c1.name ) ORDER BY group_seq, c1.customer_id; xml中 c2.status = 2 AND c2.email LIKE '%customer%' AND c2.phone LIKE '138%'

这3个条件是可选,生产环境下怎么设置索引呢,那些索引必须设置,那些可以选择设置,那些没必要设置,详细介绍

WHERE c2.status = 2 AND c2.phone LIKE '138%' WHERE c2.status = 2 AND c2.email LIKE '%customer%' WHERE AND c2.email LIKE '%customer%' AND c2.phone LIKE '138%' WHERE AND c2.phone LIKE '138%'

索引类别

推荐索引 (表:customers)

说明

优先级

核心必备索引​

(status, name)

优化主查询的status过滤和name排序,同时高效支持子查询的关联条件c2.name = c1.name。

必须​

高频条件索引​

(status, phone)

针对status=2和phone LIKE '138%'这个高选择性组合,效率极高。

建议(若条件常用)​

低频条件索引​

(status, email)

对email LIKE '%customer%'效果有限,因模糊匹配方式无法利用索引的有序性。

谨慎(通常不推荐)​

全覆盖索引​

(status, name, phone, email)

作为备选,尝试用一个索引覆盖所有场景,但索引体积较大。

可选(需权衡)​

索引设计思路详解

查询性能瓶颈主要在于子查询。EXISTS会为外层查询(c1)的每一行数据执行一次子查询(c2),因此子查询的速度至关重要。设计索引需遵循以下核心原则:

  1. 最左前缀原则:复合索引(A, B, C)可以被用于A=?、A=? AND B=?的查询,但不能用于跳过A直接查询B=?或C=?。

  2. 索引选择性:指索引列区分数据的能力。phone和email的选择性通常远高于status。选择性高的列放在复合索引中效果更好。

  3. LIKE 查询的索引利用:LIKE '138%'这样的前缀匹配可以利用索引。而LIKE '%customer%'这样的前后模糊匹配基本上无法利用索引进行快速定位,通常会导致全索引扫描或全表扫描。

基于可选条件,以下是具体的索引分析和建议:

1. 必须设置的索引

  • 索引:​idx_status_name (status, name)

  • 理由:

    • 这是查询的基石。无论其他条件如何组合,status=2和基于name的关联与排序都是固定的。

    • 该索引可以同时优化外层查询的WHERE c1.status = 2和ORDER BY c1.name,避免昂贵的文件排序(filesort)。

    • 它也能极快地定位子查询中的c2.status = 2 AND c2.name = c1.name,这是子查询的连接条件。

2. 建议根据查询频率设置的索引

  • 索引:​idx_status_phone (status, phone)

  • 理由:

    • 当查询条件包含phone LIKE '138%'时,这个索引是性能提升的关键。status进行第一层快速过滤后,对phone的前缀匹配可以在这个索引上高效完成范围扫描。

    • 这个索引能完美覆盖WHERE c2.status = 2 AND c2.phone LIKE '138%'这种组合。

3. 需要谨慎考虑的索引

  • 索引:​idx_status_email (status, email)

  • 理由与风险:

    • 对于email LIKE '%customer%'这个条件,由于其模糊匹配的方式,即使为(status, email)创建了索引,数据库也通常只能利用status部分进行过滤,然后对email列进行扫描。

    • 创建建议:只有当你的业务中,email字段包含'customer'的数据量非常少(例如低于1%),并且这个查询模式极其频繁时,才值得为其创建这个索引。否则,额外的索引会增加写操作的负担,但收效甚微。

4. 一个备选的综合方案

  • 索引:​idx_covering (status, name, phone, email)

  • 理由与风险:

    • 这个索引试图用一个索引覆盖所有可能的查询路径。它包含了status和name以满足核心需求,同时追加了phone和email来尝试覆盖可选条件。

    • 优点:在某些情况下,优化器可能会选择这个索引作为覆盖索引,避免回表。

    • 缺点:索引体积庞大,维护成本高。并且对于email的模糊查询,帮助依然有限。这更像是一种“重武器”,建议在充分了解数据分布后,通过EXPLAIN命令验证其效果后再决定是否采用。

实施与验证建议

  1. 使用EXPLAIN分析:创建索引后,务必使用EXPLAIN命令分析SQL语句。关注以下关键字段:

    • type:至少达到ref或range级别,避免ALL(全表扫描)。

    • key:确认查询实际使用了你创建的索引。

    • Extra:如果出现Using index(覆盖索引)是最佳情况。出现Using filesort则需注意。

  2. 查询重写技巧:如果你的应用代码可以灵活调整,可以考虑将可选的查询条件动态拼接成不同的SQL,而不是依赖一个统一的复杂查询。这样可以为每种条件组合设置最合适的索引,实现最优性能。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/10/26 21:39:47

基于深度卷积神经网络的网络流量检测与识别(设计源文件+万字报告+讲解)(支持资料、图片参考_相关定制)

基于深度卷积神经网络的网络流量检测与识别(设计源文件万字报告讲解)(支持资料、图片参考_相关定制) ,包含代码实现、数据集和项目报告。项目详情介绍可参考下图(一个是模型跑出的相关实验结果表、混淆矩阵等,一个是根…

作者头像 李华
网站建设 2026/10/26 21:39:47

RAG开发必看:结构化数据的5种骚操作,小白程序员也能轻松掌握

大家好!今天来聊聊如何在RAG应用中更好地利用结构化数据。很多同学可能觉得RAG主要是处理文本文档,但其实结构化数据也能发挥很大作用。我总结了5种实用的方法: 1. 直接存储行数据 最简单直接的方式就是把数据表的每一行当作一个独立的chun…

作者头像 李华
网站建设 2026/10/28 1:57:19

导师推荐!9款AI论文工具测评:本科生毕业论文必备

导师推荐!9款AI论文工具测评:本科生毕业论文必备 2026年AI论文工具测评:为何需要这份榜单? 随着人工智能技术的不断进步,越来越多的本科生开始依赖AI工具来辅助论文写作。然而,市面上的AI论文工具种类繁多&…

作者头像 李华
网站建设 2026/10/27 9:41:08

Atcoder[ABC401F] Add One Edge 3 题解

[ABC401F] Add One Edge 3 思路 设第一棵树的直径长度为 l1l1l1,第二棵树的直径长度为 l2l2l2,aia_iai​ 为第一棵树中以点 iii 为端点的路径的长度最大值,bib_ibi​ 为第二棵树中以点 iii 为端点的路径的长度最大值。则 f(i,j)f(i,j)f(i,j…

作者头像 李华