标签: xml

使用 XML 阅读器优化计划

从这里执行查询以从默认扩展事件会话中提取死锁事件

SELECT CAST (
    REPLACE (
        REPLACE (
            XEventData.XEvent.value ('(data/value)[1]', 'varchar(max)'),
            '<victim-list>', '<deadlock><victim-list>'),
        '<process-list>', '</victim-list><process-list>')
    AS XML) AS DeadlockGraph
FROM (SELECT CAST (target_data AS XML) AS TargetData
    FROM sys.dm_xe_session_targets st
    JOIN sys.dm_xe_sessions s ON s.address = st.event_session_address
    WHERE [name] = 'system_health') AS Data
CROSS APPLY TargetData.nodes ('//RingBufferTarget/event') AS XEventData (XEvent)
    WHERE XEventData.XEvent.value('@name', 'varchar(4000)') = 'xml_deadlock_report';
Run Code Online (Sandbox Code Playgroud)

在我的机器上完成大约需要 20 分钟。报告的统计数据是

Table 'Worktable'. Scan count 0, logical reads 68121, physical reads 0, read-ahead reads 0, 
         lob logical reads 25674576, lob …
Run Code Online (Sandbox Code Playgroud)

xml sql-server execution-plan database-internals sql-server-2012

38
推荐指数
2
解决办法
1万
查看次数

XML 索引的性能非常奇怪

我的问题基于此:https : //stackoverflow.com/q/35575990/5089204

为了在那里给出答案,我做了以下测试场景。

测试场景

首先我创建一个测试表并用 100.000 行填充它。一个随机数(0 到 1000)应该为每个随机数产生 ~100 行。这个数字被放入一个 varchar col 并作为一个值放入您的 XML。

然后我做一个像 OP 那样的调用,需要它使用 .exist() 和 .nodes() ,第二个有一个小优势,但都需要 5 到 6 秒。事实上,我调用了两次:第二次以交换的顺序和稍微改变的搜索参数和“//item”而不是完整路径来避免通过缓存结果或计划产生误报。

然后我创建一个 XML 索引并执行相同的调用

现在 - 真正让我感到惊讶的是什么!-在.nodes完整路径是比以前(9秒)慢得多,但.exist()下降到半秒,用全路径甚至下降到约0.10秒。(同时.nodes()具有短的路径比较好,但仍远远落后于.exist()

问题:

我自己的测试简而言之:XML 索引可以极大地破坏数据库。它们可以极大地加快速度(s.edit 2),但也可以减慢您的查询速度。我想了解它们是如何工作的...什么时候应该创建一个 XML 索引?为什么.nodes()有索引比没有索引更糟糕?如何避免负面影响?

CREATE TABLE #testTbl(ID INT IDENTITY PRIMARY KEY, SomeData VARCHAR(100),XmlColumn XML);
GO

DECLARE @RndNumber VARCHAR(100)=(SELECT CAST(CAST(RAND()*1000 AS INT) AS VARCHAR(100)));

INSERT INTO #testTbl VALUES('Data_' + …
Run Code Online (Sandbox Code Playgroud)

performance xml sql-server sql-server-2012

32
推荐指数
1
解决办法
4493
查看次数

FOR XML 无法序列化数据,因为它包含字符 (0x0000)

我有一个很大的查询(如有必要,我会在此处发布)并且出现此错误:

消息 6841,级别 16,状态 1,第 1 行
FOR XML 无法序列化节点“NoName”的数据,因为它包含 XML 中不允许的字符 (0x0000)。要使用 FOR XML 检索此数据,请将其转换为 binary、varbinary 或 image 数据类型并使用 BINARY BASE64 指令。

我唯一使用的部分FOR XML在这里:

WHERE 
    (CodFuncionario = Results.CodFuncionario) 
FOR XML PATH(''), TYPE).value('(./text())[1]', 
    'VARCHAR(MAX)'), 1, 2, '') AS [Experiencia]
Run Code Online (Sandbox Code Playgroud)

但是,什么是node noname?以及如何查找此值:(0x0000)

这是子查询之一(我拥有 FOR XML 的唯一部分):

SELECT 
    [CodFuncionario],
    STUFF
    (
        (
            SELECT 
                ' / ' + 
            CAST
            (
                [DescFuncao] + '-' + 
                [DescTempoExperiencia] 
                AS VARCHAR(MAX)
            )...
FROM 
    [Linked_Server].db.dbo.tblFuncionarioExperiencia T0
INNER JOIN
    [Linked_Server].db.dbo.tblFuncao T1 On T0.codFuncao = …
Run Code Online (Sandbox Code Playgroud)

xml sql-server sql-server-2008-r2

22
推荐指数
3
解决办法
3万
查看次数

将 VARCHAR 转换为 VARBINARY

我一直在一个表中记录昂贵的运行查询及其查询计划,以便我们监控性能趋势并确定需要优化的区域。

然而,现在已经到了查询计划占用太多空间的地步(因为我们针对每个查询存储整个计划)。

因此,我试图通过将 QueryPlanHash 和 QueryPlan 提取到另一个表来规范化现有数据。

CREATE TABLE QueryPlans
(
    QueryPlanHash VARBINARY(25),
    QueryPlan XML,
    CONSTRAINT PK_QueryPlans PRIMARY KEY
    (
      QueryPlanHash
    )
);
Run Code Online (Sandbox Code Playgroud)

由于query_plan_hashin的定义sys.dm_exec_query_stats是一个二进制字段(并且我会定期插入新数据),因此我使用VARBINARY了新表中的数据类型。

但是,下面的插入失败了...

INSERT INTO QueryPlans
    ( QueryPlanHash, QueryPlan )
SELECT queryplanhash, queryplan
FROM
(
    SELECT 
      p.value('(./@QueryPlanHash)[1]', 'varchar(20)') queryplanhash,
      QueryPlan,
      ROW_NUMBER() OVER (PARTITION BY p.value('(./@QueryPlanHash)[1]', 'varchar(20)') ORDER BY DateRecorded) rownum
    FROM table
    CROSS APPLY QueryPlan.nodes('/ShowPlanXML/BatchSequence/Batch/Statements/StmtSimple[@QueryPlanHash]') t(p)
) data
WHERE rownum = 1
Run Code Online (Sandbox Code Playgroud)

....有错误

Implicit conversion from data type varchar to varbinary is …
Run Code Online (Sandbox Code Playgroud)

xml sql-server varchar sql-server-2012 varbinary

19
推荐指数
1
解决办法
17万
查看次数

LOB_DATA、慢表扫描和一些 I/O 问题

我有一个相当大的表,其中一列是 XML 数据,XML 条目的平均大小约为 15 KB。所有其他列都是常规整数、大整数、GUID 等。为了获得一些具体数字,假设该表有一百万行,大小约为 15 GB。

我注意到的是,如果我想选择所有列,这个表选择数据的速度真的很慢。当我做

SELECT TOP 1000 * FROM TABLE
Run Code Online (Sandbox Code Playgroud)

从磁盘读取数据大约需要 20-25 秒 - 即使我没有对结果强加任何排序。我使用冷缓存(即 after DBCC DROPCLEANBUFFERS)运行查询。IO统计结果如下:

扫描计数 1,逻辑读 364,物理读 24,预读 7191,lob 逻辑读 7924,lob 物理读 1690,lob 预读 3968。

它抓取了大约 15 MB 的数据。执行计划如我所料显示聚集索引扫描。

除了我的查询外,磁盘上没有任何 IO;我还检查了聚集索引碎片是否接近 0%。这是一个消费级 SATA 驱动器,但我仍然认为 SQL Server 能够以比 ~100-150 MB/min 更快的速度扫描表。

XML 字段的存在导致大部分表数据位于 LOB_DATA 页上(实际上约 90% 的表页是 LOB_DATA)。

我想我的问题是 - 我认为 LOB_DATA 页面会导致扫描缓慢不仅是因为它们的大小,还因为当表中有很多 LOB_DATA 页面时,SQL Server 无法有效扫描聚集索引,我是否正确?

更广泛地说 - 拥有这样的表结构/数据模式是否合理?使用 Filestream 的建议通常说明更大的字段大小,所以我真的不想走那条路。我还没有真正找到关于这个特定场景的任何好的信息。

我一直在考虑 XML 压缩,但它需要在客户端或使用 SQLCLR 完成,并且需要在系统中实现相当多的工作。

我尝试了压缩,因为 XML 是高度冗余的,所以我可以(在 …

performance xml sql-server blob

19
推荐指数
2
解决办法
2901
查看次数

SQL Server 在插入时更改 XML 结构

我正在将一些 XML 数据插入 SQL Server 中的 XML 列,但在插入数据后,它已被 sql server 更改。这是我插入的数据

              <xsl:value-of select="name/n/given" />
            <xsl:text> </xsl:text>
          <xsl:value-of select="name/n/family" />
Run Code Online (Sandbox Code Playgroud)

当我读回来时,它看起来像这样

              <xsl:value-of select="name/n/given" />
          <xsl:text />
          <xsl:value-of select="name/n/family" />
Run Code Online (Sandbox Code Playgroud)

注意第二行。这是一个问题,因为它改变了 XSLT 转换输出的方式。第一个例子将在给定和姓氏之间创建一个空格,而第二个不会创建任何空格,所以它会像约翰约翰森,而第一个会像约翰约翰森。

有没有办法解决这个问题?

xml sql-server

16
推荐指数
2
解决办法
2114
查看次数

sp_send_dbmail 存储过程随附件发送

我的任务是为我的一位客户发送一份小型月度报告。该报告以前在实例上手动运行,输出复制到电子表格并作为附件发送给客户。

我正在寻找一个更永久的解决方案,所以我打算使用 sp_send_dbmail存储过程来运行查询并将其作为附件发送。

一切正常,但消息的格式。最初我尝试将输出附加为带有 a 的 CSV 文件,@query_result_seperator = ','但结果无处不在!

当我正常运行报告时,输出在 SQL 中看起来不错。但是将其作为 CSV 发送或仅在消息正文中发送则不然。

我认为如果我将输出导出为 HTML 并作为附件/或 XML 发送它可能会更好,但我不知道如何执行此操作。

有没有人有什么建议?

提前致谢!

xml sql-server stored-procedures database-mail

15
推荐指数
2
解决办法
7万
查看次数

将 XML 数据存储在哪种数据类型中:VARCHAR(MAX) 或 XML

我正在使用 SQL Server 2008 为一组新资源定义架构...在这种情况下,每条记录(例如行)都需要存储 XML 片段。时; 虽然不经常;我需要查询 XML 以查找元素和属性值。如果留给我自己的设备,我会倾向于使用XML数据类型,尽管我一直认为这是有问题的。所以这让我想到了我的问题。

鉴于这种情况,在尝试决定将 XML 存储在XML列中还是varchar(MAX)列中时,我应该考虑哪些因素

如果有帮助……这里有一些额外的细节:

  • 尚未决定对这些片段(例如 XSD)使用模式
  • 碎片的大小从小到大不等
  • 所有 XML 都将是格式良好的
  • 在一天的过程中,将收集多达约 10,000 个片段,需要约 3 个月的在线查询支持
  • 对 XML 的查询将全天发生,但应该保持轻量级,很少有这种类型的并发查询

schema sql-server-2008 xml database-design datatypes

14
推荐指数
2
解决办法
1万
查看次数

如何尽可能快地分解此扩展事件 XML?

我在 SQL Server 2008 R2 中创建了一个扩展事件会话。会话运行,并在事件发生时收集事件,正如您所期望的那样。

如果我在事件相对较少的情况下切碎 xml,性能是可以接受的。当我有数千个事件时,需要永远分解 xml。

我知道我做错了什么,我只是没有足够的关于 XML 引擎内部的知识来理解什么。

这是我的扩展事件会话的定义:

IF EXISTS 
(
    SELECT 1 
    FROM sys.server_event_sessions dxs 
    WHERE dxs.name = 'queries'
)
BEGIN
    IF EXISTS (
        SELECT 1 
        FROM sys.dm_xe_sessions dxs 
        WHERE dxs.name = 'queries'
    )
    BEGIN
        ALTER EVENT SESSION queries ON SERVER STATE = STOP;
    END
    DROP EVENT SESSION queries ON SERVER;
END

CREATE EVENT SESSION queries ON SERVER 
ADD EVENT sqlserver.sql_statement_starting
(
    ACTION 
    (
        package0.collect_system_time
        --, package0.event_sequence
        , sqlserver.client_app_name
        , sqlserver.client_hostname
        --, sqlserver.database_name
        , …
Run Code Online (Sandbox Code Playgroud)

xml sql-server sql-server-2008-r2 extended-events

14
推荐指数
1
解决办法
1567
查看次数

使用 XPath/XQuery 连接同一 XML 元素的所有值

我有一个这样的 XML 值:

<R>
  <I>A</I>
  <I>B</I>
  <I>C</I>
  ...
</R>
Run Code Online (Sandbox Code Playgroud)

我想连接所有的I值并返回它们作为单个字符串:ABC...

现在我知道我可以分解 XML,将结果聚合回无节点 XML,然后应用于.values('text()[1]', ...)结果:

SELECT
  (
    SELECT
      n.n.value('text()[1]', 'varchar(50)') AS [text()]
    FROM
      @MyXml.nodes('/R/I') AS n (n)
    FOR XML
      PATH (''),
      TYPE
  ).value('text()[1]', 'varchar(50)')
;
Run Code Online (Sandbox Code Playgroud)

但是,我想仅使用 XPath/XQuery 方法来完成所有这些工作,如下所示:

SELECT @MyXml. ? ( ? );
Run Code Online (Sandbox Code Playgroud)

有这样的方法吗?

我在这个方向寻找解决方案的原因是因为我的实际 XML 也包含其他元素,例如:

SELECT
  (
    SELECT
      n.n.value('text()[1]', 'varchar(50)') AS [text()]
    FROM
      @MyXml.nodes('/R/I') AS n (n)
    FOR XML
      PATH (''),
      TYPE
  ).value('text()[1]', 'varchar(50)')
;
Run Code Online (Sandbox Code Playgroud)

而且我希望能够将I值提取为单个字符串,并将J值提取为单个字符串,而不必为每个值使用笨拙的脚本。

xml sql-server xquery sql-server-2014

14
推荐指数
2
解决办法
4111
查看次数