为何筛选条件放宽时查询优化器选择串行执行计划?
放宽筛选条件导致执行计划从并行转串行的原因分析
正在学习Iztik Ben-Gan所著的《T-SQL Querying》一书时,遇到如下疑问:为何放宽筛选条件后,查询优化器会从并行执行计划转为串行执行计划?
现象对比
两个查询均对dbo.Orders表执行聚集索引扫描,但执行计划类型不同:
并行执行计划的查询
SELECT [orderid], [custid], [empid], [shipperid], [orderdate], [filler] FROM dbo.Orders WHERE orderid <= 30000
串行执行计划的查询
SELECT [orderid], [custid], [empid], [shipperid], [orderdate], [filler] FROM dbo.Orders WHERE orderid <= 490000
表与索引信息
该表共100万行数据,orderid分布均匀,使用的聚集索引定义如下:
CREATE CLUSTERED INDEX [idx_cl_od] ON [dbo].[Orders] ( [orderdate] ASC )WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, SORT_IN_TEMPDB = OFF, DROP_EXISTING = OFF, ONLINE = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON, OPTIMIZE_FOR_SEQUENTIAL_KEY = OFF) ON [PRIMARY] GO
原因分析
SQL Server查询优化器选择并行/串行计划的核心依据是成本收益比,而非单纯的行数多少,具体到这个场景:
- 并行执行的前提与开销:并行计划需要额外开销(线程调度、数据拆分/合并、协调通信),只有当查询的预估执行成本超过「并行阈值(默认值为5,指CPU+IO成本的总和)」,且并行带来的效率提升能覆盖额外开销时,优化器才会选择并行。
- 第一个查询(小范围筛选):由于聚集索引按
orderdate排序,与筛选条件orderid无关,优化器只能执行聚集索引扫描(无法用seek定位),预估扫描行数仅3万(占总数据3%)。此时优化器判断:用多线程分摊扫描和筛选的工作量,能抵消并行开销并提升效率,因此选择并行计划。 - 第二个查询(大范围筛选):预估扫描行数达49万(占总数据49%),此时优化器会重新计算成本:
- 大范围扫描时,串行执行的磁盘顺序读取效率更高(并行可能导致IO碎片化);
- 并行所需的线程调度、数据合并开销,远超过多线程带来的效率提升;
因此优化器认为串行计划的总成本更低,转而选择串行执行。
补充说明
- 这里的关键是聚集索引键与筛选条件不匹配,导致两个查询都只能走全表扫描(聚集索引扫描),优化器完全依赖统计信息预估行数和成本;
- 并行阈值可通过
sp_configure 'cost threshold for parallelism'调整,但默认值5是经过大量场景验证的合理阈值。
内容的提问来源于stack exchange,提问作者Sveinung Tyssedal
相关产品推荐
相关产品推荐

