SQL SELECT Speed Int与varchar


110

我正在创建表格,这让我感到奇怪。

如果我存储有品牌的汽车(例如宝马,奥迪等),如果将品牌存储为int或varchar会对查询速度产生任何影响。

也是

SELECT * FROM table WHERE make = 5 AND ...;

快/慢于

SELECT * FROM table WHERE make = 'audi' AND ...;

还是速度会大致相同?

Answers:


99

Int比较比varchar比较快,原因很简单,因为Int比varchars占用更少的空间。

对于未建立索引的访问和建立索引的访问都适用。最快的方法是建立索引的int列。


正如我看到的那样,您已经标记了问题postgreql,您可能会对不同日期类型的空间使用感兴趣:


13
您指的是第7.4页。在现代版本中,如果您<126个字节,则它们占用1个字节以上的长度。还要注意,字符串慢得多的原因通常是归类敏感的比较非常昂贵-并不是字符串占用了更多空间。但是,最终结果当然是相同的。
Magnus Hagander

@Magnus-感谢您的单挑。看到您的代表点足够多时,请随时编辑我的答案。
罗伯特·蒙提亚努

“不要让字符串占用更多空间” ...最小大小以上的字符串甚至比高精度数字占用更多空间,因为数字(单数)具有固定单位,所以字符串始终是聚合类型。字符串中每个字符4个字节的8位字节(64位数字),包括长度字节或结构;或另一个难以置信的天真实现的终结符……
MrMesees

@RobertMunteanu嘿罗伯特,对不起,我知道这是一篇老文章,但是我可以在下面进行检查...:为了查询整数,我必须将每个字符串列链接到另一个表(关系)。但是,这意味着每个查询需要更多的联接操作。我如何确定这种权衡是否值得?谢谢!
2017年

2
“因为int比varchars占用的空间少,这是一个简单的事实,即int比较比varchar比较快”- 通常这是不正确。根据所使用的DBMS以及要插入的确切数据类型和字符串,可能会发现,(例如)8字节的整数比包含一些平均长度为3-4个字符的文本ID的ascii varchars长。因此,这个答案-不精确且缺乏任何特定的上下文或实验结果-并未真正回答问题。每个人都知道varchars 可以比ints占用更多的空间,但是不必这样做。
Marcin Wojnarski

36

一些粗略的基准测试:

Postgres 9.x中有400万条记录

Table A = base table with some columns
Table B = Table A + extra column id of type bigint with random numbers
Table C = Table A + extra column id of type text with random 16-char ASCII strings

在8GB RAM,i7,SSD笔记本电脑上的结果:

Size on disk:                A=261MB        B=292MB        C=322MB
Non-indexed by id: select count(*), select by id: 450ms same on all tables
Insert* one row per TX:       B=9ms/record        C=9ms/record
Bulk insert* in single TX:    B=140usec/record    C=180usec/record
Indexed by id, select by id:  B=about 200us       C=about 200us

* inserts to the table already containing 4M records

因此,对于此设置来说,只要您的索引适合RAM,bigint与16个字符的文本在速度上就没有区别。


6
很有意思。差异为何可忽略不计?
Chibueze Opata

18

使用int而不是varchar会更快一些。对于速度而言,更重要的是在查询可用于查找记录的字段上具有索引。

使用int的另一个原因是对数据库进行规范化。与其将文本“ Mercedes-Benz”存储在表中数千次,不如存储其ID和将品牌名称存储在单独的表中一次。


你能解释更多吗?您是不是Mercedes-Benz要存储数千次id 1?例如表car_brands,列BrandsId。行Mercedes-Benz1。并在主表中列Brands和值1。当SELECT,然后在第一个拿到Idcar_brandsSELECT Something FROM main_table WHERE Brands = (SELECT Id FROM car_brands WHERE Brands = Mercedes-Benz)。还是其他方法?
Andris

3
@ user2118559:是的,这就是存储它的方式。要获取数据,通常将使用联接而不是子查询:select something from main_table c inner join car_brands b on b.Id = c.Brands where b.Brands = 'Mercedes-Benz'
Guffa

为什么要下票?如果您不解释自己认为是错的是什么,那将无法改善答案。
加法

8

细分为字符串比较和非浮点数的实际性能,在这种情况下,无符号和有符号的任何大小都没有关系。尺寸实际上是性能上的真正差异。与1、2、4或8字节比较相比,它是1字节+(最多126字节)...显然,非浮点型比字符串和浮点型小,因此在组装时对CPU更友好。

所有语言中的字符串到字符串比较都比CPU可以在1条指令中进行比较的速度慢。即使在32位CPU上比较8字节(64位),也仍然比VARCHAR(2)或更大的速度更快。*同样,查看生成的程序集(即使是手工),也需要更多的指令来比较一个字符到一个字符,而不是1到8字节的CPU数字。

现在,快多少?也取决于数据量。如果您只是将5与“ audi”进行比较-这就是您的数据库所拥有的全部,那么产生的差异是如此之小,您将永远看不到它。根据CPU,实现(客户端/服务器,Web /脚本等)的不同,您可能要等到您在数据库服务器上进行几百次比较(可能甚至只有几千次比较才能看到)时,才能看到它。

  • 消除有关哈希比较的错误争议。大多数哈希算法本身都很慢,因此您无法从CRC64和更小的内容中受益。在过去的12年中,我为多县搜索引擎开发了搜索算法,为征信局开发了7年。您可以更快地以数字形式保存的任何内容...例如,电话号码,邮政编码,甚至货币* 1000(存储),货币div 1000(检索)都比DECIMAL更快。

奥兹


6

是否建立索引,int快得多(varchar越长,它变得越慢)。

另一个原因:varchar字段上的索引将比int上的索引大得多。对于较大的表,可能意味着数百兆字节(和数千页)。由于仅读取索引需要大量磁盘读取,因此这会使性能变得更差。


3
例如,有5百万条“ audi”记录,索引是否仅包含“ audi”字符串的一个副本和5百万个primary_key整数?大小差异真的会那么大吗,是vchar还是integer?
lulalala

您是对的lulalala,但是对于将包含随机字符串的列,答案是足够的。
阿瓦斯·菲亚兹

4

通常int会更快。varchar越长,它变得越慢


3

提示:如果该字段的可能值化妆永远不会(或很少)改变,你可以使用ENUM作为妥协。它结合了良好的速度和良好的可读性。


1
有趣的是,ENUM和int之间的速度差如何?
googletorp 2010年

PostgresSQL是否具有enum数据类型?我虽然是MySQL特有的。
罗伯特·蒙蒂亚努

Postgres具有ENUM,但我认为它的实现方式与MySQL不太相同。postgresql.org/docs/current/static/datatype-enum.html
googletorp 2010年

2
在性能方面,ENUM的性能应与搜索字段中的int大致相同,但在目标列表中的性能应与varchar相同(因为它必须将整个字符串传输给匹配行的客户端,而不仅仅是int)
Magnus Hagander

1
在这里有趣地读了一个为什么不在MySQL中使用枚举(只是向火上加油:D)的有趣读物
Wilt

1

如果您打开两个字段中的任何一个的索引,它将更快。关于您的问题,我认为intvarchar


0

有点相对。是的,INT将更快,但问题是在您的情况下它是否值得注意。VARCHAR是一些小的单词还是更长的文本?表格中有多少行?如果只有几行,则很有可能将其完全缓冲在内存中(在经常请求时),在这种情况下,您不会注意到太大的差异。当然,还有索引,当表增长时,索引将变得更加重要。使用SSD的速度可能比具有优化查询的HD的速度快。优秀的磁盘控制器有时也会加快> 10x的查询速度。这可能为仅使用VARCHAR留下了空间,这使读取和写入查询变得更加容易(无需编写复杂的联接)并加快了开发速度。然而,纯粹主义者会不同意并且总是使一切正常化。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.