【问题标题】:SQL Server 2008 - why is performance WORSE with xml index?SQL Server 2008 - 为什么 xml 索引的性能更差?
【发布时间】:2010-11-09 00:27:25
【问题描述】:

这太疯狂了,但是在我将主 XML 索引添加到我的 xml 字段后,查询性能下降了大约 50%。

这就是我正在做的事情。

  • 我有一个表,其中包含一个 XML 字段 ActivityStepLog(包含 LogData、XML)

  • 我通过运行以下命令生成要插入此表的示例数据

    插入到 dbo.ActivityStepLog (
    日志GUID
    ,LogContextID
    ,LogTypeID
    ,LogSourceName
    ,日志内容
    ,日志日期
    ,创建日期
    ,创建者
    )
    选择
    LogGUID = newid()
    ,LogContextID = newid()
    ,LogTypeID = 2
    ,LogSourceName = '测试测试测试'
    ,LogContent = (SELECT top 1 * FROM ##SampleData SampleData1 where DecisionLogID = SampleData.DecisionLogID FOR XML AUTO, ELEMENTS, ROOT('BusinessRule') )
    ,LogDate = current_timestamp
    ,CreateDate = current_timestamp
    ,CreatedBy = '测试创建者'
    来自##SampleData SampleData

SampleData 有 100,000 行,我循环运行 5 次,最终得到 500,000 行。

  • LogContent 字段最终将包含如下数据:

    -2147483643 0569281A-D1A3-49E3-9E68-BCAC62E2C1C3 1016 2 0 -2147483495 1 2009-05-18T11:47:00 没有任何

(抱歉,不确定这是否会正确格式化 - 它基本上只是一组简短的元素)。

然后我只运行一个非常简单的 sql -

SELECT *
FROM ActivityStepLog
WHERE LogContent.value('(/BusinessRuleDecisionLog/SampleData1/DecisionLogID)[1]', 'int') = -2147483535

在 LogContent 上创建主 xml 索引之前需要 8 秒,之后大约需要 12 秒。我已经清理了缓存等(DROPCLEANBUFFERS 和 FREEPROCCACHE),它似乎不会影响比例,尽管它确实会影响整体时间。

这是我的统计数据:

带有 xml 索引 表'xml_index_nodes_325576198_256000'。扫描计数 1000000,逻辑读取 3517272,物理读取 0,预读读取 0,lob 逻辑读取 0,lob 物理读取 0,lob 预读读取 0。 表“ActivityStepLog”。扫描计数 1,逻辑读取 71694,物理读取 0,预读读取 0,lob 逻辑读取 0,lob 物理读取 0,lob 预读读取 0。

带有 OUT xml 索引

(受影响的 5 行) 表“ActivityStepLog”。扫描计数 1,逻辑读取 71694,物理读取 0,预读读取 0,lob 逻辑读取 0,lob 物理读取 0,lob 预读读取 0。

因此,没有 xml 索引的逻辑读取要少得多。我尝试添加所有可用的二级索引,但与拥有主 xml 索引相比并没有提高性能。

我将对此进行更多研究,但我非常感谢任何指针或 cmets。

谢谢, 西尔维娅

【问题讨论】:

  • 因为除了主索引之外,您还需要一个二级索引 - 用于路径 IIRC
  • 感谢您的评论,但正如我在帖子中提到的,我确实添加了所有可用的二级 xml 索引,但没有看到任何性能提升。

标签: xml sql-server-2008


【解决方案1】:

从对此进行更多研究 - 似乎对于 UNTYPED xml 字段,至少在我的测试用例中,xml 索引会降低性能。这对于键入的 xml 似乎有所不同,尽管我没有深入研究它。

DID 极大地提高了性能的一件事(感谢 wBob 在 msdn sql xml 论坛上的想法!)是在 xml 字段上创建全文索引。那时我得到了亚秒级的表现。为了准确,我还包括了一个 xml 过滤器。

SELECT *
FROM dbo.ActivityStepLog
WHERE 
   CONTAINS (LogContent, '-2147483535')
   and LogContent.value('(/BusinessRuleDecisionLog/SampleData1/DecisionLogID)[1]', 'int') = -2147483535

我还需要研究这是否适合我所有的过滤需求,但到目前为止看起来不错。

西尔维娅

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-03-31
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-10-03
    • 1970-01-01
    相关资源
    最近更新 更多