会,标量函数(如UPPER、CONVERT)在WHERE中逐行计算且阻断索引;ITVF可展开优化,MSTVF和UDF易致统计丢失、序列化执行;应避免列上函数,改用参数端转换或常量替换。

SQL 函数调用会拖慢查询吗?
会,但取决于函数类型和使用方式。标量函数(如 UPPER()、DATEADD())在 WHERE 或 SELECT 中对每行逐个计算,可能阻断索引下推、抑制并行执行,甚至让优化器放弃估算。而内联表值函数(ITVF)通常可展开为等价 SQL,代价接近原生查询;多语句表值函数(MSTVF)则像黑盒,常导致统计信息丢失和嵌套循环连接。
WHERE 子句里用 CONVERT() 或 CAST() 为什么查得慢?
这类显式转换常出现在“把字段转成字符串再模糊匹配”场景,例如:WHERE CAST(order_id AS VARCHAR) LIKE '123%'。问题在于:
- 字段被函数包裹后,无法走
order_id 列上的索引(即使该列是整型主键)
- SQL Server 无法对转换结果生成有效统计直方图,优化器容易低估/高估行数
- 如果
order_id 是聚集索引键,强制转换还会阻止范围扫描,退化为全索引扫描
更稳妥的做法是反向转换:把参数转为目标列类型,例如 WHERE order_id >= 12300 AND order_id (若业务允许前缀数字解析)。
GETDATE() 和 SYSDATETIME() 在 WHERE 中能用索引吗?
可以,但仅限于“列 >= 函数调用”这类单调递增表达式。例如:WHERE created_at >= GETDATE() - 1,优化器能将函数求值一次后转为常量,再配合 created_at 上的索引做范围查找。但以下写法会失效:
-
WHERE DATEDIFF(day, created_at, GETDATE()) = 0 —— 函数包裹列,索引失效
-
WHERE YEAR(created_at) = YEAR(GETDATE()) —— 同样破坏 sargability
注意:GETDATE() 是运行时标量函数,每次执行只算一次(非每行),但只要它让谓词不可 SARGable,索引就白搭。
自定义标量函数(UDF)为何比内置函数更危险?
SQL Server 2019 之前,UDF 默认被当作“黑盒”,优化器既不内联也不推导其行为,哪怕函数体只有一行 RETURN @x + 1。后果包括:
- 强制序列化执行(禁用并行)
- 每行调用一次,且无法复用中间结果(无缓存)
- 执行计划中显示为
Compute Scalar,但实际开销常被严重低估
SQL Server 2019+ 启用 QUERY_OPTIMIZER_HOTFIXES 或数据库兼容级别 ≥ 150 后,部分简单 UDF 可自动内联——但必须满足:无副作用、无引用对象、无分支逻辑。否则仍退化为旧模式。
函数代价最隐蔽的地方不在 CPU,而在执行计划失真:你以为只是加了个 LEN(),结果优化器选了嵌套循环而非哈希连接,最后扫了千万行才出结果。别信“这个函数很简单”,先看执行计划里的 Actual Row Count 和 Operator Cost 分布。
华友协同办公自动化OA系统
华友协同办公管理系统(华友OA),基于微软最新的.net 2.0平台和SQL Server数据库,集成强大的Ajax技术,采用多层分布式架构,实现统一办公平台,功能强大、价格便宜,是适用于企事业单位的通用型网络协同办公系统。 系统秉承协同办公的思想,集成即时通讯、日记管理、通知管理、邮件管理、新闻、考勤管理、短信管理、个人文件柜、日程安排、工作计划、工作日清、通讯录、公文流转、论坛、在线调查、
下载
CONVERT() 或 CAST() 为什么查得慢?
这类显式转换常出现在“把字段转成字符串再模糊匹配”场景,例如:WHERE CAST(order_id AS VARCHAR) LIKE '123%'。问题在于:
- 字段被函数包裹后,无法走
order_id列上的索引(即使该列是整型主键) - SQL Server 无法对转换结果生成有效统计直方图,优化器容易低估/高估行数
- 如果
order_id是聚集索引键,强制转换还会阻止范围扫描,退化为全索引扫描
WHERE order_id >= 12300 AND order_id (若业务允许前缀数字解析)。
GETDATE() 和 SYSDATETIME() 在 WHERE 中能用索引吗?
可以,但仅限于“列 >= 函数调用”这类单调递增表达式。例如:WHERE created_at >= GETDATE() - 1,优化器能将函数求值一次后转为常量,再配合 created_at 上的索引做范围查找。但以下写法会失效:
-
WHERE DATEDIFF(day, created_at, GETDATE()) = 0 —— 函数包裹列,索引失效
-
WHERE YEAR(created_at) = YEAR(GETDATE()) —— 同样破坏 sargability
注意:GETDATE() 是运行时标量函数,每次执行只算一次(非每行),但只要它让谓词不可 SARGable,索引就白搭。
自定义标量函数(UDF)为何比内置函数更危险?
SQL Server 2019 之前,UDF 默认被当作“黑盒”,优化器既不内联也不推导其行为,哪怕函数体只有一行 RETURN @x + 1。后果包括:
- 强制序列化执行(禁用并行)
- 每行调用一次,且无法复用中间结果(无缓存)
- 执行计划中显示为
Compute Scalar,但实际开销常被严重低估
SQL Server 2019+ 启用 QUERY_OPTIMIZER_HOTFIXES 或数据库兼容级别 ≥ 150 后,部分简单 UDF 可自动内联——但必须满足:无副作用、无引用对象、无分支逻辑。否则仍退化为旧模式。
函数代价最隐蔽的地方不在 CPU,而在执行计划失真:你以为只是加了个 LEN(),结果优化器选了嵌套循环而非哈希连接,最后扫了千万行才出结果。别信“这个函数很简单”,先看执行计划里的 Actual Row Count 和 Operator Cost 分布。
华友协同办公自动化OA系统
华友协同办公管理系统(华友OA),基于微软最新的.net 2.0平台和SQL Server数据库,集成强大的Ajax技术,采用多层分布式架构,实现统一办公平台,功能强大、价格便宜,是适用于企事业单位的通用型网络协同办公系统。 系统秉承协同办公的思想,集成即时通讯、日记管理、通知管理、邮件管理、新闻、考勤管理、短信管理、个人文件柜、日程安排、工作计划、工作日清、通讯录、公文流转、论坛、在线调查、
下载









