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

SQL函数影响索引,本质是破坏了“索引列的原始值可直接比对”这一前提。数据库只能高效走索引,当它看到 WHERE UPPER(name) = 'ALICE' 或 WHERE YEAR(create_time) = 2023 这类写法时,无法用已建的 name 或 create_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 > 100、col + 1 = 5 —— 左侧不是纯列名VARCHAR,但查询写成 WHERE phone = 13812345678(数字没加引号),MySQL 可能触发全表扫描核心原则是:把函数从索引列上“移开”,改到常量侧或用等价范围表达。
WHERE LEFT(name, 3) = 'Tom'WHERE name LIKE 'Tom%'(前提是索引在 name 上,且不带前导 %)WHERE YEAR(create_time) = 2023WHERE create_time >= '2023-01-01' AND create_time
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 > 100WHERE price > 100 / 1.1(注意浮点精度是否可接受)当业务逻辑确实绕不开函数处理时,可用这些技术保持索引可用:
ALTER TABLE orders ADD COLUMN order_year INT AS (YEAR(order_date)) STORED; CREATE INDEX idx_order_year ON orders(order_year);
CREATE INDEX idx_name_upper ON users ((UPPER(name)));(注意括号语法)email 和 email_lower,查时直击后者改写后别凭感觉,用 EXPLAIN 确认是否真正走了索引:
type 字段:优先看到 ref、range、const;避免 ALL(全表扫描)key 字段:是否显示你期望的索引名Extra:出现 Using filesort 或 Using temporary 是性能隐患信号SQL_NO_CACHE 排除缓存干扰:EXPLAIN SELECT SQL_NO_CACHE ...
以上就是SQL函数为什么影响索引_查询改写优化思路【教程】的详细内容,更多请关注php中文网其它相关文章!
每个人都需要一台速度更快、更稳定的 PC。随着时间的推移,垃圾文件、旧注册表数据和不必要的后台进程会占用资源并降低性能。幸运的是,许多工具可以让 Windows 保持平稳运行。
Copyright 2014-2025 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号