【问题标题】:SQL SELECT speed int vs varcharSQL SELECT 速度 int 与 varchar
【发布时间】:2011-01-21 18:15:00
【问题描述】:

我正在创建一个表格,这让我感到好奇。

如果我存储,比如具有品牌(fx BMW、Audi 等)的汽车,如果我将品牌存储为 int 或 varchar,它会对查询速度产生任何影响。

原来如此

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

比快/慢

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

还是速度差不多?

【问题讨论】:

    标签: sql performance postgresql select


    【解决方案1】:

    Int 比较比 varchar 比较快,因为 int 占用的空间比 varchar 少得多。

    这对于非索引访问和索引访问都适用。最快的方法是索引 int 列。


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

    【讨论】:

    • 您指的是第 7.4 页。在现代版本中,如果您有
    • @Magnus - 感谢您的提醒。当我看到您有足够的代表点时,请随时编辑我的答案。
    • “不是字符串占用更多空间”... 超过最小大小的字符串占用的空间甚至比高精度数字还要多,因为数字(单数)具有固定单位,字符串总是聚合类型。 64 位数字 8 个字节 字符串中每个字符 4 个字节,包括长度字节或结构;或另一个用于令人难以置信的幼稚实现的终止符......
    • “Int 比较比 varchar 比较快,因为 int 占用的空间比 varchars 少得多”——一般来说并非如此。根据您使用的 DBMS 以及您要插入的确切数据类型和字符串,您的(例如)8 字节整数可能比保存一些平均长度为 3-4 个字符的文本 ID 的 ascii varchars 更长。因此,这个答案 - 不精确并且缺乏任何具体的背景或实验结果 - 并没有真正回答这个问题。每个人都知道 varchars 允许比 int 占用更多的空间,但它们不是必须的。
    • 您能否在此处支持您对索引访问的声明?我在网上看到的每个基准都表明 varchar 与 int 对于索引访问是相同的,并且您没有发布任何数据或参考来支持您的声明。 stackoverflow.com/a/48583244/834393
    【解决方案2】:

    一些粗略的基准:

    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 字符文本在速度上没有区别。

    【讨论】:

    • 非常有趣。为什么差别可以忽略不计?
    • @ChibuezeOpata 在可以比较数据之前,必须将其加载到比 RAM 更靠近 CPU 的缓存中。总体比较时间可能完全由该加载决定。 i7 L1 & L2 caches are 64 bytes in size,您可以一次从 RAM 中加载 64 个连续字节。因此,只要您的数据小于 32 字节(将 32 字节相互比较),唯一的区别就是 CPU 需要比较的周期,这可以忽略不计。只是猜测,实际答案可能非常复杂。
    【解决方案3】:

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

    使用 int 还有另一个原因,那就是规范化数据库。与其将文本“Mercedes-Benz”存储在表中数千次,不如存储它的 id 并将品牌名称存储在单独的表中一次。

    【讨论】:

    • 你能解释更多吗?你的意思是代替Mercedes-Benz 存储数千次id 1。例如表car_brands、列BrandsId。行Mercedes-Benz1。在主表列Brands 和值1。而当SELECT 时,首先从表car_brands 中获取Id,然后是SELECT Something FROM main_table WHERE Brands = (SELECT Id FROM car_brands WHERE Brands = Mercedes-Benz)。还是其他方法?
    • @user2118559:是的,这就是您存储它的方式。要获取数据,您通常会使用连接而不是子查询:select something from main_table c inner join car_brands b on b.Id = c.Brands where b.Brands = 'Mercedes-Benz'
    • 为什么投反对票?如果你不解释你认为错的地方是什么,就无法改进答案。
    【解决方案4】:

    分解字符串比较与非浮点数的实际性能,在这种情况下,任何大小的无符号和有符号都无关紧要。尺寸实际上是性能的真正差异。无论是 1byte+(最多 126bytes)还是 1、2、4 或 8 字节的比较……显然非浮点数比字符串和浮点数小,因此在汇编中对 CPU 更友好。

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

    现在,快多少?还取决于数据量。如果您只是将 5 与 'audi' 进行比较——这就是您的数据库所拥有的,那么由此产生的差异是如此之小,您永远看不到它。根据 CPU、实现(客户端/服务器、Web/脚本等),您可能不会看到它,直到您在数据库服务器上进行数百次比较(甚至可能进行数千次比较才会明显)。

    • 使有关哈希比较的不正确争议无效。大多数散列算法本身都很慢,因此您不会从 CRC64 或更小的东西中受益。在超过 12 年的时间里,我为多县搜索引擎开发了搜索算法,并为征信机构开发了 7 年。您可以更快地保存数字的任何内容...例如电话号码、邮政编码,甚至货币 * 1000(存储)货币 div 1000(检索)都比 DECIMAL 更快进行比较。

    奥兹

    【讨论】:

      【解决方案5】:

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

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

      【讨论】:

      • 比如500万条“audi”的记录,索引不是只有一份“audi”字符串和500万个primary_key整数吗?大小差异真的会那么大吗,是vchar还是整数?
      • 你是对的 lulalala 但是对于将包含随机字符串的列,答案是足够公平的。
      【解决方案6】:

      一般来说 int 会更快。 varchar 越长越慢

      【讨论】:

        【解决方案7】:

        提示:如果字段 make 的可能值将从不(或很少)更改,您可以使用 ENUM 作为折衷方案。它结合了良好的速度和良好的可读性。

        【讨论】:

        • 有意思,ENUM 和 int 的速度会有什么区别?
        • PostgresSQL 有enum 数据类型吗?我虽然它是特定于 MySQL 的。
        • Postgres 有 ENUM,但我认为它的实现方式与 MySQL 不同。 postgresql.org/docs/current/static/datatype-enum.html
        • 性能方面,ENUM 在搜索字段中的性能应该与 int 差不多,但在目标列表中作为 varchar (因为它必须将整个字符串传输到客户端以获取匹配的行,而不是只是 int)
        • Here an interesting read 关于为什么不在 MySQL 中使用枚举(只是为了火上浇油:D)
        【解决方案8】:

        如果您在任一字段上打开索引,它会更快。至于你的问题,我认为intvarchar快。

        【讨论】:

          【解决方案9】:

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

          【讨论】:

            猜你喜欢
            • 2015-11-24
            • 2010-09-16
            • 2015-07-27
            • 2013-12-31
            • 2012-09-29
            • 2011-02-06
            • 1970-01-01
            • 2013-10-02
            • 1970-01-01
            相关资源
            最近更新 更多