0

環境: SQL Server 2012。プライマリおよびセカンダリ (値) インデックスは、xml 列に基づいて構築されます。

xml 列 WordIndex を持つテーブル Message があるとします。WordId と WordText を持つテーブル Word もあります。Message.WordIndex の Xml には、次のスキーマがあります。

<xs:schema attributeFormDefault="unqualified"
           elementFormDefault="qualified"
           xmlns:xs="http://www.w3.org/2001/XMLSchema"
           targetNamespace="http://www.example.com">
    <xs:element name="wi">
        <xs:complexType>
            <xs:sequence>
                <xs:element maxOccurs="unbounded" name="w">
                    <xs:complexType>
                        <xs:sequence>
                            <xs:element maxOccurs="unbounded" name="p" type="xs:unsignedByte" />
                        </xs:sequence>
                        <xs:attribute name="wid" type="xs:unsignedByte" use="required" />
                    </xs:complexType>
                </xs:element>
            </xs:sequence>
        </xs:complexType>
    </xs:element>
</xs:schema>

それに付随するいくつかのデータ:

<wi xmlns="http://www.example.com">
  <w wid="1">
    <p>28</p>
    <p>72</p>
    <p>125</p>
  </w>
  <w wid="4">
    <p>89</p>
  </w>
  <w wid="5">
    <p>11</p>
  </w>
</wi>

OR または AND を使用して、xml 列の WordIndex で複数の値を検索する必要があります。私は XQuery の n00b であるため、私がやっていることはかなり初歩的です (デバッグ出力から取得したため、実際の値です)。

with xmlnamespaces(default 'http://www.example.com')
select
    m.Subject,
    m.MessageId,
    m.WordIndex.query('
        let $dummy := 0
        return
            <word_list>
            {
                for $w in /wi/w
                    where $w/@wid=64
                    return <word wid="64" pos="{data($w/p)}"/>
            }
            {
                for $w in /wi/w
                    where $w/@wid=70
                    return <word wid="70" pos="{data($w/p)}"/>
            }
            {
                for $w in /wi/w
                    where $w/@wid=63
                    return <word wid="63" pos="{data($w/p)}"/>
            }
            </word_list>
        ') as WordPosition
from
    Message as m
-- more joins go here ...
where
    -- more conditions go here ...
    and m.WordIndex.exist('/wi/w[@wid=64]') = 1
    and m.WordIndex.exist('/wi/w[@wid=70]') = 1
    and m.WordIndex.exist('/wi/w[@wid=63]') = 1

これをどのように最適化できますか?

4

1 に答える 1

0

期待される結果が何であるかはわかりませんが、これをもう少し一般的でデータ駆動型にすることができます (たとえば、sql:column または sql:variable を使用)。次のようなことを試してください:

declare @wids table ( wid INT PRIMARY KEY )

insert into @wids ( wid )
values ( 64 ), ( 70 ) 

;with xmlnamespaces(default 'http://www.example.com') 
select 
    m.Subject, 
    m.MessageId, 
    m.WordIndex.query(' 
        return 
            <word_list> 
            { 
                for $w in /wi/w
                where $w/@wid = sql:column("w.wid")
                return <word wid="{$w/@wid}" pos="{data($w/p)}"/> 
            } 
            </word_list> 
        ') as WordPosition 
from 
    Message as m
    cross apply @wids w 
where m.WordIndex.exist('wi/w[@wid=sql:column("w.wid")]') = 1
于 2012-09-09T21:35:52.680 に答える