web-dev-qa-db-ja.com

最適化/高速化クエリ

以下のクエリは、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秒です。このクエリを最適化して実行を高速化するにはどうすればよいですか?

6
IT researcher

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

enter image description here

36ミリ秒で実行される変更されたバージョンのクエリプラン。

select count(*)
from dbo.BalanceTable
where [daily_balance].exist('/Root/Row/date/text()[.=''2007-05-10'']')=1

enter image description here

そこでは時間がかかることもたくさんあるので、この変更の影響が更新文で劇的になるとは思いません。更新ステートメントを使用して行ったテストでは、期間が約30%低下しました。これがパフォーマンスにどの程度影響するかを確認するには、データをテストする必要があります。

8
Mikael Eriksson

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インデックスを実装して、フィルタリングを高速化することもできます。

リンク:

MSDN XMLスキーマ

MSDN型付きVS型なしXML

MSDN XMLインデックス

3
D Kramer