AskOverflow.Dev

AskOverflow.Dev Logo AskOverflow.Dev Logo

AskOverflow.Dev Navigation

  • 主页
  • 系统&网络
  • Ubuntu
  • Unix
  • DBA
  • Computer
  • Coding
  • LangChain

Mobile menu

Close
  • 主页
  • 系统&网络
    • 最新
    • 热门
    • 标签
  • Ubuntu
    • 最新
    • 热门
    • 标签
  • Unix
    • 最新
    • 标签
  • DBA
    • 最新
    • 标签
  • Computer
    • 最新
    • 标签
  • Coding
    • 最新
    • 标签
主页 / dba / 问题 / 29742
Accepted
peter
peter
Asked: 2012-12-04 18:45:26 +0800 CST2012-12-04 18:45:26 +0800 CST 2012-12-04 18:45:26 +0800 CST

带有函数调用的估计查询计划与实际查询计划

  • 772

我在 SQL 服务器上有这个查询,一个合并复制查询:

SELECT DISTINCT
    b.tablenick,
    b.rowguid,
    c.generation,
    sys.fn_MSgeneration_downloadonly
    (
        c.generation,
        c.tablenick
    )
FROM #belong b
LEFT OUTER JOIN dbo.MSmerge_contents c ON 
    c.tablenick = b.tablenick
    AND c.rowguid = b.rowguid;

估计的查询计划包括有关 3 个查询的信息:

  1. 上面的查询
  2. 对 fn_MSgeneration_downloadonly 的函数调用
  3. 对 fn_MSArticle_has_downloadonly_property 的函数调用

实际的查询计划仅包含以下信息:

  1. 上面的查询

没有什么关于功能的。为什么实际计划中缺少功能信息?

我尝试了这些选项:

SET STATISTICS PROFILE ON
SET STATISTICS XML ON

它创建了一个实际计划,但它缺少与我在 Management Studio 中使用实际查询计划选项时相同的第 2 部分和第 3 部分。

例如,如果我要使用 Profiler 来捕获有关函数调用的信息,我会选择哪些事件?


没有找到与查询计划特别相关的答案,但我分析了 SP:StmtStarting 和 SP:StmtCompleted 并显示了函数调用。

sql-server merge-replication
  • 1 1 个回答
  • 2246 Views

1 个回答

  • Voted
  1. Best Answer
    Paul White
    2012-12-04T21:41:40+08:002012-12-04T21:41:40+08:00

    并没有关于功能。为什么实际计划中缺少功能信息?

    出于性能原因,这是设计使然。

    包含BEGIN和END在定义中的函数为每个输入行创建一个新的 T-SQL 堆栈框架。换句话说,函数体为每个输入 row 单独执行。这一事实解释了与 T-SQL 标量和多语句函数相关的大多数性能问题(请注意,内联表值函数不使用该BEGIN...END语法)。

    在您的问题的上下文中,这将导致SHOWPLAN每一行的完整输出。XML 计划输出非常冗长且生成成本很高,因此为每一行生成完整输出一般来说是个坏主意。

    例子

    考虑下面的 T-SQL 标量函数,它是在AdventureWorks示例数据库中创建的,它返回给定 ID 的产品名称:

    CREATE FUNCTION dbo.DumbNameLookup
    (
        @ProductID integer
    )
    RETURNS dbo.Name
    AS
    BEGIN
        RETURN
        (
            SELECT
                p.Name
            FROM Production.Product AS p
            WHERE
                p.ProductID = @ProductID
        );
    END;
    

    执行前计划

    预执行计划(SSMS 中的估计计划)显示父语句和嵌套函数调用的计划信息:

    -- Pre-execution plan shows main query and nested function call
    SET SHOWPLAN_XML ON;
    GO
    SELECT dbo.DumbNameLookup(1);
    GO
    SET SHOWPLAN_XML OFF;
    

    SSMS 输出:

    SSMS预执行计划

    在SQL Sentry Plan Explorer中查看的相同 XML更清楚地显示了调用的嵌套性质:

    PE预执行计划

    执行后输出

    当请求执行后计划输出时,SSMS 仅显示主查询的详细信息:

    -- Post-execution plan shows main query only
    SET STATISTICS XML ON;
    SELECT dbo.DumbNameLookup(1);
    SET STATISTICS XML OFF;
    

    SSMS 执行后

    可以使用 SQL Server Profiler 中的Showplan XML Statistics Profile Event Class显示不这样做的性能影响,使用多次调用该函数的查询(每个输入行一次):

    SELECT TOP (5)
        p.ProductID,
        dbo.DumbNameLookup(p.ProductID)
    FROM Production.Product AS p;
    

    探查器输出:

    跟踪输出

    函数执行有五个单独的执行后计划,父查询有一个。五个功能计划在分析器下部窗格中如下所示:

    功能计划

    父查询计划是:

    家长计划

    执行不带该TOP (5)子句的查询会为 Product 表中的 504 行中的每一行生成一个完整的执行计划。您可能会看到这将如何在更大的表中迅速失控。

    触发器的情况正好相反。这些不显示任何执行前计划信息,但包含执行后计划。这反映了触发器的基于集合的性质;每个受影响的行都会触发一次,而不是每行一次。

    • 17

相关问题

  • SQL Server - 使用聚集索引时如何存储数据页

  • 我需要为每种类型的查询使用单独的索引,还是一个多列索引可以工作?

  • 什么时候应该使用唯一约束而不是唯一索引?

  • 死锁的主要原因是什么,可以预防吗?

  • 如何确定是否需要或需要索引

Sidebar

Stats

  • 问题 205573
  • 回答 270741
  • 最佳答案 135370
  • 用户 68524
  • 热门
  • 回答
  • Marko Smith

    如何查看 Oracle 中的数据库列表?

    • 8 个回答
  • Marko Smith

    mysql innodb_buffer_pool_size 应该有多大?

    • 4 个回答
  • Marko Smith

    列出指定表的所有列

    • 5 个回答
  • Marko Smith

    从 .frm 和 .ibd 文件恢复表?

    • 10 个回答
  • Marko Smith

    如何在不修改我自己的 tnsnames.ora 的情况下使用 sqlplus 连接到位于另一台主机上的 Oracle 数据库

    • 4 个回答
  • Marko Smith

    你如何mysqldump特定的表?

    • 4 个回答
  • Marko Smith

    如何选择每组的第一行?

    • 6 个回答
  • Marko Smith

    使用 psql 列出数据库权限

    • 10 个回答
  • Marko Smith

    如何从 PostgreSQL 中的选择查询中将值插入表中?

    • 4 个回答
  • Marko Smith

    如何使用 psql 列出所有数据库和表?

    • 7 个回答
  • Martin Hope
    Mike Walsh 为什么事务日志不断增长或空间不足? 2012-12-05 18:11:22 +0800 CST
  • Martin Hope
    Stephane Rolland 列出指定表的所有列 2012-08-14 04:44:44 +0800 CST
  • Martin Hope
    haxney MySQL 能否合理地对数十亿行执行查询? 2012-07-03 11:36:13 +0800 CST
  • Martin Hope
    qazwsx 如何监控大型 .sql 文件的导入进度? 2012-05-03 08:54:41 +0800 CST
  • Martin Hope
    markdorison 你如何mysqldump特定的表? 2011-12-17 12:39:37 +0800 CST
  • Martin Hope
    pedrosanta 使用 psql 列出数据库权限 2011-08-04 11:01:21 +0800 CST
  • Martin Hope
    Jonas 如何使用 psql 对 SQL 查询进行计时? 2011-06-04 02:22:54 +0800 CST
  • Martin Hope
    Jonas 如何从 PostgreSQL 中的选择查询中将值插入表中? 2011-05-28 00:33:05 +0800 CST
  • Martin Hope
    Jonas 如何使用 psql 列出所有数据库和表? 2011-02-18 00:45:49 +0800 CST
  • Martin Hope
    bernd_k 什么时候应该使用唯一约束而不是唯一索引? 2011-01-05 02:32:27 +0800 CST

热门标签

sql-server mysql postgresql sql-server-2014 sql-server-2016 oracle sql-server-2008 database-design query-performance sql-server-2017

Explore

  • 主页
  • 问题
    • 最新
    • 热门
  • 标签
  • 帮助

Footer

AskOverflow.Dev

关于我们

  • 关于我们
  • 联系我们

Legal Stuff

  • Privacy Policy

Language

  • Pt
  • Server
  • Unix

© 2023 AskOverflow.DEV All Rights Reserve