我有一个非常大的查询(约 630 行),它涉及大量嵌套SELECT语句并从多个视图中提取。我们的 SQL Server 将并行度设置为 2,阈值为 95(这样设置是因为我们的 DBA 正在根据其他一些应用程序对其进行优化)。此查询最近开始需要 5-10 分钟才能完成,而通常不到一分钟。在调查原因时,我们注意到它似乎永远不会触发并行,总是串行运行,并怀疑这可能与它的性能有关。奇怪的是,在实验过程中,我们甚至将阈值降回了默认值 5 秒,它仍然无法并行运行。什么可以阻止它?
我们一直在当时没有其他人使用的非生产环境中进行测试,因此这是唯一运行的查询。我们的DBA也尝试过清除缓存和计划,甚至回收系统,但都没有效果。
更新 1:根据评论,我已经确认统计数据每晚更新,但问题仍然存在。我们实际上将代码回滚到没有如此严重性能问题的早期版本,但将继续测试此代码,因为它应该提高旧代码的性能,并且在初始测试中确实做到了。将在此处相应地更新。
Astor Data、Greenplum 和 GridSQL 都允许对 SQL 查询进行大规模并行处理。它们也都是围绕 PostgreSQL 技术构建的。这仅仅是因为许可问题还是有其他原因?对我来说,它看起来像 MyISAM,不符合 ACID,因此不会遇到与 MVCC 相同的问题(如这里所见),因为 PostgreSQL 更适合构建高性能数据仓库。毕竟,就我所见,OLAP 负载不需要事务。
这与在带有嵌套循环的查询之上有一个公共密钥驱动程序有关,并且来自驱动程序的行的并行性是需求类型或循环类型。我会假设需求分区会表现得更好,但我得到了相反的结果。
我在 SQL Server 中的同一次尝试中同时启动了查询。当我监控的查询运行时dm_exec_query_profilesdmv 不断。我注意到循环版本的启动速度要快得多,它们在 dmv 的表插入部分中插入更多行的速度要快得多,而且它们从驱动程序侧并行性部分更快地获取更多行。从逻辑上思考需求分区应该更有利,因为我们的 SQL 服务器通常超过 50-60% 的 cpu,运行 litespeed 备份,有 64 个内核等。我能够通过循环分区更好地平衡线程上处理的行,还有数据分区内是如此不平衡我注意到需求分区中的一些线程仅处理来自驱动程序的 1 条记录,而来自驱动程序的平均记录大约为 196。通过需求分区,我对分区内的行进行降序排序,而在循环中我尝试更好地平衡行。
我是否应该始终使用循环法,为什么循环法开始处理行的速度比需求分区快得多,我可以对需求分区进行更多优化吗?
查询计划位于 One Drive 链接中,我找不到在此处发布它们的另一种方式(pastetheplan 仅接受 xml,它不捕获计划资源管理器捕获的等待统计信息和持续时间等额外信息)。
CompareRoundRobinToDemand_DM_2_5114.pesession CompareRoundRobinToDemand_RRB_2_3046.pesession
同时开始,Round Robin 的速度要快得多
CompareRoundRobinToDemand_DM_3_5228.pesession CompareRoundRobinToDemand_RRB_3_4367.pesession
同时开始,Round Robin 又快了
CompareRoundRobinToDemand_DM_4_4813.pesession CompareRoundRobinToDemand_RRB_4_3577.pesession
同时开始,Round Robin 又快了
先感谢您。
我能够平衡几乎完美的循环行,而对于需求,我只是按行降序排列驱动程序,平衡需求中的行是我的程序中的一个选项,但没有产生更好的结果。在我的观察中,当整体 CPU 使用率较低时,需求表现更好,而当服务器更忙时,轮询表现更好。我注意到与循环相比,需求创建了一个额外的线程,而且总体 CPU 利用率需求略高于类似的 RRB 版本。
我知道需求中的行分布不平衡。内存授予也是故意的,它最终没有使用那么多内存。从驱动程序传递的前 16 条记录的需求与循环法相同,但循环法由于某种原因开始处理它们的速度要快得多。我想明白为什么。我还想了解什么时候使用需求或循环法更有利。似乎当服务器空闲时需求工作得更快,当服务器有现有负载时循环更快,这是迄今为止的观察,这是否有我不知道的基础。
Microsoft 是否更改了有关文件数量和并行度的查询优化器?优化器是否不再考虑文件数量来确定查询的并行度?如果是这样,有人知道更改是什么时候进行的吗?如果没有,任何人都可以提供指向讨论该主题的 Microsoft 文档的链接(SQL Server 2014 或 2016 的当前文档)?
我想MAXDOP在我的电脑上测试一下。所以我MAXDOP为特定查询设置为 2。但是,当我在运行查询时查看任务管理器中的逻辑处理器时,看起来它们都被使用了。我认为如果MAXDOP设置为 2 ,它只会使用 2 个逻辑处理器?有谁知道发生了什么?请看下图。
另一个问题是,DOP执行计划返回的值是1。现在我知道设置MAXDOP并不意味着SQL Server 会实际使用设置的数字。然而,考虑到我的 4 个逻辑处理器似乎都被用于处理查询,看到DOP1.
这是我运行的查询:

这是我运行时发生的情况(即看起来所有 4 个逻辑处理器都用于运行查询):

我正在集群上尝试 oracles 并行选项,但令人惊讶的是,并行选项的结果更糟。我期待并行选项有一些改进,但肯定不会有更糟的结果。我想知道为什么会这样,以及我在集群上使用并行选项的方式是否有任何问题。
当我拥有的 CPU 数量为 8 时,我使用的度数为 4。我尝试直接将并行添加到集群ALTER CLUSTER cluster PARALLEL 4以及在索引/*+ PARALLEL_INDEX(clust_index, 4) */和表的语句中/*+ PARALLEL(4) */,
这是我从并行的跟踪:
无并行:
假设有一个带有聚集索引的表
create table [a_table] ([key] binary(900) unique clustered);
Run Code Online (Sandbox Code Playgroud)
和一些数据
insert into [a_table] ([key])
select top (1000000) row_number() over (order by @@spid)
from sys.all_columns a cross join sys.all_columns b;
Run Code Online (Sandbox Code Playgroud)
通过检查该表的存储统计
select st.index_level, page_count = sum(st.page_count)
from sys.dm_db_index_physical_stats(
db_id(), object_id('a_table'), NULL, NULL, 'DETAILED') st
group by rollup (st.index_level)
order by grouping_id(st.index_level), st.index_level desc;
Run Code Online (Sandbox Code Playgroud)
有人能看见
index_level page_count
----------- ----------
8 1
7 7
6 30
5 121
4 487
3 1952
2 7812
1 31249
0 125000
NULL 166659
Run Code Online (Sandbox Code Playgroud)
该表总共需要 166659 页。
然而表扫描 …
sql-server parallelism database-internals sql-server-2014 scan
我和一个非常老的 DBA 一起工作,他说了很多奇怪的话。Dude 有一本 O'Reilly 的书,封面上只有一个变形虫。
午餐时我们讨论了并行性,因为我们的新服务器有 24 个内核。他说,在并行计划中,每个操作员都会获得 DOP 线程。因此,如果您有 MAXDOP 8 并且您的查询有 4 个并行运算符,它将一次使用 32 个线程。
这似乎不对,因为您会很快用完线程。
我还读到整个查询可能只有 8 个,这似乎太少了。
为什么我在 sysprocesses 中看到每个 SPID 的线程数比 MAXDOP 多?
他们中的任何一个都正确吗?
如果我有一批两个不同的SELECT语句,是否可以并行执行它们(如果 SQL 优化器认为它是最有效的执行方法)?
如果第一个SELECT语句选择到临时表中,SELECT然后第二个语句插入到同一个临时表中,这是否会阻止两个语句并行运行?
(我猜答案是肯定的,是的 :)。
sql-server parallelism sql-server-2008-r2 temporary-tables sql-server-2017
我发现本地计算机上的查询计划和 Azure SQL 上的查询计划之间存在奇怪的差异。我正在尝试实现行级安全性,其中我从 SESSION_CONTEXT 读取用户标识符,然后在 TVF 中检查用户是否具有访问权限。
在我的本地计算机上 - SQL Server 2019 Developer Edition,兼容级别 150 的数据库,查询计划符合预期。但是当我在兼容级别为 150 的 Azure DB 上运行它时,我只能获得带有NonParallelPlanReason="NonParallelizableIntrinsicFunction". 我尝试了超大规模数据库以及弹性池中的数据库,两个数据库的结果相同。
您可以使用以下代码重现该内容:
CREATE TABLE Users (
UserIdentifier nvarchar(100) PRIMARY KEY CLUSTERED
)
INSERT INTO Users (UserIdentifier) VALUES ('MyUserIdentifier')
CREATE TABLE TableWithRLS (
Id int NOT NULL IDENTITY(1,1) PRIMARY KEY CLUSTERED,
DataColumn nvarchar(100) NULL
)
INSERT INTO TableWithRLS (DataColumn)
SELECT TOP 10000000 A.[name] FROM sys.all_columns AS A
CROSS JOIN sys.all_columns AS B
CROSS JOIN sys.all_columns AS C …Run Code Online (Sandbox Code Playgroud) performance sql-server parallelism azure-sql-database row-level-security
parallelism ×10
sql-server ×8
maxdop ×1
mysql ×1
optimization ×1
oracle ×1
partitioning ×1
performance ×1
postgresql ×1
rdbms ×1
scan ×1