EndsWith SQL 查询 VARBINARY(MAX) FILESTREAM 列

EndsWith SQL query for VARBINARY(MAX) FILESTREAM columns

目前,由于 WHERE 子句中的条件,我有两个 SQL 查询建议在同一 VARBINARY 列上多次调用 DATALENGTH

在同一个查询中对 DATALENGTH 的这些多次调用是否会影响性能,或者 DATALENGTH 计算的结果可以是 Microsoft optimized/cached 服务器 SQL ?

目标是为 VARBINARY(MAX) FILESTREAM 列构建 EndsWith SQL 查询。

在我的例子中,我无法向 table 添加任何额外的索引或列,但是 我想了解可能的替代方案是什么。

-- 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 --

到目前为止我尝试了什么...

Proposal A - REVERSE BinKey and BinData, 然后使用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

有没有更好的算法?对于较大的斑点,它的表现如何?

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

-- 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

其中returns以下:

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

我添加了 10,000 条记录,每条记录的大小约为 1kb。查询所有这些花费了 0.020 秒。我还尝试在 10,000 条 1kb 记录之后添加 10 条 1MB 大小的记录。 运行 查询用了 .037 秒。当 1kb 或 1MB 的记录以 0x1125 结尾时,它会稍微增加执行时间,因为 SSMS 必须接收并格式化输出 window 中的记录。以 0x1125 结尾的 50 个 1kb 行花费了 .057 秒到 运行。当 1MB 行之一以 0x1125 结尾时,运行 花费了 .110 秒。不是很科学,但似乎表现还可以。