优化/加速查询

IT *_*her 6 sql-server sql-server-2008-r2 xquery query-performance

下面的查询用于插入和更新 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';
Run Code Online (Sandbox Code Playgroud)

修改余额

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;
Run Code Online (Sandbox Code Playgroud)

修改事务

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;
Run Code Online (Sandbox Code Playgroud)

表模式

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  
Run Code Online (Sandbox Code Playgroud)

执行计划

执行计划附在这里sql执行计划

样本数据

下面给出了供参考的示例 XML 数据。

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';
Run Code Online (Sandbox Code Playgroud)

我正在使用 SQL Server 2008 R2。500 次查询所需的总时间为 20 到 40 秒。如何优化此查询以加快执行速度?

Mik*_*son 8

我认为您无法优化 XML_DML 语句。

但是您可以exists对 where 子句中的检查做一些事情。

最好在谓词之前完全遍历到您正在检查的值。

所以,而不是.exist('/Root/Row[date=''2007-05-10'']')你可以做.exist('/Root/Row/date/text()[.=''2007-05-10'']')

您的版本的查询计划exists在我计算机上的 3200 行中以 173 毫秒执行。

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

在此处输入图片说明

在 36 毫秒内执行的修改版本的查询计划。

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

在此处输入图片说明

我不希望此更改对您的更新语句产生如此巨大的影响,因为那里还有很多事情需要时间进行。在我对更新语句所做的测试中,我看到持续时间下降了大约 30%。你必须对你的数据进行测试,看看这对你的表现有多大影响。


D K*_*mer 3

我会尝试通过创建 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
Run Code Online (Sandbox Code Playgroud)

要为您提供的示例数据创建一个新数据,这应该类似于:

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 
Run Code Online (Sandbox Code Playgroud)

值得注意的是,我从您的表定义中获取了数据类型。因为我不能根据您的 XML/真实值进行确定。所以你可以摆弄他们。上面的代码经过测试可以用于创建表。

您还可以尝试实施(可能是辅助的)XML 索引来加快过滤速度。

链接:

MSDN XML 架构

MSDN 类型化 VS 非类型化 XML

MSDN XML 索引