【问题标题】:Performance of string comparison vs int join in SQLSQL 中字符串比较与 int 连接的性能
【发布时间】:2012-09-14 19:54:16
【问题描述】:

在 int 列上搜索表比在字符串列(比如 varchar)上搜索要快是公认的。

但是,如果我有一个带有 Color 列的 Shirt 表,那么使用该表上的主键作为 Shirt 表上的外键创建一个 Color 表会更高效吗?在搜索绿色衬衫时,连接是否会否定将 Shirt 颜色列中的值设为 int 而不是字符串值(如“Green”)的性能优势?

【问题讨论】:

  • 这是一个实际的性能问题吗?它看起来很像过早优化。听我说:复杂的数据库并不好玩。 除非你有充分的理由,否则不要让你的数据库变得更复杂。
  • @BrendanLong 这不是实际的性能问题,而是理论上的问题。至少在我的情况下是这样。但是,您的评论似乎与针对理论性能问题给出的所有标准化答案背道而驰。
  • 规范化是这样做的正当理由,但你的问题是关于性能的,所以这就是我的评论。理论性能不值得担心。

标签: sql performance join foreign-keys varchar


【解决方案1】:

除了性能之外,创建单独的颜色表可以让您的设计更加规范化。因此,在未来的某一天,当有人决定现在应该将“深蓝色”称为“海军蓝”时,您更新 Color 表中的 1 行,而不是更新 Shirt 表中的许多行。

【讨论】:

  • 这很合乎逻辑。
【解决方案2】:

如果我理解正确,您是在问这两个查询中哪一个会更快:

SELECT * FROM shirt where color = 'Green'

SELECT shirt.* FROM shirt s INNER JOIN colors c 
       ON s.colorid = c.colorid 
       WHERE c.color = 'Green'

这在一定程度上取决于数据库(嗯......可能很大程度上取决于它是否正确优化,如果不是全部的话,大多数都应该),但是颜色表中的查找应该可以忽略不计,然后剩余的执行可以使用整数查找值,应该更快。大部分处理最终将相当于SELECT * from shirt WHERE colorid=N。但是,我怀疑除非表很大,否则您不会注意到速度上的差异。该决定可能应该基于哪种设计最有意义(可能是标准化的)。

【讨论】:

  • +1 因为虽然它没有完全回答我的问题,但它在澄清问题方面做得很好。
【解决方案3】:

与正在执行的其他操作相比,这两种方法之间不太可能存在很大的性能差异。如果您只有少数几种颜色(最多几百种),则颜色表适合大多数数据库中的单个页面。颜色上的索引将使查找速度非常快,并且不会引起任何 I/O 活动(在第一次运行加载页面之后)。

字符串比较依赖于数据库,但它确实涉及一个函数并从页面读取数据。所以,它不是免费的。当然,不同的数据库对于字符串函数可能具有不同的性能特征。

它应该存储在哪里应该是您的应用程序的一个功能。假设您有一个将颜色呈现给用户的应用程序。有一天,您可能想用西班牙语、斯瓦希里语或中文显示颜色的名称。如果是这样,拥有一个单独的表会使这种国际化变得更加容易。更简单地说,您可能希望阻止输入“Grene”,如果是这样,拥有这样的表格会使选择列表更容易。

另一方面,如果性能是您唯一关心的问题,那并没有什么不同。在其他情况下,查找表实际上可能比非规范化表。当字符串很长时会发生这种情况,从而增加了更大表中每条记录的长度。更大的表意味着更多的页面,这需要更长的时间才能加载到内存中。

【讨论】:

    【解决方案4】:

    DBMS 有机会在值数量有限的情况下优化指标。我不知道如何告诉 SQL 这样做。它可能会弄清楚。

    如果报告性能是一个严重问题,则启动数据仓库..

    正如 Joe 所指出的,您希望数据库尽可能标准化。如果您有一个单独的报告功能,可能会导致性能问题,您应该运行一个定期转换(或设置规则以实时构建)第二个只读模式。第一个是OLTP,第二个是OLAP(“数据仓库”);如果您要认真对待您的数据,这些都是重要的概念。

    如果知道它足够重要,请测试它。

    如果没有人给你答案,最好的办法就是自己测试。

    (1) 制作 2 个数据库

    (2) 每个都测试你的 2 个表

    (3) 在数据库中,只加入字符串“color”,并将其用于 FK;另一个通过 int ('colorID') 加入

    用 200 万个虚拟行填充每个。对每个查询运行多个查询,计时第一次运行和平均运行时间。

    在您的开发机器上使用一个实例将网络排除在外。

    您还应该在每种类型的测试之前启动和停止实例;东西会故意留在内存中,以便 SQL 可以更快地交付它,但很可能,这会使您的测试结果与实际操作产生偏差 - 它可能不再在内存中或缓存中。

    【讨论】:

      【解决方案5】:

      这真的取决于查询优化器。您的颜色表将非常小,因此可能基于数据库统计信息和查询计划,它可能会完全加载到内存中,因此您不仅最终否定了连接的性能成本,它实际上可能更快。这显然取决于您使用的 dbms,但有几个 dbms 可以提示以特殊方式处理表。

      Color 表的另一个 +1 是如果您需要更改颜色名称,您只需更新 1 次,而不是每次出现都更改字符串值。

      【讨论】:

        猜你喜欢
        • 2020-06-26
        • 2011-03-18
        • 2021-10-13
        • 1970-01-01
        • 1970-01-01
        • 2018-05-11
        • 2014-01-24
        • 2010-10-25
        • 1970-01-01
        相关资源
        最近更新 更多