You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

为何SQL Server读取大表全量数据时不采用并行执行计划?

问题描述

创建如下SQL Server表结构:

CREATE TABLE [dbo].[GpsData]
(
    [GpsDataID] [int] IDENTITY(1,1) NOT NULL,
    [UnitID] [int] NOT NULL,
    [Longitude] [float] NOT NULL,
    [Latitude] [float] NOT NULL,
    [GpsTimeStamp] [datetime] NOT NULL,
    [SpeedKmpH] [tinyint] NULL,
    [OdoKm] [float] NULL,
    [DataStatusID] [tinyint] NULL,
    [DateCreated] [datetime] NOT NULL,

    PRIMARY KEY CLUSTERED ([GpsDataID] ASC)
                WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, 
                      IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, 
                      ALLOW_PAGE_LOCKS = ON, OPTIMIZE_FOR_SEQUENTIAL_KEY = OFF) ON [PRIMARY]
) ON [PRIMARY]

插入200万行数据后,执行以下三类查询均能获得并行执行计划:

  • 主键范围过滤查询:
SELECT * 
FROM GpsData 
WHERE GpsDataID < 3000
  • 等效全表的条件查询:
SELECT * 
FROM GpsData 
WHERE GpsDataID % 2 = 0 OR GpsdataID % 2 = 1
  • 非主键列过滤查询:
SELECT * 
FROM GpsData 
WHERE Longitude > 1

但执行纯全表扫描查询时:

SELECT * FROM GpsData

却无法生成并行执行计划。按常理全表扫描可由多线程分别扫描表的不同部分并合并结果,为什么会出现这种差异?

原因分析

这是SQL Server查询优化器基于成本估算和并行执行规则做出的选择,核心原因如下:

  • 串行全表扫描的综合成本更低:对于纯全表扫描,SQL Server认为单线程顺序读取聚集索引的开销,远低于启动并行执行的额外成本——包括线程分配、任务协调、结果合并等操作的开销,这些额外消耗抵消了多线程带来的收益,因此优化器选择串行计划。
  • 带过滤的查询触发并行阈值:另外三个查询都包含过滤逻辑,要么需要执行范围查找,要么需要对每一行计算条件(如取模、数值比较),这些操作的CPU开销更高,优化器估算出的执行成本超过了默认的并行执行阈值(Cost Threshold for Parallelism,默认值为5),因此会生成并行计划来分摊CPU负载。
  • 聚集索引的顺序IO优势:该表的聚集主键GpsDataID让数据完全有序存储,串行扫描可以利用顺序IO的高效性,连续读取数据页;而并行扫描需要将数据页拆分给多个线程,反而会破坏顺序IO的连续性,导致IO效率下降,优化器会综合权衡这一点选择更优方案。
  • 优化器的特殊处理逻辑:SQL Server对纯全表扫描的并行计划生成有特殊限制,除非表的规模极大(远超过200万行)或服务器CPU资源极度充裕,否则不会轻易启用并行。而带过滤条件的查询因为有额外计算开销,更容易满足并行触发的成本条件。

内容的提问来源于stack exchange,提问作者Markus

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.21 17:53:11