SQL函数为什么影响索引_查询改写优化思路【教程】

15次阅读

SQL 函数导致索引失效,因破坏“索引列原始值可直接比对”前提;如 UPPER(name)、YEAR(create_time)等作用于 WHERE 左侧时,数据库无法利用原索引,需改写为 SARGable 形式或用生成列、函数索引等方案。

SQL 函数为什么影响索引_查询改写优化思路【教程】

SQL 函数影响索引,本质是破坏了“索引列的原始值可直接比对”这一前提。数据库只能高效走索引,当它看到 WHERE UPPER(name) = 'ALICE'WHERE YEAR(create_time) = 2023 这类写法时,无法用已建的 namecreate_time 索引做快速定位——因为索引里存的是原始 name 值和 create_time 时间戳,不是它们的函数结果。

哪些函数操作会让索引失效

只要出现在 WHERE 子句左侧(即被作用于索引列)的函数或表达式,基本都会导致索引跳过:

  • 字符串函数:如 UPPER()LOWER()SUBSTRING()TRIM() —— 例如 WHERE SUBSTRING(phone, 1, 3) = '138'
  • 日期函数:如 YEAR()MONTH()DATE()DAYOFYEAR() —— 例如 WHERE DATE(order_time) = '2025-12-18'
  • 数学运算:如 col * 2 > 100col + 1 = 5 —— 左侧不是纯列名
  • 隐式类型转换:如字段是 VARCHAR,但查询写成 WHERE phone = 13812345678(数字没加引号),MySQL 可能触发全表扫描

改写思路:让条件“SARGable”(可搜索参数化)

核心原则是:把函数从索引列上“移开”,改到常量侧或用等价范围表达。

  • 字符串前缀匹配 → 改用 LIKE ‘xxx%’
    WHERE LEFT(name, 3) = 'Tom'
    WHERE name LIKE 'Tom%'(前提是索引在 name 上,且不带前导 %)
  • 年份提取 → 改为时间范围
    WHERE YEAR(create_time) = 2023
    WHERE create_time >= '2023-01-01' AND create_time
  • 大小写不敏感查询 → 改用校对规则或函数索引(MySQL 8.0+)
    ✅ 创建索引时指定 CASE INSENSITIVE 校对集,或使用生成列:
    ALTER TABLE user ADD COLUMN name_lower VARCHAR(50) STORED AS (LOWER(name)); CREATE INDEX idx_name_lower ON user(name_lower);
  • 数值运算 → 移项还原为纯列比较
    WHERE price * 1.1 > 100
    WHERE price > 100 / 1.1(注意浮点精度是否可接受)

进阶替代方案:绕过函数限制

当业务逻辑确实绕不开函数处理时,可用这些技术保持索引可用:

  • 生成列 + 索引(MySQL 5.7+/8.0 推荐):把函数结果持久化为新列并建索引
    例:ALTER TABLE orders ADD COLUMN order_year INT AS (YEAR(order_date)) STORED; CREATE INDEX idx_order_year ON orders(order_year);
  • 函数索引(MySQL 8.0.13+、PostgreSQL 原生支持)
    CREATE INDEX idx_name_upper ON users ((UPPER(name)));(注意括号语法)
  • 冗余字段维护:应用层写入时同步保存处理后值,如同时存 emailemail_lower,查时直击后者

验证是否生效:必须看执行计划

改写后别凭感觉,用 EXPLAIN 确认是否真正走了索引:

  • 关注 type 字段:优先看到 refrangeconst;避免 ALL(全表扫描)
  • key 字段:是否显示你期望的索引名
  • 留意 Extra:出现 Using filesortUsing temporary 是性能隐患信号
  • SQL_NO_CACHE 排除缓存干扰:EXPLAIN SELECT SQL_NO_CACHE ……
星耀云
版权声明:本站原创文章,由 星耀云 2025-12-18发表,共计1599字。
转载说明:转载本网站任何内容,请按照转载方式正确书写本站原文地址。本站提供的一切软件、教程和内容信息仅限用于学习和研究目的;不得将上述内容用于商业或者非法用途,否则,一切后果请用户自负。本站信息来自网络,版权争议与本站无关。
text=ZqhQzanResources