Polybase 的性能

Sel*_*BA' 6 sql-server polybase sql-server-2019

我们一直在 SQL Server 2019 (CU2) 机器上试验 Polybase,使用 SQL Server 外部数据源,但性能并不好 - 在大多数情况下提高了 1400%。在每种情况下,我们查询的所有表/视图都来自指向同一外部数据源的外部表。我们尝试过运行在本地框上分解的查询,并使用与作为外部表拉入的视图相同的查询。我们还将来自远程服务器的每个统计数据脚本化到外部表上,没有任何变化。您可以使用示例查询在下面看到性能差异。

服务器在资源方面设置相同:32GB 的 RAM、8 个 vCPU、SSD 磁盘,并且没有其他正在运行的查询。我尝试过两台不同的远程服务器,一台运行带有最新 SP/CU 的 SQL Server 2016,另一台运行 CU2 的单独 2019 机器。服务器是在同一台主机上运行的虚拟机,我们已经排除了任何类型的主机争用。

示例查询:

SELECT
     StockItem_StockNumber, BlanktypeId, NameHTML, BackgroundStrainName, IsExact, IsConditional
     ,ROW_NUMBER() Over(Partition By StockItem_StockNumber, BlanktypeId Order By pt.Name, p.Name, gptr.Text) as row_num
     ,pt.Name as Level1, p.Name as Level2, gptr.Text as Level3, MGIReference_JNumber
     ,gptr.Type as Level3Type  
FROM
     StockItemBlanktypes sig
     INNER JOIN Blanktypes g on g.BlanktypeId = sig.Blanktype_BlanktypeId
     INNER JOIN BlanktypeStockTerms gpt on gpt.Blanktype_BlanktypeId = g.BlanktypeId
     INNER JOIN StocktypeTerms p on p.StocktypeTermId = gpt.StocktypeTerm_StocktypeTermId
     INNER JOIN BlanktypeStockTermReferences gptr on gptr.BlanktypeStockTerm_BlanktypeStockTermId = gpt.BlanktypeStockTermId
     INNER JOIN StockTermClosures ptc on ptc.ChildStockTerm_StocktypeTermId = p.StocktypeTermId
     INNER JOIN StocktypeTerms pt on pt.StocktypeTermId = ptc.ParentStockTerm_StocktypeTermId
WHERE
     ptc.ParentHeaderKey = 3
Run Code Online (Sandbox Code Playgroud)

直接在远程 2016/2019 盒子上运行:

 SQL Server Execution Times:
   CPU time = 3486 ms,  elapsed time = 5035 ms.
Run Code Online (Sandbox Code Playgroud)

使用 Polybase 和 PUSHDOWN OFF 在 2019 盒子上运行:

 SQL Server Execution Times:
   CPU time = 15016 ms,  elapsed time = 92113 ms.
Run Code Online (Sandbox Code Playgroud)

使用 Polybase 和 PUSHDOWN 在 2019 盒子上运行:

 SQL Server Execution Times:
   CPU time = 3875 ms,  elapsed time = 74149 ms.
Run Code Online (Sandbox Code Playgroud)

Polybase 执行计划(无论 PUSHDOWN 选项如何,它们看起来都一样):

Polybase 执行计划

启动 Polybase 查询后不久 sp_whoisactive(等待信息):

等待信息

sp_whoisactive(等待信息)进一步进入 Polybase 查询:

更多等待信息

使用链接服务器而不是 Polybase:

 SQL Server Execution Times:
   CPU time = 3032 ms,  elapsed time = 9316 ms.
Run Code Online (Sandbox Code Playgroud)

运行查询所需的时间大约增加了 1400%。令人困惑的是,微软正在推动 Polybase 作为 ETL 的替代品,但这种性能是不可能的。

其他人是否在使用 Polybase 以及从 SQL Server 到 SQL Server 的连接时看到了类似的性能?而且,有谁知道 Polybase 内部操作会导致这种缓慢吗?

谢谢你。


2020/2/23 更新:

并不是说它对查询性能有任何影响,但我今天发现 Polybase 查询不遵守 MAXDOP 设置(实例范围或查询提示),并且设置的统计信息 CPU 时间没有准确报告。

我能够通过 XML 查看执行计划,这是唯一提供信息的部分。我能在 PREEMPTIVE_SHAREDMEM_GETDATA 上找到的唯一信息是当线程等待调用 COM 对象的 GetData 方法完成时它的等待类型。

在此处输入图片说明


2020/2/23 的第二次更新:

我创建了一个大表,并在本地和 Polybase 上运行了“select *”。这些运行具有几乎相同的运行时间。我向 Microsoft 开立了一个支持案例,如果我们取得任何进展,我会回来报告。


2020/2/24 更新:

在 Kevin 的回应(如下)之后,为了清晰起见,我对原始帖子进行了一些调整,运行他引用的查询/DMV 会返回以下结果:

在此处输入图片说明

Kev*_*sel 6

我将假设上面查询中列出的所有表都是指向同一外部数据源的外部表。考虑到这一点,这里有一些注意事项。

分布式请求

有两个 DMV 将提供比您当前拥有的信息更多的信息: sys.dm_exec_distributed_requestssys.dm_exec_distributed_request_steps。尝试运行慢查询并查看分布式请求 DMV 中显示的内容。这是我喜欢用于此目的的示例查询:

SELECT TOP(100)
    r.execution_id,
    r.status,
    r.error_id,
    r.start_time,
    r.end_time,
    r.total_elapsed_time,
    t.text
FROM sys.dm_exec_distributed_requests r
    CROSS APPLY sys.dm_exec_sql_text(r.sql_handle) t
ORDER BY
    r.end_time DESC;
GO
Run Code Online (Sandbox Code Playgroud)

您最终可能会看到多个结果,如下所示:

单个 T-SQL SELECT 语句生成两个单独的 PolyBase 操作。

对于其中的每一个,您都可以获得所涉及的一组步骤(更改查询以使用您的执行 ID):

SELECT
    rs.execution_id,
    rs.step_index,
    rs.operation_type,
    rs.distribution_type,
    rs.location_type,
    rs.[status],
    rs.error_id,
    rs.start_time,
    rs.end_time,
    rs.total_elapsed_time,
    rs.row_count,
    rs.command
FROM sys.dm_exec_distributed_request_steps rs
WHERE rs.execution_id IN ('QID573', 'QID574')
ORDER BY
    rs.execution_id DESC,
    rs.step_index ASC;
GO
Run Code Online (Sandbox Code Playgroud)

我倾向于寻找的是“过多”的行数。例如,如果我期望返回少量行,但给定步骤的行计数要高得多,则 PolyBase 数据移动服务发送的行数比我理想的要多得多,并迫使 PolyBase 引擎完成将表格组合在一起的脏活。这导致了下一个考虑。

过滤器和谓词

在您的查询中,我没有看到任何显式过滤器或谓词,但我想知道是否存在隐式过滤器。例如,在StocktypeTerms表中,我ParentHeaderKey = 3在连接条件中看到。如果这是一个高度选择性的联接标准,则 PolyBase 可能会流式传输所有行,然后在本地执行过滤器,而不是远程执行过滤器操作并仅拉入所需的行。

出现这种情况的原因有多种,包括复杂的过滤器(这可能是)、PolyBase 无法下推的谓词(对可下推的内容有一些严格的限制)或由两个不同的外部形成的谓词数据源(这是我希望看到的场景,但目前效果不佳)。由于缺少条款WHERE,我不会深入讨论本节的更多细节。

网络性能

如果外部数据源和本地 SQL Server 实例之间存在网络问题,可能会导致速度变慢。在第二次更新中,您提到针对单个表创建外部表并将其所有数据向下传输,并且时间差异很小。这表明网络速度在您的情况下不是一个重要问题。

具体指导

考虑到上述情况,我将针对您的具体情况推荐以下内容,作为找出可能出现问题的方法。

如果您发现到达本地 SQL Server 实例的行数多于执行计划中指示的 313,585 行,则意味着本地 SQL Server 实例上发生了可以远程处理的额外工作。有两件事可能会有所帮助。

首先,尝试使用 on 运行查询OPTION(FORCE EXTERNALPUSHDOWN)。您提到启用和禁用谓词下推(通过在外部数据源定义上设置PUSHDOWN = ONPUSHDOWN = OFF),但不清楚您是否指定了此提示。这有可能会触发 PolyBase 引擎的行为与您仅通过编写查询看到的不同。鉴于您的具体查询,我的猜测是此查询提示不会产生影响。

其次,使用上述 SQL 查询在远程数据源上创建一个视图。然后,在本地创建引用该远程视图的外部表。其作用是强制外部数据源在将任何内容发送到本地 SQL Server 之前将所有这些表连接在一起。

在我的简单案例中,为查询创建视图会减少分布式请求和检索数据的时间:

查询指向视图的外部表。