【问题标题】:Should a long ordered list of ids be stored in a column of a database table? [duplicate]是否应该将长有序的 id 列表存储在数据库表的列中? [复制]
【发布时间】:2021-12-01 10:10:14
【问题描述】:

假设我有一个用户表,其中包含一个 id 列和一个排名列。 每个用户都可以按某种顺序对其他用户进行排名。 假设这个列表可能很长(某个常数的最大值,比如 10,000),但通常会短得多。 只需要存储和检索用户的整个列表,也就是说,每个列表都不需要是例如在查询中搜索。

一个想法是以逗号分隔的字符串形式将其存储为 id 列表。 唯一的缺点是外键不能将列表中的每个 id 连接到相应用户的 id 列,这意味着如果用户的 id 发生更改,它不会在列表中自动更改。但是,用户的 id 永远不会改变,所以这是一个原则问题(不破坏 1NF?)。

另一个想法是创建一个表,其中每个条目都有一个 from 和 to 用户 ID 列以及一个排名列。这样做的缺点是,与用户数量相比,该表可能包含大量记录(例如数十亿)。此外,在检索用户列表时,它需要搜索许多记录。有重复的数据,例如排名现在是显式存储的,而不是隐式存储的,这意味着在列表中进行一次更改可能意味着属于该列表的所有记录都必须更新其排名列。

什么是更好的解决方案?有完全不同的解决方案吗?

编辑: 我想大多数人会说第二个是最好的,因为它是一个关系数据库,但是,你能说可以减轻负面影响或者为什么它们不重要吗?如果有序列表可以更长,例如每个都有数百万个元素,所以列表更像是一团数据,而一个等效的表可能包含数万亿个条目?

当使用表格时,用户可能需要将排名复制到前端语言的数组中以进行编辑,因此每次更改都必须在前端和后端进行,或者必须删除旧记录并为新列表的每个元素插入一条新记录。

【问题讨论】:

    标签: sql database-design


    【解决方案1】:

    对于关系数据库来说,这通常不是一个好的设计。

    存储以逗号分隔的值列表是一种非规范化。良好的关系数据库设计鼓励规范化。

    所有类型的优化都会以牺牲其他查询为代价来改进一种查询。在您的情况下,如果您只存储或检索整个 id 列表,那么它可能是一个很好的优化。但是,如果您想在列表中添加一个 id,或者搜索一个特定的 id,或者确保它们被正确排序,或者许多其他类型的操作,那么这些任务就不会被优化。

    使用逗号分隔的列表实际上有很多缺点,不仅仅是你提到的外键。我在这里写了一个关于这个的旧答案:Is storing a delimited list in a database column really that bad?

    使用规范化设计使数据库更加灵活。也就是说,您可以对数据运行多种类型的查询,而且没有一种是特别不利的。

    因此,像非规范化这样的优化要求您确保预先知道哪些查询对您的项目很重要,并且您知道您不需要任何类型的查询,这些查询因非规范化设计而成本更高。或者,如果您偶尔确实需要这些查询,则不需要它们来提高效率。

    如果您以规范化的方式存储这些行,您表示担心会产生很多行,但大多数 RDBMS 产品可以处理数十亿行。

    如果您创建了正确的索引,搜索不应该扫描很多行。哪些索引是正确的取决于您需要优化哪些查询。


    如果有序列表可以更长,例如每个都有数百万个元素,所以列表更像是一团数据,而一个等效的表可能包含数万亿个条目?

    恕我直言,如果您必须解决这种规模的数据管理问题,那么您就不会问如何在 Stack Overflow 上解决它。你会聘请一些高级软件架构专家来解决它。

    他们会告诉您基本相同的事情:您必须非常明确您需要针对这些数据执行哪些类型的查询,然后他们才能选择最佳架构来支持这些特定查询.因为在这种规模下,除了最佳方法之外,您什么都做不了。

    如果您不需要解决“数万亿个元素”规模的问题,那么使用关系解决方案就足够了,并且提供了灵活性,如上所述。

    我看到很多 SO 问题都在询问 Facebook 如何管理如此规模的数据。答案几乎总是:“他们做什么并不重要,因为您永远不必按照他们的规模做事。”

    【讨论】:

    • 这很有道理,我进行了编辑。特别是有没有办法在删除记录时避免更新所有排名较高的记录?
    猜你喜欢
    • 2011-03-05
    • 1970-01-01
    • 1970-01-01
    • 2010-09-18
    • 1970-01-01
    • 1970-01-01
    • 2017-04-03
    相关资源
    最近更新 更多