【问题标题】:SQL performance for string field vs multiple int/varchar fields字符串字段与多个 int/varchar 字段的 SQL 性能
【发布时间】:2021-10-04 13:29:04
【问题描述】:

我正在尝试正确设计数据库,但我不确定我应该选择 2 个选项中的哪一个。将有大约 20 个布尔值用于过滤(为简单起见,示例中有 4 个)。

  • 道具1
  • 道具2
  • 道具3
  • 道具4

选项 1)

每个道具的 int(1) 或 varchar(1) 字段。查询的过滤器部分可能像

WHERE prop1=1 AND prop3=1 AND prop4=1

选项 2)

使用带有代表道具的字符的单个文本字段

  • a:prop1
  • b: 道具2
  • c: 道具3
  • d: prop4

那么类似于选项 1 的查询的过滤部分会像

WHERE props LIKE '%a%' AND props LIKE '%c%' AND props LIKE '%d%'

或者如果字符已排序:

WHERE props LIKE '%a%' AND props LIKE '%cd%'

我的想法是选项 2 更容易添加新的道具,所以我喜欢这个选项,但是 LIKE 比较器的性能会比相等比较器差吗?与多个 int(1) 或 varchar(1) 相比,使用单个文本有什么不同吗?还有其他我没有想到的好处或缺点吗?

【问题讨论】:

  • 字符串字段肯定会变慢。在现代 MySQL 版本上,您可以使用 JSON 字段,它可能会比字符串字段执行得更好,但可能仍然比单个字段慢。
  • 别再考虑性能了。
  • 如果您需要过滤的行只有几百 - 几千,那么不要太担心,选择最容易处理的;如果您需要它来扩展并且将查询数百万行,那么高效的存储和使用整数或小整数值将会得到回报。

标签: mysql database-design database-performance


【解决方案1】:

主要问题是您是否可以比扫描整个表运行得更快。除非可以使用 Index(es) 单独处理少量布尔值,否则答案是“否”。

WHERE bools LIKE '%a%c%d%' 是一个巧妙的技巧,可以将任意数量的标志组合在一起。但是,它需要查看每一行,而LIKE 略显重量级。

INT(1) 占用 4 个字节加上开销。 TINYINT 是你要钓的;它需要 1 个字节,加上开销。

具有最多 64 个布尔值的 SET 是另一种技术。编码有点笨拙,但还是比较高效的

INT UNSIGNED(最多 32 个)或 BIGINT UNSIGNED(最多 64 个)标志的实现方式与 SET 类似,并且最多占用 8 个字节。但是编码相当笨拙。让我们在最低有效位中从 0 开始对位进行编号。

WHERE (bools & ( (1 << 0) | (1 << 2) | (1 << 3) ) ) = 
               ( (1 << 0) | (1 << 2) | (1 << 3) )

将检查位 0、2 和 3 是否都已设置。 (这就像您对 a、c、d 的测试。)这种方法可以进行各种 AND 和 OR。 (您可以预先计算这些位值——在本例中为 13。或者使用位字面量:0b1101。)

SET 或 INT 中的位的好处是每行内的“速度”。尽管如此,所有行都必须经过测试。

因此,我建议对您的布尔值等进行分类,并确定需要索引的内容以及可以将哪些内容放入此组合列或非布尔值的组合 JSON 列中。

【讨论】:

  • 谢谢,SET 正是我在用例中所需要的,但我什至不知道它的存在!
  • @KMK - 也​​读到它的朋友FIND_IN_SET()
【解决方案2】:

从性能的角度来看,这两个选项都有缺点:

  1. 几乎不可能为 20 列建立正确的索引,无论它们的数据类型如何,因为查询可能会因设置条件 prop1、prop1 + prop2、prop2 + prop3、prop2 + prop4 等而有所不同。所以你需要很多综合指数。此外,基于布尔值的索引通常因为基数低而表现不佳(值只能是 0 或 1,请参阅here for example)。

  2. 另一方面,带有前导 % 的 LIKE 语句也是一个性能问题。关闭 % 可以工作,但前导 % 被确定为慢。

我在这里看到你想为你的记录分配一组属性,每条记录可以有 0..n 分配propX,你想有效地过滤它。就像一个用户可以分配 0,1,2,...n 个角色一样。在关系数据库中,它被归类为经典的多对多关系。如果您使用可能的props 设置一个表,并使用连接表将它们连接到您的记录,例如detailed here,您可以只使用有限数量的索引进行良好的查询。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2013-12-31
    • 2010-10-05
    • 2016-11-05
    • 1970-01-01
    • 1970-01-01
    • 2011-04-24
    • 1970-01-01
    相关资源
    最近更新 更多