INT和VARCHAR在搜索中的区别

11

以下哪个查询会更快且更优化(以及为什么):

  1. SELECT * FROM items WHERE w = 320 AND h = 200 (w和h均为INT类型)

  2. SELECT * FROM items WHERE dimensions = '320x200'(dimensions是VARCHAR类型)

第二个查询更快和更优化,因为它只需要一个字符串匹配,而第一个查询需要两个整数比较。此外,第二个查询还可以使用索引来提高性能。

2
我要指出的是,这两列还可能包含更准确的数据,这对于良好的数据库设计至关重要。 - HLGEM
如果你将高度和宽度作为两个单独的varchar进行比较,那么这将是一个更好的比较。现在大家都在回答“如果这样,如果那样”的问题... - puck
6个回答

6
这里有一些实际的测量数据。(使用SQLite;稍后可以尝试使用MySQL。)
数据 = 所有1,000,000种 w,h ∈ {1…1000} 的组合,随机排序。
创建条目表。 CREATE TABLE items (id INTEGER PRIMARY KEY, w INTEGER, h INTEGER) 平均执行 SELECT * FROM items WHERE w = 320 and h = 200 的时间(20次运行)是5.39±0.29微秒。
创建条目表。 CREATE TABLE items (id INTEGER PRIMARY KEY, dimensions TEXT) 执行 SELECT * FROM items WHERE dimensions = '320x200' 的平均时间为5.69±0.23微秒。
就效率而言,没有显著差异。
但在可用性方面有很大的区别。例如,如果你想计算矩形的面积和周长,双列法很容易: SELECT w * h, 2 * (w + h) FROM items 试着写出另一种方法的相应查询。

2
可能唯一知道的方法是运行它。如果使用的所有列都有索引,那么基本上没有什么区别。如果INT是4个字节,它的大小几乎与字符串相同。
唯一的问题在于VARCHAR的存储方式。如果您使用常量字符串大小,则可能比VARCHAR更快,但主要是因为您的select *需要获取它。
使用INT的巨大优势在于您可以进行更复杂的过滤。这本身就应该是偏爱它的原因。如果您需要范围,或者只是宽度,或者想要在过滤中对宽度进行数学运算怎么办?基于列的约束或聚合呢?
此外,在将值传递到编程语言中时,您无需在使用之前解析它们(这需要时间)。
编辑:其他答案提到了字符串比较。如果有索引,将不会执行许多字符串比较。并且可以实现非常快速的比较算法,无需逐字节循环。要确定mysql的详细信息,您必须了解其工作原理。

2

直观来说,如果你没有在这些列上创建INDEX索引,整数比较似乎更快。

在整数比较中,您可以使用逻辑运算符直接比较32位值的相等性。

另一方面,字符串是字符数组,难以进行比较。需要逐个字符进行比较。

然而,另一个问题是,在第二个查询中,您有1个字段要比较,在第一个查询中,您有2个字段要比较。如果您有100万条记录,并且没有在列上创建索引,那么在最坏情况下(不幸的是,最后的结果就是您正在寻找的内容或者根本找不到),这意味着您可能会进行100万次字符串比较。

另一方面,如果您有100万条记录,并且它们全部都是w=320,那么您将对h进行比较。这意味着需要进行200万次比较。但是,如果您在这些字段上创建了索引,则它们几乎相同,因为VARCHAR将被哈希(需要O(1)常数时间),并将使用INT比较进行比较,需要O(logn)时间。

结论:这取决于具体情况。建议在可搜索的列上使用索引并使用整数进行比较。


1
第二个查询,由于匹配精确字符串的机会较小(这意味着记录集较小但基数更大)
第一个查询,匹配第一列的机会更高,可能匹配更多行(基数较小)
当然,假设两种情况都定义了索引。

第一个查询首先只会找到第一个字段匹配的行,然后在该记录集中搜索第二个字段的匹配项,这样是否可以通过搜索较小的数据集来抵消呢? - JNK
@JNK - 解释了较少的记录但更大的基数,比较两列只有更多记录且每列基数较小。 - ajreal

0

首选第一个,因为比较数值数据更快。


0

这取决于数据和可用的索引。但是,VARCHAR版本更快是完全可能的,因为搜索单个索引比两个索引更快。如果值的组合提供了唯一(或“大多数”唯一)的结果,而每个单独的H/W值都有多个条目,则可以使用单个索引将其缩小到更小的集合。

另一方面,如果您在两个整数列上有一个多列索引,那么这可能是最有效的。


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