以下のクエリは、SQL Serverデータベースでテーブルを挿入および更新するために使用されます。 SSMSで初めて実行するときにXQueryが遅くなります。
新しい<ROW>
を挿入
Update BalanceTable set [daily_balance].modify('
insert <Row><date>2007-05-10</date><Balance>-8528</Balance><Transactiondr>835</Transactiondr><Transactioncr>9363</Transactioncr><Rowid>2</Rowid></Row>
as first into (/Root)[1]')
where [daily_balance].exist('/Root/Row[date=''2007-05-10''] ')=0
and [daily_balance].exist('/Root')=1
and [AccountID]=61
and [Date] = '31-May-2007';
バランスを変更する
Update BalanceTable
set [daily_balance].modify('
replace value of (/Root/Row[date=''2007-05-10'']/Balance/text())[1]
with (/Root/Row[date=''2007-05-10'']/ Balance)[1] -3510')
where [AccountID]=577
and [Date]='31-May-2007'
and [daily_balance].exist('/Root/Row[date=''2007-05-10'']')=1;
transactioncrを変更する
Update BalanceTable
set [daily_balance].modify('
replace value of (/Root/Row[date=''2007-05-10'']/Transactioncr/text())[1]
with (/Root/Row[date=''2007-05-10'']/ Transactioncr)[1] +3510')
where [AccountID]=577
and [Date]='31-May-2007'
and [daily_balance].exist('/Root/Row[date=''2007-05-10'']')=1;
USE [Fitness Te WM16]
GO
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
SET ANSI_PADDING ON
GO
CREATE TABLE [dbo].[BalanceTable](
[AccountID] [int] NULL,
[Type] [char](10) NULL,
[Date] [date] NULL,
[Balance] [decimal](15, 2) NULL,
[TRansactionDr] [decimal](15, 2) NULL,
[TRansactionCr] [decimal](15, 2) NULL,
[daily_Balance] [xml] NULL,
[AutoIndex] [int] IDENTITY(1,1) NOT NULL,
CONSTRAINT [PK_BalanceTable] PRIMARY KEY CLUSTERED
(
[AutoIndex] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY] TEXTIMAGE_ON [PRIMARY]
GO
SET ANSI_PADDING OFF
GO
実行計画はここに添付されています SQL実行計画
参照用のサンプルXMLデータを以下に示します。
<Root>
<Row>
<date>2007-05-31</date>
<Balance>-47718</Balance>
<Transactiondr>0</Transactiondr>
<Transactioncr>47718</Transactioncr>
<Rowid>7</Rowid>
</Row>
<Row>
<date>2007-05-29</date>
<Balance>-31272</Balance>
<Transactiondr>0</Transactiondr>
<Transactioncr>31272</Transactioncr>
<Rowid>6</Rowid>
</Row>
<Row>
<date>2007-05-18</date>
<Balance>-48234</Balance>
<Transactiondr>0</Transactiondr>
<Transactioncr>48234</Transactioncr>
<Rowid>5</Rowid>
</Row>
<Row>
<date>2007-05-11</date>
<Balance>-42120</Balance>
<Transactiondr>0</Transactiondr>
<Transactioncr>42120</Transactioncr>
<Rowid>4</Rowid>
</Row>
<Row>
<date>2007-05-10</date>
<Balance>-21060</Balance>
<Transactiondr>0</Transactiondr>
<Transactioncr>21060</Transactioncr>
<Rowid>3</Rowid>
</Row>
<Row>
<date>2007-05-08</date>
<Balance>-10530</Balance>
<Transactiondr>0</Transactiondr>
<Transactioncr>10530</Transactioncr>
<Rowid>2</Rowid>
</Row>
<Row>
<date>2007-05-04</date>
<Balance>-21060</Balance>
<Transactiondr>0</Transactiondr>
<Transactioncr>21060</Transactioncr>
<Rowid>1</Rowid>
</Row>
<Maxrowid>7</Maxrowid>
</Root>
SQL Server 2008 R2を使用しています。 500クエリの合計時間は20〜40秒です。このクエリを最適化して実行を高速化するにはどうすればよいですか?
XML_DMLステートメントを最適化するためにできることはないと思います。
ただし、where句でexists
チェックについて何かを行うことができます。
述語の前に、チェックしている値まで完全にトラバースすることをお勧めします。
したがって、.exist('/Root/Row[date=''2007-05-10'']')
の代わりに.exist('/Root/Row/date/text()[.=''2007-05-10'']')
を実行できます。
私のコンピューターで173ミリ秒で3200行以上実行されるexists
のバージョンのクエリプラン。
select count(*)
from dbo.BalanceTable
where [daily_balance].exist('/Root/Row[date=''2007-05-10'']')=1
36ミリ秒で実行される変更されたバージョンのクエリプラン。
select count(*)
from dbo.BalanceTable
where [daily_balance].exist('/Root/Row/date/text()[.=''2007-05-10'']')=1
そこでは時間がかかることもたくさんあるので、この変更の影響が更新文で劇的になるとは思いません。更新ステートメントを使用して行ったテストでは、期間が約30%低下しました。これがパフォーマンスにどの程度影響するかを確認するには、データをテストする必要があります。
XMLスキーマを作成して、列にxml形式を指定してみます。これは、現在型指定されていないXMLを解析しているときに説明している多数の呼び出しに役立つはずです。
次のクエリを使用して、現在定義されているスキーマコレクションを確認できます。
SELECT * FROM sys.xml_schema_collections AS XML1
INNER JOIN sys.xml_schema_elements AS XML2
ON XML1.xml_collection_id = XML2.xml_collection_id
提供されたサンプルデータ用に新しいデータを作成するには、次のようになります。
CREATE XML SCHEMA COLLECTION BalanceXMLSchema AS
'<?xml version="1.0" encoding="utf-8"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
<xs:element name="Root">
<xs:complexType>
<xs:sequence>
<xs:element name="Row" maxOccurs="unbounded">
<xs:complexType>
<xs:sequence>
<xs:element type="xs:date" name="date"/>
<xs:element type="xs:decimal" name="Balance"/>
<xs:element type="xs:decimal" name="Transactiondr"/>
<xs:element type="xs:decimal" name="Transactioncr"/>
<xs:element type="xs:int" name="Rowid"/>
</xs:sequence>
</xs:complexType>
</xs:element>
<xs:element type="xs:int" name="Maxrowid"/>
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:schema>
'
--And then use it in your table creation
CREATE TABLE [dbo].[BalanceTable](
[AccountID] [int] NULL,
[Type] [char](10) NULL,
[Date] [date] NULL,
[Balance] [decimal](15, 2) NULL,
[TRansactionDr] [decimal](15, 2) NULL,
[TRansactionCr] [decimal](15, 2) NULL,
[daily_Balance] [xml](BalanceXMLSchema) NULL, --By specifying it in the XML column definition
[AutoIndex] [int] IDENTITY(1,1) NOT NULL,
CONSTRAINT [PK_BalanceTable] PRIMARY KEY CLUSTERED
(
[AutoIndex] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY] TEXTIMAGE_ON [PRIMARY]
GO
注目に値するのは、テーブル定義からデータ型を取得したことです。私はあなたのXML /真の値に基づいて確かに言うことができないので。だからあなたはそれらをいじることができます。上記のコードは、テーブルの作成に機能するようにテストされています。
また、(おそらくセカンダリ)XMLインデックスを実装して、フィルタリングを高速化することもできます。
リンク: