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 / 问题 / 314518
Accepted
Erik Darling
Erik Darling
Asked: 2022-07-18 09:32:23 +0800 CST2022-07-18 09:32:23 +0800 CST 2022-07-18 09:32:23 +0800 CST

为什么 SQL Server 可以准确地跟踪某些多语句表值函数查询计划而不是其他的时间?

  • 772

设置

对于这个演示,我使用的是2013 版本的 Stack Overflow 数据库和 SQL Server 2022 CTP2,但它可以追溯到 SQL Server 2017,这是我想检查的。

功能一

对于此函数,SQL Server 跟踪函数中花费的执行时间:

CREATE OR ALTER FUNCTION
    dbo.ScoreStats
(
    @UserId int
)
RETURNS
    @out table
    (
        TotalScore bigint
    )
WITH SCHEMABINDING
AS 
BEGIN

    INSERT
        @out
    (
        TotalScore
    )
    SELECT
        TotalScore = 
            SUM(x.Score)
    FROM 
    (
        SELECT
            Score = 
                SUM(p.Score)
        FROM dbo.Posts AS p
        WHERE p.OwnerUserId = @UserId

        UNION ALL

        SELECT
            Score = 
                SUM(c.Score)
        FROM dbo.Comments AS c
        WHERE c.UserId = @UserId    
    ) AS x;

    RETURN;

END;

这是查询和执行计划:

SELECT
    u.DisplayName,
    TotalScore = 
        (
            SELECT
                ss.TotalScore
            FROM dbo.ScoreStats(u.Id) AS ss
        )
FROM dbo.Users AS u
WHERE u.Reputation >= 1000000;

坚果

您可以看到,在查询计划和 Query Time Stats 属性中都准确地跟踪了时间。

功能二

这是第二个功能,它不会发生:

CREATE OR ALTER FUNCTION
    dbo.VoteStats()
RETURNS
    @out table
    (
        PostId int,
        UpVotes int,
        DownVotes int,
        UpMultipier AS 
             UpVotes * 2
    )
WITH SCHEMABINDING
AS 
BEGIN

    INSERT
        @out
    (
        PostId,
        UpVotes,
        DownVotes
    )
    SELECT
        v.PostId,
        UpVotes = 
            SUM
            (
                CASE v.VoteTypeId
                     WHEN 2
                     THEN 1
                     ELSE 0
                END
            ),
        DownVotes = 
            SUM
            (
                CASE v.VoteTypeId
                     WHEN 3
                     THEN 1
                     ELSE 0
                END
            )
    FROM dbo.Votes AS v
    GROUP BY 
        v.PostId;

    RETURN;

END;

这是查询和执行计划:

SELECT TOP (100)
     p.Id,
     vs.UpVotes,
     vs.DownVotes
FROM dbo.VoteStats() AS vs
JOIN dbo.Posts AS p
    ON vs.PostId = p.Id
WHERE vs.DownVotes > vs.UpMultipier
AND   p.CommunityOwnedDate IS NULL
AND   p.ClosedDate IS NULL
ORDER BY vs.UpVotes DESC;

坚果

在此查询中,时间没有在图形执行计划中准确跟踪,而是在 Query Time Stats 属性中进行跟踪。

MAXDOP 1 处的功能二

即使是强制连载,也无法准确跟踪时间:

SELECT TOP (100)
     p.Id,
     vs.UpVotes,
     vs.DownVotes
FROM dbo.VoteStats() AS vs
JOIN dbo.Posts AS p
    ON vs.PostId = p.Id
WHERE vs.DownVotes > vs.UpMultipier
AND   p.CommunityOwnedDate IS NULL
AND   p.ClosedDate IS NULL
ORDER BY vs.UpVotes DESC
OPTION(MAXDOP 1);

坚果

问题

回到手头的问题:为什么在一个查询计划中可以准确地跟踪时间,而在另一个查询计划中却没有?

sql-server execution-plan
  • 2 2 个回答
  • 773 Views

2 个回答

  • Voted
  1. Best Answer
    Paul White
    2022-07-18T19:59:07+08:002022-07-18T19:59:07+08:00

    这是使用交错 TVF 执行的结果。

    交错执行改变了单查询执行的优化和执行阶段之间的单向边界,并使计划能够根据修改后的基数估计进行调整。在优化过程中,如果我们遇到交错执行的候选对象,即当前的多语句表值函数 (MSTVF),我们将暂停优化,执行适用的子树,捕获准确的基数估计,然后继续优化下游操作。

    您的第一个示例不符合交错执行的条件,但第二个示例可以。第二个示例计划的根节点具有以下属性:

    包含候选人

    第二个示例中的 TVF 人口节点具有:

    交错执行

    运行带有禁用该功能提示的测试查询:

    SELECT TOP (1) VS.* 
    FROM dbo.VoteStats() AS VS
    OPTION (USE HINT ('DISABLE_INTERLEAVED_EXECUTION_TVF'));
    

    给出一个计划,包括填充 TVF 的时间:

    有时间的计划


    此问题仅在第一次执行符合交错 TVF 执行条件的语句时发生。SQL Server 执行计划的 TVF 填充部分,以在查询优化期间获得准确的基数估计。在获得该信息之前,不会编译和优化计划的其余部分。

    编译完成后,SQL Server 不会为第一次执行重复填充表变量的工作,因为这会重复已经完成的工作(在优化期间)。不幸的是,在运行时跳过表填充意味着表变量填充的性能信息无法以通常的方式获得。

    在后续执行中(重用计划),SQL Server确实将表变量填充步骤作为常规查询执行的一部分运行,因此运行时性能数字按预期显示在 showplan 输出中。

    如果再次运行第二个示例,重用缓存的计划,您将看到完整的运行时性能信息。

    注意:此行为与智能查询处理的交错 TVF 执行功能特别相关。这不是 TVF 正常缓存行为的结果,正如我在自我回答的问答中解释的那样SQL Server 缓存多语句表值函数的结果吗?.

    • 14
  2. Pedro Lopes
    2022-07-18T09:47:02+08:002022-07-18T09:47:02+08:00

    并行执行(交换运算符和子线程)中的跟踪时间并非易事,并且在当前实现中实际上并不准确。另一个计划是连续的,因此很容易准确跟踪。是什么让你确定它是关于一个函数的?任何行模式并行执行都不会被每个操作员准确跟踪(按时间)。

    • -4

相关问题

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

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

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

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

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

Sidebar

Stats

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

    连接到 PostgreSQL 服务器:致命:主机没有 pg_hba.conf 条目

    • 12 个回答
  • Marko Smith

    如何让sqlplus的输出出现在一行中?

    • 3 个回答
  • Marko Smith

    选择具有最大日期或最晚日期的日期

    • 3 个回答
  • Marko Smith

    如何列出 PostgreSQL 中的所有模式?

    • 4 个回答
  • Marko Smith

    列出指定表的所有列

    • 5 个回答
  • Marko Smith

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

    • 4 个回答
  • Marko Smith

    你如何mysqldump特定的表?

    • 4 个回答
  • Marko Smith

    使用 psql 列出数据库权限

    • 10 个回答
  • Marko Smith

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

    • 4 个回答
  • Marko Smith

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

    • 7 个回答
  • Martin Hope
    Jin 连接到 PostgreSQL 服务器:致命:主机没有 pg_hba.conf 条目 2014-12-02 02:54:58 +0800 CST
  • Martin Hope
    Stéphane 如何列出 PostgreSQL 中的所有模式? 2013-04-16 11:19:16 +0800 CST
  • 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
    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

热门标签

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