SQL 为什么不推荐在 WHERE 中对列做函数运算?

13次阅读

索引失效是核心问题,因函数运算使数据库无法利用B+树索引,导致全表扫描;应将函数移至常量侧或改用范围查询,函数索引仅作补充。

SQL 为什么不推荐在 WHERE 中对列做函数运算?

因为这会让数据库无法有效使用索引,导致全表扫描,性能急剧下降。

索引失效是核心问题

数据库的B+树索引是按列的原始值有序存储的。一旦在 WHERE 中对列使用函数(比如 WHERE YEAR(create_time) = 2023WHERE UPPER(name) = ‘ABC’),优化器就无法直接拿函数结果去匹配索引中的原始值。它必须先对每一行计算函数,再比对——相当于绕过了索引,只能逐行扫描。

常见触发函数运算的写法

  • 日期截取类:YEAR()、MONTH()、date()、DATE_FORMAT()、TO_DAYS()
  • 字符串处理类:UPPER()、LOWER()、TRIM()、SUBSTRING()、CONCAT()
  • 数学/类型转换:ABS()、ROUND()、CAST()、CONVERT()

更高效的替代方案

把函数从列上“移开”,改到常量侧或用范围表达:

  • WHERE YEAR(create_time) = 2023 ✅ 改为:WHERE create_time >= ‘2023-01-01’ AND create_time
  • WHERE UPPER(name) = ‘JOHN’ ✅ 改为:WHERE name = ‘john’(配合大小写敏感校对规则),或建函数索引(mysql 8.0+/postgresql支持)
  • WHERE price * 1.1 > 100 ✅ 改为:WHERE price > 100 / 1.1

特殊情况:函数索引可解但需谨慎

MySQL 8.0、PostgreSQL、oracle 等支持函数索引(如 CREATE INDEX idx_year ON t (YEAR(create_time))),但它只对完全匹配该函数的查询生效,且会增加维护成本和存储开销。优先考虑重写条件,函数索引应作为补充手段而非默认方案。

text=ZqhQzanResources