【问题标题】:DB Architecture: One table using WHERE vs multiple数据库架构:一张表使用 WHERE 与多张
【发布时间】:2020-06-07 03:25:43
【问题描述】:

我想知道一张有 600 万行的表(也就是一个巨大的数据库)和 10 万活跃用户之间有什么区别:

CREATE TABLE shoes (
id serial primary key,
color text,
is_left_one boolean,
stock int
);

还有 6 个索引,例如:

CREATE INDEX blue_left_shoes ON shoes(color,is_left_one) WHERE color=blue AND is_left_one=true;

对比:6 个表,100 万行:

CREATE TABLE blue_left_shoes(
id serial primary key,
stock int
);

后一种似乎更有效,因为用户不必询问条件,因为表是条件,但也许创建索引可以缓解这种情况?

此表用于查询左、右、“蓝色”、“绿色”或“红色”鞋子并检查剩余商品的数量,但这是一个简化的示例,但您可以考虑亚马逊(或任何数字销售平台)工具提示“库存仅剩 3 件”,用于工作负载和用例。将由用户(每天 10 万活跃用户)进行查询。

注意:这个问题主要针对 PostgreSQL,但与其他数据库的差异仍然相关且有趣。

【问题讨论】:

  • is_left_one acts as a boolean value. 然后,无论如何,让它成为boolean。此外,如果不定义表的工作负载和角色,您的问题将无处可去。如果你从不查询整张表,只查询6个分区中的一个,那么统一表的缺点多多。
  • 好的,我为 bool 进行了编辑,并将添加所需的详细信息
  • 如今 600 万行并不被认为是“巨大的”。我什至不会认为它“大”。

标签: sql database postgresql indexing low-latency


【解决方案1】:

在后一种情况下,您使用名为 blue_left_shoes 的表

  • 您的代码需要首先确定要查看哪个表(而不是在 where 子句中参数化一个值)
  • 随着排列和选项的增加,您需要增加表的数量,并增加应用中确定要使用哪个表的逻辑
  • 任何需要使用此数据库的东西(即报告工具或 API)现在都需要重新实施所有这些规则

您在高层强加逻辑以提高性能。

如果您要对表进行适当的分区和/或索引,您将获得相同的效果 - SQL 查询仅查看重要的记录。不同的是你不需要在更高层实现这个逻辑

只要您可以正确地建立索引,保持这是一个表几乎总是正确的做法。

分区

数据库分区是您选择一个或多个列来决定如何“拆分”您的表的地方。在您的情况下,您可以选择 (color, is_left_one)。

现在您的表以这种方式在逻辑上进行拆分和排序,当您搜索蓝色时,它会自动知道要查找的分区。它不会查找任何其他分区(这称为分区修剪)

请注意,这会根据搜索条件自动发生。您无需手动计算出要查看的特定表格。

  • 分区不需要任何额外的存储空间(除了必须保存的各种元数据)
  • 您不能将多个分区应用于一个表。只有一个

索引

创建索引还可以提高性能。但是索引占用空间并且会影响插入和更新性能(因为它们需要维护)。实际上,选择权衡几乎总是远远超过任何插入/更新否定

你应该总是在分区之前查看索引

非选择性索引

在您的特定情况下,还有一件额外的事情需要考虑:布尔字段不是“选择性”的。我不会详细介绍,但我只想说您不应该单独在此字段上创建索引,因为它不会被使用,因为它只会将您必须查看的记录数量减半。您需要在任何索引中包含一些其他字段(即颜色)以使其有用

【讨论】:

  • 排除应用层的时间?如果您的索引正确地放在整个表上?不包括缓存?这是一个复杂的话题。您必须针对您的具体情况衡量性能。我只是说在应用程序逻辑中实现表分区是一个坏主意。通常当有人想出它时,这是因为他们不太了解索引的工作原理
  • 好的,谢谢尼克,我阅读了更多关于分区的内容,它看起来很有趣,因为它基本上就是我在 6 个表示例中的 id。但它会将数据库的大小乘以 2 吗?对 DB 大小有什么影响?
  • 如果你有两张每张一百万行的表,或者一张有两百万行的分区表,它们的大小相同
  • 分区意味着您不必创建单独的表。您创建一个表并按某些内容对其进行分区,当您对其进行查询并将某些内容放入与分区匹配的where 子句中时,它会自动知道要查看表的哪一部分而不查看其他部分。这与直接索引非常相似
  • 如果您担心数据库中可能存在性能问题,请先了解索引和分区。不要试图用应用程序中的东西来解决它
【解决方案2】:

一般来说,您希望将所有“喜欢”的数据保存在一个表中,而不是拆分成多个表。这有充分的理由:

  • 添加新组合更容易。
  • 维护表更容易。
  • 您可以轻松地“跨”实体进行查询。
  • 总体而言,数据库效率更高,因为页面被填满的可能性更大。

还有其他原因。在您的情况下,您可能有一个论据将数据分成 6 个单独的表。这里的收益来自于数据中没有coloris_left_one。这意味着该数据不会重复 600 万次。这可以节省数十兆字节的数据存储空间。

我说最后一句有点半开玩笑(意思是我没那么认真)。如今的计算机拥有如此多的成员,以至于 100 MB 通常并不重要。但是,如果您有一个内存严重受限的环境(我想在这里“观看”,甚至不是“智能手机”),那么它可能会很有用。

否则,分区是一个很好的解决方案,几乎可以满足您的需求。

【讨论】:

  • 是的,我还将列“颜色”和布尔值保存在数据中。谢谢你的好点。 +1!
【解决方案3】:

为此:

WHERE color=blue AND is_left_one=true

最优索引是

INDEX(color, is_left_one)  -- in either order

首先拥有id 使其对WHERE 毫无用处。

拥有多个相同的表而不是一个通常是不好的。

【讨论】:

  • 您能否详细说明“拥有多个相同的表而不是一个通常不好”?我知道这是一个(远)不太漂亮的设计,但我需要挤出每一点性能,所以我的问题尤其是在性能/内存/延迟方面
  • @AntoninGAVREL - 为了提高性能,让我们看看对服务器造成最大拖累的 SQL 语句。 (我怀疑不仅仅是这个WHERE 子句。)
猜你喜欢
  • 1970-01-01
  • 2011-03-14
  • 1970-01-01
  • 2014-06-28
  • 2014-04-29
  • 2016-10-18
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多