SQL 中函数调用的代价分析

发布时间 - 2026-01-25 00:00:00    点击率:
会,标量函数(如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 分布。


# cos  # datediff  # 为什么  # sql  # 常量  # count  # select  # 整型  # 字符串  # 循环  # operator  # len  # 对象  # 数据库  # 这类  # 也不  # 序列化  # 子句  # 还会  # 出现在  # 而在  # 很简单  # 自定义  # 能将 


相关栏目: 【 网站优化151355 】 【 网络推广146373 】 【 网络技术251813 】 【 AI营销90571


相关推荐: 怎么制作网站设计模板图片,有电商商品详情页面的免费模板素材网站推荐吗?  Laravel怎么做数据加密_Laravel内置Crypt门面的加密与解密功能  Laravel策略(Policy)如何控制权限_Laravel Gates与Policies实现用户授权  Laravel如何使用Seeder填充数据_Laravel模型工厂Factory批量生成测试数据【方法】  详解ASP.NET 生成二维码实例(采用ThoughtWorks.QRCode和QrCode.Net两种方式)  如何在万网主机上快速搭建网站?  js实现获取鼠标当前的位置  Laravel怎么处理异常_Laravel自定义异常处理与错误页面教程  如何挑选最适合建站的高性能VPS主机?  Laravel如何处理表单验证?(Requests代码示例)  悟空识字如何进行跟读录音_悟空识字开启麦克风权限与录音  Win11怎么关闭专注助手 Win11关闭免打扰模式设置【操作】  大型企业网站制作流程,做网站需要注册公司吗?  详解免费开源的.NET多类型文件解压缩组件SharpZipLib(.NET组件介绍之七)  Bootstrap整体框架之JavaScript插件架构  Laravel如何实现文件上传和存储?(本地与S3配置)  Laravel怎么实现软删除SoftDeletes_Laravel模型回收站功能与数据恢复【步骤】  香港服务器部署网站为何提示未备案?  android nfc常用标签读取总结  如何在景安服务器上快速搭建个人网站?  Laravel怎么清理缓存_Laravel optimize clear命令详解  HTML透明颜色代码怎么让图片透明_给img元素加透明色的技巧【方法】  在centOS 7安装mysql 5.7的详细教程  教你用AI润色文章,让你的文字表达更专业  网站建设保证美观性,需要考虑的几点问题!  Laravel怎么实现模型属性的自动加密  Laravel如何创建自定义Facades?(详细步骤)  Laravel如何优化应用性能?(缓存和优化命令)  如何注册花生壳免费域名并搭建个人网站?  谷歌浏览器下载文件时中断怎么办 Google Chrome下载管理修复  Laravel如何发送系统通知?(Notification渠道示例)  如何快速生成凡客建站的专业级图册?  Laravel如何监控和管理失败的队列任务_Laravel失败任务处理与监控  如何在HTML表单中获取用户输入并结合JavaScript动态控制复利计算循环  Laravel如何使用缓存系统提升性能_Laravel缓存驱动和应用优化方案  如何在腾讯云服务器快速搭建个人网站?  香港服务器网站生成指南:免费资源整合与高速稳定配置方案  Laravel如何实现数据库事务?(DB Facade示例)  制作无缝贴图网站有哪些,3dmax无缝贴图怎么调?  Python自动化办公教程_ExcelWordPDF批量处理案例  如何快速选择适合个人网站的云服务器配置?  深圳网站制作公司好吗,在深圳找工作哪个网站最好啊?  PHP的CURL方法curl_setopt()函数案例介绍(抓取网页,POST数据)  深圳防火门网站制作公司,深圳中天明防火门怎么编码?  Laravel如何实现全文搜索功能?(Scout和Algolia示例)  如何在IIS中新建站点并配置端口与IP地址?  油猴 教程,油猴搜脚本为什么会网页无法显示?  Laravel怎么实现前端Toast弹窗提示_Laravel Session闪存数据Flash传递给前端【方法】  java ZXing生成二维码及条码实例分享  简单实现Android文件上传