SQL Server / XML.query() 导致大量内存授予

ube*_*oke 7 xml sql-server xquery memory-grant

以下(在我的系统上,在 SQL Server 2016 和 2019 std 上测试)产生大量内存授予请求(3327 MB)

declare @wibble xml = '<wibble><wobble>1</wobble></wibble>'

select @wibble.query('//wobble[1]')
Run Code Online (Sandbox Code Playgroud)

我可以做些什么来减少补助金?

https://www.brentozar.com/pastetheplan/?id=HkezxS8-K

Mik*_*son 14

快速查看您的 xpath 表达式//wobble[1]和测试数据,您正在寻找第一个wobble可以找到的数据。

人们甚至可以认为您的表达式与此相同,这(//wobble)[1]与您的测试数据给出了相同的结果。使用这样的括号,您将从wobbleXML 文档中获得第一个,并且不会为查询授予内存。

因此,您可能知道使用//wobble[1](不带括号) 根本不同。此查询将查看文档中的所有元素,如果其中有wobble元素,它将返回第一个元素并将结果与​​所有元素连接起来。

例如。

<wibble>
  <wobble>1</wobble>
  <wobble>2</wobble>
  <wobble>3</wobble>
  <wibble>
    <nowobblehere>X</nowobblehere>
    <wobble>A</wobble>
    <wobble>B</wobble>
    <wobble>C</wobble>
  </wibble>
</wibble>
Run Code Online (Sandbox Code Playgroud)

使用//wobble[1]你会得到

<wobble>1</wobble>
<wobble>A</wobble>
Run Code Online (Sandbox Code Playgroud)

在哪里使用(//wobble)[1]只会给你<wobble>1</wobble>

如果你真的需要连接结果,你可以粉碎你的节点,然后重建它们for xml path以获得更小的内存授权。对我来说,它要求 1MB 而不是 280MB。仍然有过多的内存授予警告。

select T.X.query('wobble[1]')
from @wibble.nodes('//*[wobble]') as T(X)
for xml path('');
Run Code Online (Sandbox Code Playgroud)

//*[wobble]为您提供具有wobble节点的所有节点,并wobble[1]为您提供wobble该节点中的第一个节点。