【问题标题】:Why is there a Sort in execution plan when using XQuery为什么在使用 XQuery 时执行计划中有排序
【发布时间】:2015-01-29 08:31:50
【问题描述】:

我在 SQL Server 中有一个包含 10,000,000 行的表

CREATE TABLE [dbo].[tmpTable](
    [EventId] [int] NULL,
    [Data] [nvarchar](max) NULL
) 
CREATE NONCLUSTERED INDEX [ci] ON [dbo].[tmpTable]
(
    [EventId] ASC
)
INCLUDE ([Data])

数据列是 XML

当我使用 SQL 时,

    SELECT  EventId
  , CAST(Data AS xml ).value('(/d/nv/@v)[1]', 'uniqueidentifier') AS ID1
  , CAST(Data AS xml ).value('(/d/nv/@v)[2]', 'int') AS ID2
  , CAST(Data AS xml ).value('(/d/nv/@v)[3]', 'bigint') AS ID3
  , CAST(Data AS xml ).value('(/d/nv/@v)[4]', 'bit') AS ID4
  , CAST(Data AS xml ).value('(/d/nv/@v)[5]', 'nvarchar(100)') AS ID5
  , CAST(Data AS xml ).value('(/d/nv/@v)[6]', 'nvarchar(100)') AS ID6
  , CAST(Data AS xml ).value('(/d/nv/@v)[7]', 'bigint') AS ID7
  , CAST(Data AS xml ).value('(/d/nv/@v)[8]', 'int') AS ID8
    FROM tmpTable
    WHERE EventId = 100

执行计划中会有Sort吗?这会扼杀性能。但是,如果我使用

Select Top 100

排序将消失。任何的想法?有什么办法可以去掉排序

执行计划:

|--Compute Scalar(DEFINE:([Expr1011]=[Expr1010], [Expr1022]=[Expr1021], [Expr1033]=[Expr1032], [Expr1044]=[Expr1043], [Expr1055]=[Expr1054], [Expr1066]=[Expr1065], [Expr1077]=[Expr1076], [Expr1088]=[Expr1087]))
       |--Parallelism(Gather Streams)
            |--Nested Loops(Inner Join, OUTER REFERENCES:([tmpTable].[dbo].[tmptmpTable].[Data]))
                 |--Nested Loops(Inner Join, OUTER REFERENCES:([tmpTable].[dbo].[tmptmpTable].[Data]))
                 |    |--Nested Loops(Inner Join, OUTER REFERENCES:([tmpTable].[dbo].[tmptmpTable].[Data]))
                 |    |    |--Nested Loops(Inner Join, OUTER REFERENCES:([tmpTable].[dbo].[tmptmpTable].[Data]))
                 |    |    |    |--Nested Loops(Inner Join, OUTER REFERENCES:([tmpTable].[dbo].[tmptmpTable].[Data]))
                 |    |    |    |    |--Nested Loops(Inner Join, OUTER REFERENCES:([tmpTable].[dbo].[tmptmpTable].[Data]))
                 |    |    |    |    |    |--Nested Loops(Inner Join, OUTER REFERENCES:([tmpTable].[dbo].[tmptmpTable].[Data]))
                 |    |    |    |    |    |    |--Nested Loops(Inner Join, OUTER REFERENCES:([tmpTable].[dbo].[tmptmpTable].[Data]))
                 |    |    |    |    |    |    |    |--Sort(ORDER BY:([tmpTable].[dbo].[tmptmpTable].[Data] ASC))
                 |    |    |    |    |    |    |    |    |--Parallelism(Repartition Streams, Hash Partitioning, PARTITION COLUMNS:([tmpTable].[dbo].[tmptmpTable].[Data]))
                 |    |    |    |    |    |    |    |         |--Table Scan(OBJECT:([tmpTable].[dbo].[tmptmpTable]), WHERE:([tmpTable].[dbo].[tmptmpTable].[EventId]=(100)))

样本数据

<d>
  <nv n="MediaDesc" v="79cc07e3-8d4a-4c8a-bc9f-3fcba485532b" />
  <nv n="ChannelNumber" v="116" />
  <nv n="Duration" v="61773" />
  <nv n="IsTunedToService" v="True" />
  <nv n="StreamSelection" v="FULLSCREEN_SECONDARY" />
  <nv n="ChannelType" v="LiveTVMediaChannel" />
  <nv n="TuneID" v="634050840267464082" />
</d>

【问题讨论】:

  • EventId 上有索引吗?
  • 您能否提供示例数据并分享您的执行计划,因为我已经测试了上述场景并且没有找到任何类型
  • 是的,EventId 有一个包含数据列的非集群索引
  • 样本数据:
  • @SongTian 为问题添加详细信息,使其易于查看和阅读。以上内容不可读。

标签: sql-server performance sorting xquery sql-execution-plan


【解决方案1】:

如果您将列的数据类型更改为 XML 而不是强制转换为 XML,您将获得更好的性能。

转换为 XML 是一项昂贵的操作。 SQL Server 尽最大努力尽可能快地为您提供所需的结果,在这种情况下,它看起来像是使用表假脱机来完成工作。线轴在您提供的计划中不可见,但我相信它位于嵌套循环连接内的每个分支中。

一些重现您所见内容的代码。

create table T(S nvarchar(max) null);

go

insert into T(S) 
select top(50) '<N>1</N><N>2</N>'
from sys.columns;

insert into T(S) 
select top(50) '<N>3</N><N>4</N>'
from sys.columns;

您的查询:

select cast(T.S as xml).value('(N/text())[2]', 'int')
from T;

查询计划:

lazy spool 缓存最后生成的结果集,只要外部部分的值相同,spool 就可以返回缓存的结果集(回退)。但是,当当前输入值与先前输入值不同时,阀芯必须为新值生成结果(重新绑定)。优化器添加排序运算符以最小化重新绑定的次数。

您可以使用跟踪标志 (8690) 删除创建带有排序和假脱机的计划的优化。 Microsoft 没有记录它,因此不要在生产中使用它,但您可以在测试中使用它来查看优化对您的系统有什么影响。

select cast(T.S as xml).value('(N/text())[2]', 'int')
from T
option (querytraceon 8690);

有关什么是惰性假脱机及其工作原理的更多信息,请参阅 SQLPerformance.com 上 Paul White 的 this answer

【讨论】:

  • 实际上,在我的情况下,我已经测试了 XML 列中的数据,性能很差。所以改为 nvarchar。
【解决方案2】:

看起来 SORT 与并行化有关。添加OPTION (MAXDOP 1) 以防止并行处理。此外,如果 EventId 是唯一的,则使索引唯一。

编辑

表上没有聚集索引 - SORT 可以作为 HEAP 连接到它。使索引 [ci] 聚集。

【讨论】:

  • OPTION (MAXDOP 1) 可以去掉 Parallelism ,但是 Sort 还在,仍然是消费者
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-10-14
  • 2023-03-10
  • 1970-01-01
相关资源
最近更新 更多