13

人们普遍认为,在 int 列上搜索表比在字符串列(比如 varchar)上搜索要快。

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

4

5 回答 5

20

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

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. 但是,我怀疑除非表很大,否则您不会注意到速度差异。该决定可能应该基于哪种设计最有意义(可能是标准化的)。

于 2012-09-14T20:02:52.113 回答
11

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

于 2012-09-14T20:01:08.020 回答
7

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

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

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

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

于 2012-09-14T20:05:15.677 回答
4

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

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

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

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

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

(1)制作2个数据库

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

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

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

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

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

于 2012-09-14T20:07:50.867 回答
1

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

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

于 2012-09-14T20:03:02.387 回答