数据库架构:一个 table 使用 WHERE 与多个
DB Architecture: One table using WHERE vs multiple
我想知道一个 table 有 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 table 秒,100 万行:
CREATE TABLE blue_left_shoes(
id serial primary key,
stock int
);
后者似乎更有效,因为用户不必询问条件,因为 table 是条件,但也许创建索引可以缓解这种情况?
这个table用于查询左、右、"blue"、"green"或"red"鞋子,以及查看剩余物品的数量,但它是一个简化的示例,但您可以将亚马逊(或任何数字销售平台)工具提示 "only 3 items left in stock" 用于工作负载和用例。将进行查询的是用户(每天 10 万活跃用户)。
注意:问题主要针对 PostgreSQL,但与其他数据库的差异仍然相关且有趣。
为此:
WHERE color=blue AND is_left_one=true
最优索引为
INDEX(color, is_left_one) -- in either order
首先拥有 id
使其对 WHERE
毫无用处。
拥有多个相同的表而不是一个通常是不好的。
在后一种情况下,您使用名为 blue_left_shoes
的 table
- 您的代码需要首先确定要查看哪个 table(而不是在 where 子句中参数化值)
- 随着排列和选项的增加,您需要增加 table 的数量,并增加您的应用程序中确定使用哪个 table 的逻辑
- 任何需要使用此数据库的东西(即报告工具或 API)现在都需要重新实施所有这些规则
您正在高层强加逻辑以提高性能。
如果您要适当地对 and/or 索引 table 进行分区,您会得到相同的效果 - SQL 查询仅查看重要的记录。不同的是,你不需要在更高层实现这个逻辑
只要你能正确地建立索引,保持它是一个 table 几乎总是正确的做法。
分区
数据库分区是您 select 一列或多列决定如何 "split up" 您的 table 的地方。在您的情况下,您可以选择 (color, is_left_one).
现在您的 table 以这种方式进行逻辑拆分和排序,当您搜索 blue,true 时,它会自动知道要查找的分区。它不会查找任何其他分区(这称为分区修剪)
请注意,这是根据搜索条件自动发生的。您无需手动计算出要查看的特定 table。
- 分区不需要任何额外的存储(除了必须保存的各种元数据)
- 您不能将多个分区应用到 table。只有一个
索引
创建索引还可以提高性能。但是索引占用 space 并且会影响插入和更新性能(因为它们需要维护)。实际上,select 权衡几乎总是远远超过任何 insert/update 负面因素
你应该总是在分区之前查看索引
非 selective 索引
在您的特定情况下,还有一件事需要考虑:布尔字段不是 "selective"。我不会详细介绍,但足以说明您不应该单独在该字段上创建索引,因为它不会被使用,因为它只会将您必须查看的记录数减半。您需要在任何索引(即颜色)中包含一些其他字段以使其有用
一般来说,您希望将所有 "like" 数据保存在一个 table 中,而不是分成多个。这样做有充分的理由:
- 添加新组合更容易。
- 维护 table 更容易。
- 您可以轻松查询 "across" 个实体。
- 总体而言,数据库效率更高,因为页面更有可能被填满。
还有其他原因。在您的情况下,您 可能 有一个将数据分成 6 个单独的 table 的参数。这里的好处来自于数据中没有 color
和 is_left_one
。也就是说,这个数据没有重复 600 万次。这可以节省数十兆字节的数据存储空间。
我说最后一点有点开玩笑(意思是我没那么认真)。现在的计算机有这么多成员,一般来说 100 Mbytes 并不重要。然而,如果你有一个内存严重受限的环境(我在这里考虑 "watch",甚至 "smart phone")那么它可能会有用。
否则,分区是一个很好的解决方案,几乎可以满足您的需求。
我想知道一个 table 有 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 table 秒,100 万行:
CREATE TABLE blue_left_shoes(
id serial primary key,
stock int
);
后者似乎更有效,因为用户不必询问条件,因为 table 是条件,但也许创建索引可以缓解这种情况?
这个table用于查询左、右、"blue"、"green"或"red"鞋子,以及查看剩余物品的数量,但它是一个简化的示例,但您可以将亚马逊(或任何数字销售平台)工具提示 "only 3 items left in stock" 用于工作负载和用例。将进行查询的是用户(每天 10 万活跃用户)。
注意:问题主要针对 PostgreSQL,但与其他数据库的差异仍然相关且有趣。
为此:
WHERE color=blue AND is_left_one=true
最优索引为
INDEX(color, is_left_one) -- in either order
首先拥有 id
使其对 WHERE
毫无用处。
拥有多个相同的表而不是一个通常是不好的。
在后一种情况下,您使用名为 blue_left_shoes
- 您的代码需要首先确定要查看哪个 table(而不是在 where 子句中参数化值)
- 随着排列和选项的增加,您需要增加 table 的数量,并增加您的应用程序中确定使用哪个 table 的逻辑
- 任何需要使用此数据库的东西(即报告工具或 API)现在都需要重新实施所有这些规则
您正在高层强加逻辑以提高性能。
如果您要适当地对 and/or 索引 table 进行分区,您会得到相同的效果 - SQL 查询仅查看重要的记录。不同的是,你不需要在更高层实现这个逻辑
只要你能正确地建立索引,保持它是一个 table 几乎总是正确的做法。
分区
数据库分区是您 select 一列或多列决定如何 "split up" 您的 table 的地方。在您的情况下,您可以选择 (color, is_left_one).
现在您的 table 以这种方式进行逻辑拆分和排序,当您搜索 blue,true 时,它会自动知道要查找的分区。它不会查找任何其他分区(这称为分区修剪)
请注意,这是根据搜索条件自动发生的。您无需手动计算出要查看的特定 table。
- 分区不需要任何额外的存储(除了必须保存的各种元数据)
- 您不能将多个分区应用到 table。只有一个
索引
创建索引还可以提高性能。但是索引占用 space 并且会影响插入和更新性能(因为它们需要维护)。实际上,select 权衡几乎总是远远超过任何 insert/update 负面因素
你应该总是在分区之前查看索引
非 selective 索引
在您的特定情况下,还有一件事需要考虑:布尔字段不是 "selective"。我不会详细介绍,但足以说明您不应该单独在该字段上创建索引,因为它不会被使用,因为它只会将您必须查看的记录数减半。您需要在任何索引(即颜色)中包含一些其他字段以使其有用
一般来说,您希望将所有 "like" 数据保存在一个 table 中,而不是分成多个。这样做有充分的理由:
- 添加新组合更容易。
- 维护 table 更容易。
- 您可以轻松查询 "across" 个实体。
- 总体而言,数据库效率更高,因为页面更有可能被填满。
还有其他原因。在您的情况下,您 可能 有一个将数据分成 6 个单独的 table 的参数。这里的好处来自于数据中没有 color
和 is_left_one
。也就是说,这个数据没有重复 600 万次。这可以节省数十兆字节的数据存储空间。
我说最后一点有点开玩笑(意思是我没那么认真)。现在的计算机有这么多成员,一般来说 100 Mbytes 并不重要。然而,如果你有一个内存严重受限的环境(我在这里考虑 "watch",甚至 "smart phone")那么它可能会有用。
否则,分区是一个很好的解决方案,几乎可以满足您的需求。