在这里使用varbinary比使用varchar有什么优势?

23

前段时间我问了一个关于在SQL Server中进行层次结构/版本号排序的问题。 (如何使用SQL Server查询通用地对“版本号”列进行排序)。

提交的答案之一是 这个T-SQL编码挑战的链接,与该谜题非常类似

在SQL2000解决方案中,作者演示了两种变体,一种使用并返回varchar,另一种使用varbinary。作者解释了他是如何做到这一点,但没有解释为什么要这样做。

那么,我的问题实际上是什么,采用不同方法(例如为什么使用varbinary而不是varchar)的主要区别/优势(如果有的话)是什么?

我省略了代码的发布,因为它在上面的文章中最为优雅地总结了。


1
我认为预期的是varbinary数据在每个原始字符串部分上通常会比varchar数据消耗更少的字节(5),因此对于非常大量的组件或比较进行操作时,它应该更有效率。但我也猜想,对于大多数用户而言,在效率方面没有太多实际的差异。 - Damien_The_Unbeliever
@Damien:谢谢你。如果你选择回答,我很乐意给你点赞并接受你的回答!如果你愿意,我会事后这样做的。 - James Wiseman
1
我本以为这是因为结果将用于排序,二进制可能更有效,因为它不必担心排序规则。但不确定这在一般情况下是否正确,即使在一般情况下正确,也不知道与使用二进制“collate”子句对字符串进行排序相比如何。 - Martin Smith
2个回答

19

我认为预期的情况是,相对于varchar数据(每个原始字符串部分占用10或11个字节),varbinary数据通常会占用更少的字节(5个),因此,在需要处理大量组件或进行比较时,它应该更有效率。

但是,如果您想使用其中任何一种解决方案,我建议您都实施一下(它们非常简短),并针对您的真实数据(和查询模式)进行一些性能分析,以查看是否存在实际差异(我不会期望有太大差别)。

(Crafty Steal):正如Martin所指出的那样,二进制比较将更加高效,因为它不涉及处理排序规则的所有代码。 :-)


6
如果我们在不同的varchar列中使用不同的排序规则来存储字符串,并在一个SQL查询中使用多个这样的列,则该SQL查询可能会抛出错误“无效的混合排序规则”。(例如,如果我们想要比较两个不兼容的排序规则的字符串或尝试将不同排序规则的数据选择到一个组合列中)。
但是,如果我们在查询中指定“COLLATE”,那么这个问题可以得到解决。例如:
 WHERE 'A' COLLATE latin1_general_ci = 'A' COLLATE latin1_general_ci 

然而,这将使您失去任何索引。

为了防止“无效混合排序”错误,我们可以使用varbinary。

如果varchar列使用了多字节排序,则varbinary使用的空间较少。 (二进制字符串没有字符集和排序规则。 二进制字符串仅是一系列字节值)。

***顺便说一下,字符集是符号和编码的集合。 排序是对字符集中的字符进行比较的一组规则https://dev.mysql.com/doc/refman/5.7/en/charset-general.html

但是,如果您选择单字节字符集(例如latin1)而不是多字节字符集(例如utf8或ucs2),则varbinary和varchar的空间要求相同。

如果没有有效性检查,则VARBINARY优于VARCHAR。例如,如果默认字符集为UTF8,则此操作是非法的:

CREATE TABLE t9 (s1 VARCHAR(5));
INSERT INTO t9 VALUES (0xF4808283);

但是,这是合法的,因为字符集并不重要:
CREATE TABLE t10 (s1 VARBINARY(5));
INSERT INTO t10 VALUES (0xF4808283);

所以,VARCHAR使用“排序规则”比较字符,而VARBINARY使用字节进行比较。大多数排序规则都是“不区分大小写”的,因此大写字母和小写字母被视为相等。由于VARBINARY不使用任何排序规则,所以在VARBINARY的情况下,搜索操作始终区分大小写。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接