0

目前,由于子句中的条件,我有两个 SQL 查询提案多次调用DATALENGTH同一列。VARBINARYWHERE

同一查询中的这些多次调用是否会DATALENGTH影响性能,或者DATALENGTH计算结果是否可以由 Microsoft SQL Server 优化/缓存?

目标是为列构建EndsWithSQL 查询VARBINARY(MAX) FILESTREAM

就我而言,我无法向表中添加任何额外的索引或列,但是我想了解可能的替代方法。

-- Table with BinData
DECLARE @foo TABLE(BinData VARBINARY(MAX));
INSERT INTO @foo (BinData) VALUES
(0x00001125), (0x00112500), (0x11250000),
(0x00000011), (0x00001100), (0x00110000), (0x11000000),
(0x112500001125);

-- BinKey
DECLARE @BinKey VARBINARY(MAX) = 0x1125;

-- Search for [BinData] ending with @BinKey --

到目前为止我尝试过的...

建议A - REVERSE BinKeyBinData,然后使用CHARINDEX

SELECT * FROM @foo WHERE
    DATALENGTH(BinData) >= DATALENGTH(@BinKey) AND
    CHARINDEX
    (
        CONVERT(VARCHAR(MAX), @BinKey),
        CONVERT(VARCHAR(MAX), BinData)
    ) = 1 + DATALENGTH(BinData) - DATALENGTH(@BinKey);

建议 B - 剪切BinData的结尾部分并将其与BinKey进行比较。

SELECT * FROM @foo WHERE
    DATALENGTH(BinData) >= DATALENGTH(@BinKey) AND
    SUBSTRING(
        BinData,
        1 + DATALENGTH(BinData) - DATALENGTH(@BinKey),
        DATALENGTH(@BinKey)
    ) = @BinKey;

James L. 的建议- 只需使用该RIGHT功能。

SELECT * FROM @foo WHERE
    RIGHT(BinData, DATALENGTH(@BinKey)) = @BinKey;

上面列出的查询的结果必须是:

0x00001125
0x112500001125

有没有更好的算法呢?对于较大的 blob,它的性能如何?

4

1 回答 1

0

我不确定如何分析这将如何执行,但这可以满足您的要求:

-- Table with BinData
DECLARE @foo TABLE(BinData VARBINARY(MAX));
INSERT INTO @foo (BinData) VALUES
(0x00001125), (0x00112500), (0x11250000),
(0x00000011), (0x00001100), (0x00110000), (0x11000000),
(0x112500001125);

-- BinKey
DECLARE @BinKey VARBINARY(MAX) = 0x1125;

-- Search for [BinData] ending with @BinKey --
select *
from   @foo
where  right(BinData, datalength(@BinKey)) = @BinKey

它返回以下内容:

BinData
----------------
0x00001125
0x112500001125

我添加了 10,000 条记录,每条大约 1kb 大小。查询所有这些需要 0.020 秒。我还尝试在 10,000 条 1kb 记录之后添加 10 条 1MB 大小的记录。运行查询花费了 0.037 秒。当 1kb 或 1MB 的记录以 0x1125 结尾时,会增加一点执行时间,因为 SSMS 必须在输出窗口中接收并格式化记录。以 0x1125 结尾的 50 个 1kb 行需要 0.057 秒才能运行。当 1MB 行之一以 0x1125 结束时,运行需要 0.110 秒。这不是很科学,但它似乎表现得很好。

于 2018-04-19T09:10:23.697 回答