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 秒。不是很科学,但似乎表现还可以。
目前,由于 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 秒。不是很科学,但似乎表现还可以。