【问题标题】:MySQL / MariaDB / InnoDB: Moving variable width columns to a secondary tableMySQL / MariaDB / InnoDB:将可变宽度列移动到辅助表
【发布时间】:2020-10-01 14:47:31
【问题描述】:

我有一个包含数百万行的 MariaDB InnoDB 表,但其中包含仅由数字和时间戳组成的短的、固定宽度的行。 我们通常使用任何现有的列来搜索、过滤和排序行。

我们想添加一列来为每一行存储一个关联的“url”。理想情况下,每一行都有它的 url。 我们知道我们不会通过 url 列进行排序、搜索和过滤。 我们不介意将 URL 截断为前 255 个字节,因此我们将为其指定 VARCHAR 类型。 但是,该列的宽度当然是可变的。整条记录会变成可变宽度,很多情况下原始记录的宽度会加倍。

我们正在考虑使用不同的辅助表来存储 varchar。 我们可以在查询数据时加入它们,或者更有效地——可能——只获取我们正在显示的页面的 url。

这种方法是否可取? 是否有更好的替代方案也可以让我们保持性能?

更新:正如用户 Bill Karwin 在下面的一条评论中指出的那样,InnoDB 不像 MyISAM 那样从固定宽度中受益,所以这里真正的问题是关于行的大小,而不是关于固定宽度与可变宽度讨论。

【问题讨论】:

  • 使用辅助表很好 - 无论单个表是否真的存在“性能影响”。几百万仍然是零钱——使用性能测试和指标来确定额外的关注/努力是否合理。什么是“关键”选项?那些自然(哈哈)适合建立一对一的关系。
  • @user2864740 数百万个场景的问题在于它经常与其他也有数百万行的表连接。我不确定我明白你所说的“关键”选项是什么意思,但我为辅助表考虑的 PK 只是第一个表的 PK 的副本。这将是 PK 和 FK(我想非自动增量是允许作为 PK 的,对吧?)。
  • InnoDB 不关心固定宽度与可变宽度的行。 MyISAM 中固定宽度的行有一些优势,但 InnoDB 没有。
  • 归结为连接上使用的索引。虽然可能会有一些额外的磁盘利用率(“每个特定查询的数据存储效率较低”),但查询的性能复杂性决定了它可以减少多少读取。在大多数情况下,未经过滤的百万 x 百万叉积会非常糟糕 - 行大小主要影响“C”常数。可能值得探索using covering indices 而不是手动分离。
  • 在某些极端情况下,分离一些体积庞大且很少使用的列是有好处的。但是您必须拥有一个规模非常大或流量非常高的数据库,然后才值得额外的复杂性。它与固定宽度与可变宽度无关。

标签: mysql mariadb denormalization


【解决方案1】:

假设您可以控制 URL 的生成方式,您可能希望将其更改为固定长度状态。 Youtube 视频的 URI,例如 are always 11 characters long 和 base-64。这解决了可变长度问题并避免了连接表。

如果更改 URI 生成不是一种选择,您可以使用一些替代方法将其设为固定长度:

  1. 您可以使用特殊字符填充空白以强制数据库中的每个 url 为 255,并在返回之前将其删除。这不是一个干净的解决方案,但使 DQL 操作比加入更快。
  2. 您可以按照您的说明获取 url,但请注意,两个 http 请求可能比仅使用一个请求的任何其他选项更耗时。
  3. 您可以仅在用户需要时加入另一个表,而不是默认情况下。

考虑到可变长度可能不是一个大问题,这取决于您的需要。唯一的问题可能是您是 grossly oversizing fields,但似乎不是您的情况。

【讨论】:

  • 无论使用何种模型,都没有理由发出“两个 http 请求”。
猜你喜欢
  • 2015-10-12
  • 1970-01-01
  • 2011-05-18
  • 1970-01-01
  • 2019-08-13
  • 2015-08-25
  • 1970-01-01
  • 2020-06-10
  • 2017-07-16
相关资源
最近更新 更多