【发布时间】:2018-04-19 08:53:47
【问题描述】:
由于WHERE 子句中的条件,目前我有两个 SQL 查询提议,它们在同一 VARBINARY 列上多次调用 DATALENGTH。
在同一查询中对DATALENGTH 的多次调用是否会影响性能,或者DATALENGTH 计算的结果是否可以由Microsoft SQL Server 优化/缓存?
目标是为VARBINARY(MAX) FILESTREAM 列构建一个EndsWith SQL 查询。
在我的情况下,我不能向表中添加任何额外的索引或列,但是 我想了解可能的替代方案。
-- 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 BinKey 和 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);
Proposal 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,它的性能如何?
【问题讨论】:
-
SQL Server 确实知道
DATALENGTH是deterministic。 -
@Damien_The_Unbeliever:是的,确定性的......但这是否意味着使用同一列作为 WHERE CLAUSE 中的参数多次调用 DATALENGTH 不会导致额外的计算?
-
这意味着它有机会将它的调用次数减少到最低限度。您需要检查特定执行计划以供您的查询确定。
-
在内部,
VAR值与它们的长度一起存储,所以我看不出DATALENGTH会是什么,除了恒定的时间,这使得它在很大程度上无关紧要你多久采取的长度相同的列/变量。但一如既往,测量为王。构建大块不是火箭科学。 (对于FILESTREAM,可能会有所不同,但我非常怀疑——文件系统不会白白记录文件长度!) -
这个问题更适合dba.stackexchange.com
标签: sql sql-server varbinary sqlfilestream datalength