1

我可以在表中添加什么索引:

CREATE TABLE [WData](
    [Account] [varchar](50) NOT NULL,
    [Table] [varchar](50) NOT NULL,
    [BatchID] [datetime2](7) NOT NULL,
    [XmlRow] [xml] NULL
) ON [PRIMARY]

以便后续存储过程运行得更快?现在速度很慢。

create PROCEDURE [Update_WData]
    @Account VARCHAR(50),
    @Table VARCHAR(50),
    @BatchID DATETIME2,
    @XmlRows xml 
AS
BEGIN
    SET NOCOUNT ON;

    DECLARE @input TABLE (
        [XmlRow] xml NULL
    );
    INSERT INTO @input (XmlRow)
    SELECT 
        c1.query('.')
    FROM @XmlRows.nodes('/Block/NewRow') AS t(c1);

    DECLARE @output TABLE ([ACTION] NVARCHAR(50) );

    MERGE WData AS t
    USING @input AS s 
    ON (t.Account = @Account AND t.[Table]=@Table AND CONVERT(VARCHAR(max),t.XmlRow)=CONVERT(VARCHAR(max),s.XmlRow))

    WHEN NOT MATCHED BY TARGET 
        THEN INSERT (Account,[Table],BatchID, [XmlRow]) 
        VALUES (@Account, @Table, @BatchID, s.XmlRow )
    WHEN MATCHED AND t.BatchID <> @BatchID
        THEN UPDATE SET t.BatchID = @BatchID
    OUTPUT 
        $ACTION
    INTO @output;
    SELECT [Action], COUNT(*) AS [Count]
    FROM @Output
    GROUP BY [Action]
END
4

1 回答 1

5

您还没有告诉我们您的集群键的选择性,但我认为有不止几行具有重复值,因为您有性能问题。

用于匹配行 from @inputto的连接WData将是嵌套循环连接,并WData在连接的内侧搜索聚集索引。来自的估计行数@input为 1,因此 SQL Server 认为它需要WData一次执行范围查找操作,以找到比较 XML 列的内容所需的所有行。

假设您有 10000 行用于 和 的唯一组合,Account并且[Table]您的 XML 包含 6NewRow个节点,这些节点在@Input.

在此处输入图像描述

聚集索引查找执行 6 次,每次返回 10000 行,然后比较连接中的 XML 列,60000 次。

您可以做的是添加一个计算的持久列,它是 XML 列的哈希。

CREATE TABLE [WData](
    [Account] [varchar](50) NOT NULL,
    [Table] [varchar](50) NOT NULL,
    [BatchID] [datetime2](7) NOT NULL,
    [XmlRow] [xml] NULL,
    H AS CAST(HASHBYTES('SHA2_512', CAST([XmlRow] AS VARBINARY(MAX))) AS BINARY(64)) PERSISTED
) ON [PRIMARY]

并将计算列添加到@Input.

DECLARE @input TABLE (
    [XmlRow] XML NULL,
    H AS CAST(HASHBYTES('SHA2_512', CAST([XmlRow] AS VARBINARY(MAX))) AS BINARY(64)) PERSISTED
);

H并在语句的ON子句中使用列MERGE

ON (
    t.Account = @Account AND 
    t.[Table]=@Table AND 
    t.H = s.H AND 
    CONVERT(VARCHAR(max),t.XmlRow)=CONVERT(VARCHAR(max),s.XmlRow)
   )

生成的散列不太可能发生任何冲突(不同 XML 值的值相同),但散列仅使用前 8000 个字节生成,因此您应该保留 XML 列的原始比较。

修改后,您将获得此查询计划。

在此处输入图像描述

读取次数是相同的,因为聚集索引查找仍然执行 6 次检查 10000 行。在搜索中对散列的检查作为残差谓词进行,使运算符在这种情况下根本不返回任何行,因此不会对 XML 列进行比较。

如果您不介意将集群密钥扩展为 64 字节,您还可以添加H密钥并大幅降低读取次数。在我的测试中,它从 1261 下降到 62。

CREATE CLUSTERED INDEX IX_WData ON WData(Account, [Table], H)
于 2013-09-07T21:08:19.540 回答