我们有一个在 SQL Server 2008 R2 上运行的第三方会计系统。要将发票插入这个会计系统,我们必须使用它附带的 API(它只是一组加密的 SP)。
我们的一些批处理需要插入大量(1,000 张)发票。所以,通常在 SQL 中你会写一个 INSERT 语句,它们会很快被插入。
但是,因为我们必须使用 SP 来插入行,所以我们目前有一个 C# 应用程序,它运行一个 PARALLEL FOR 循环并在每次迭代中调用一次 SP。
性能不是很好,虽然这很大程度上取决于 API SP 内部发生的事情,但我想知道 SQL Server 是否可以为我做些什么来提高性能。我知道我可以摆脱 C# 应用程序并在 T-SQL 中使用 CURSOR,但据我所知,这不会并行运行 - 对吗?
同样,我可以动态生成数千条 SQL 语句来调用具有不同参数的 SP,我想优化器可以看到加密的 SP 在做什么(当然比 C# 应用程序更好)并提出一个计划将尽可能多地并行运行它们。
SELECT INTO在 SQL Server 2014 中使用并行所需的最低兼容性级别是多少?
SQL Server 2012 SP2 企业版。用户抱怨速度慢。监控工具显示最高等待事件是CXPACKET。
实例设置
Ran sp_BlitzCache(来自 Brent Ozar 工具集,这些人摇滚)进行进一步诊断,结果显示成本低于 175 的查询并行。
有人见过并行性的成本阈值被忽略吗?
问题
自今年年初以来,由于我们系统中的 SQL 超时,我们一直在经历高度的用户中断。
有问题的 SQL-Server 实例在工作时间内的 CPU 使用率非常高(所有 16 个内核的 CPU 使用率始终高于 90%)。
我们还注意到等待时间非常长:CXPACKET 和 LATCH_EX 的组合约占所有等待的 97%。这在 CXPACKET 和 LATCH_EX 之间分成大约 50/50。
占 LATCH_EX 绝大多数 (>95%) 的非缓冲闩锁等待是 ACCESS_METHODS_DATASET_PARENT。
这表明问题与并行性有关。
等待时间比例的一个例子是:
CXPACKET : 332,301,799 ms
LATCH_EX : 267,955,752 ms
PAGEIOLATCH_SH : 2,955,160 ms
Run Code Online (Sandbox Code Playgroud)
这是 1 月 11 日 08:00-16:24 之间的时间段。
正在考虑的选项
1) 将 MAXDOP 从 0 更改为 4 到 8 之间的值
2) 将并行度的成本阈值从 50 修改为更高的数字
关于如何减轻我们所看到的非常高的 CPU 负载并减少超时的建议最受欢迎,特别是建议的行动方案是否明智,以及将 MAXDOP 和并行成本阈值更改为哪些数字。
背景资料
SQL-Server 2008 R2 在 AMD Opteron 6180 SE …
我有一台装有 SQL Server 2016 的全新服务器。
它有 24 个 CPU,大约 80go 的 RAM。
问题是,有时,CPU 会变得非常高(> 70%),而没有任何具体原因。
如果我查看“execute sp_WhoIsActive @get_locks=1”,我会运行大约 40 个查询,但没有锁定,其中一些查询超过 30 秒而不是几毫秒。
这在生产中大约每天附加一次。到目前为止,我唯一的解决方法是将选项“并行成本阈值”从 90 更改为 89,从 89 更改为 90。更改此值实际上可以在不到 10 秒的时间内解决问题,并且 CPU 费用越来越低,并且我的用户更快乐。
你们知道这个问题的根源吗?我已经考虑过计划缓存,但我不知道如何处理这个想法......
编辑:我已禁用英特尔超线程,但问题仍然存在。我已经安排了一个每小时清理缓存的任务。你有什么主意吗 ?
编辑 2:我在 Microsoft 支持上打开了一个问题。显然,重新启动 SQL Server 2016 解决了页面保留问题。如果我有一个“真正的”修复程序,我会尽快通知您。
在这里继续我的另一个问题,我想要一种简单的方法来形象化答案。
我试过使用这样的查询,但“运行”线程的数量有时会超过 DOP。
SELECT ost.session_id,
ost.exec_context_id,
ost.scheduler_id,
qp.node_id,
w.worker_address,
qp.physical_operator_name,
ost.task_state,
qp.row_count
FROM sys.dm_os_tasks AS ost
JOIN sys.dm_os_workers AS w
ON ost.worker_address = w.worker_address
LEFT JOIN sys.dm_exec_query_profiles AS qp
ON w.task_address = qp.task_address
WHERE ost.session_id = 57
AND ost.task_state = 'RUNNING'
ORDER BY ost.exec_context_id, ost.scheduler_id, qp.node_id, w.worker_address;
Run Code Online (Sandbox Code Playgroud)
我也尝试过使用query_thread_profile扩展事件,但是对于具有多个并行分支的计划,它显示了相同的 N 个线程 ID。这似乎与给出的答案相反,因为 DOP 没有明确限制使用的线程总数。对于以 DOP 4 运行的查询,它看起来像这样。我确信相同的四个线程(加上协调器)不会用于所有分支和运算符。
因此,在 DOP 8 上运行这样的查询会给我三个并行分支。
SELECT COUNT(DISTINCT t1.Data)
FROM dbo.t1
JOIN dbo.t2
ON t1.Id = t2.f_Id
JOIN t3
ON …Run Code Online (Sandbox Code Playgroud) 以下操作始终受到并行限制。
- 扫描公共表表达式 (CTE)。
- 临时表的扫描。
- ...
[...] 同样,
PARALLEL RESTRICTED如果函数访问临时表、客户端连接状态、游标、准备好的语句或系统无法跨工作器同步的其他后端本地状态,则必须标记它们。例如,由于最后一个原因setseed而random受到并行限制。
没有提到 CTE。现在我不确定我是否可以PARALLEL SAFE用于包含 CTE 的函数。对我来说只有PARALLEL RESTRICTED.
上下文:我必须确定现有用户定义函数的最佳标签。该设置是自 Postgres 9.6 以来的新设置,并且可以对性能产生巨大影响,因为涉及PARALLEL SAFE并行工作人员不会执行的功能的操作,PARALLEL RESTRICTED只能由领导者执行。(并PARALLEL USAFE完全禁用并行性。)
我在 pgsql-general 上发布了一个相关的问题。
发生以下错误的典型情况是什么,这意味着什么?
另请注意,当查询失败时,我发现自己与服务器断开了连接(但我自己没有观察到这一点)。
Location: "xact.cpp":4253
Expression: !m_parNestedXactCnt
SPID: 56
Process ID: 2208
Description: Trying to use the transaction while there are 1 parallel nested xacts outstanding
Location: "xact.cpp":4362
Expression: !m_parNestedXactCnt
SPID: 56
Process ID: 2208
Description: Trying to use the transaction while there are 1 parallel nested xacts outstanding
Msg 3624, Level 20, State 1, Line 131
A system assertion check has failed. Check the SQL Server error log for details. Typically, an assertion failure is caused by a software bug …Run Code Online (Sandbox Code Playgroud) 假设我有一个 100 万条记录表。每条记录都可以通过 id 唯一标识。如果该表被划分为 10 个游标,并且 Web 客户端为每个游标发出 10 个请求,说将姓氏字段更改为大写,并且有 10 个内核可用,那么工作速度会快 10 倍吗?还是比直接 for .. 循环对整个表进行常规处理更快?
我知道 PostgreSQl 无法运行进行更改的并行查询。我试图通过使用代码来解决这个问题。请注意,这些记录是独立的。所有更改都严格针对记录。
如果这是一个愚蠢的问题,请道歉。我们正在尝试将我们的多语句表值函数 (MSTVF) 转换为内联表值函数 (ITVF),以避免强制序列化查询。
我有以下 ITVF 函数(淡化了),但执行计划仍然说它的并行度为 1。所讨论的实际函数具有三个由 UNION ALL 分隔的基本 SELECT 语句。
我错过了什么吗?我怎样才能避免在这里强制序列化?
CREATE FUNCTION dbo.Test (@i int)
RETURNS TABLE
AS
RETURN
SELECT @i as [i];
GO
SELECT * FROM dbo.Test (2);
GO
Run Code Online (Sandbox Code Playgroud)
https://www.brentozar.com/pastetheplan/?id=Hyn8o50D7
该实例具有以下设置:
parallelism ×10
sql-server ×5
postgresql ×2
cursors ×1
functions ×1
latch ×1
maxdop ×1
performance ×1
plan-cache ×1
t-sql ×1
timeout ×1