【问题标题】:How to store data structures when certain operations need to be performed in faster than O(n) time?当某些操作需要以比 O(n) 更快的时间执行时,如何存储数据结构?
【发布时间】:2019-11-14 08:09:56
【问题描述】:

(我是数据库的新手,如果这是一个奇怪的问题,请道歉。如果您认为我没有清楚地思考,请随时不同意我的观点。)

一些数据结构支持可以在比O(n) 时间更好的时间内完成的操作,其中n 是当前存储在结构中的项目数。例如,heaps 允许 O(log n) 插入和删除项目。我不明白在数据库中存储此类数据结构的正确方法。

问题。关于一般数据库,特别是关于 Django 2.2.7 和 Postgres 12.0,当需要比O(n) 操作更快时,存储数据结构的正确方法是什么? ?

这个问题的其余部分是阐述和讨论。

例如,假设我们的数据库包含两张表,一张名为Person,另一张名为Task。每个Task 都有一个关联的Person 字段,称为assignee,代表任务分配给的人,还有一个关联的int 字段,称为priority,代表任务的紧迫性。

现在,现实世界中的任何给定人都可能想要查询数据库以获取分配给他们的最高优先级Task。处理此类请求的最简单方法是遍历Task 的每一行,一次一个。不幸的是,假设每个Person 至少有一个任务,随着Person 中行数的增长,这很快就会变得低效。

为了提高查询的时间复杂性,我们可能会在Person 表中添加另一列,类型为list(Task),称为tasks。这个想法是,该字段将维护此人已分配的所有任务的列表。此更改会导致数据库使用更多空间,但当有人请求分配给他们的最高优先级任务时,会大大提高性能。 (我不是专家,但我认为这种添加冗余信息以提高性能的过程称为“非规范化” - 知道他们的东西的人可以发表评论并确认我正确使用了这个术语吗?)

无论如何,即使上述非规范化已经到位,仍然存在问题。也就是说,如果某人有大量与之相关的任务会发生什么?在这种情况下,即使Person 表包含tasks 字段,数据库为请求提供服务所花费的时间也可能非常长。

在我的计算机科学学位中,我们被教导通过选择适当的数据结构来解决这类问题。在这种情况下,我们可能会更改tasks 字段的类型,这样它就不会指向list(Task) 类型的对象,而是指向heap(Task) 类型的对象。

但是,这样做的正确方法对我来说并不明显。如果堆在硬盘驱动器上存储为一个项目数组,并且如果对堆的每个操作都需要我们将整个数组加载到内存中,执行操作,然后再次存储它,那么现在我们回到@ 987654346@ 的时间复杂度只是执行一次插入或弹出操作,通常需要O(log n) 时间。

所以我的问题是如何避免这种情况。

【问题讨论】:

标签: django database postgresql time-complexity storage


【解决方案1】:

我不明白在数据库中存储此类数据结构的正确方法。

您不会将数据结构存储在数据库中,而是使用数据库提供的特定数据结构将数据存储在数据库中。

你提到了 PostgreSQL。那是一个特定的产品,广泛兼容SQL数据库标准,使用与relational model数据兼容的数据结构。它定义了它使用的数据结构,以及使用它们的时间复杂度。在您的具体示例中,关系数据库提供了一种数据结构来解决您的问题,称为index

在我的计算机科学学位中,我们被教导通过选择适当的数据结构来解决这类问题。

没错。选择合适的数据结构后,您可以使用实现它的数据存储产品来存储您的数据data structure 不是可以存储的东西。

请注意,关系数据库只是存储和表示数据的一种方式。它们已被证明非常有用,并提供了多种数据结构(最值得注意的是表和索引)。但是还有一些其他的数据结构不能被关系数据库很好地实现。在这种情况下,您使用不同的产品。例如,Redis 将自己标榜为data-structures server,并提供了一组与关系数据库完全不同的特定数据结构和访问模式。 Graph databases 是另一个例子。

【讨论】:

  • 我刚刚看了一点 Redis,在数据库最终太大而无法放入主内存的情况下,这似乎不是一个合适的数据库框架。对吗?
【解决方案2】:

大 O 表示法可能会产生误导。例如,索引查找是 O(log n),但对数的底非常高,即使是最大的表也不必读取超过 6 个索引块。

这类似于在表中定位可用空间。即使是一张大表,其空闲空间映射也非常小,因此定位一个有空闲空间的块会很快。

我认为您的担忧属于过早优化领域。

【讨论】:

  • 虽然我同意大 O 表示法可能会产生误导的一般观点(实际上我通常是指出这一点的人),但我并不真正理解您的评论。当您不知道软件的预期目标时,如何将解决方案标记为过早优化?
  • 确实,看看实际的问题:“关于一般的数据库,特别是关于 Django 2.2.7 和 Postgres 12.0,什么是更快地存储数据结构的正确方法比需要 O(n) 次操作吗?”这不可能是过早的优化,因为假设需要比 O(n) 更快的操作。
  • 我的回答是关于在表中插入和删除单个行。对不起,我以为这就是你想要的。当表很大时,这些操作不会显着变慢。
  • 很公平!
【解决方案3】:

如果您想手动实现所有自己的数据结构,您首先使用 PostgreSQL 做什么?您使用复杂的软件是因为它已经为您完成了这些事情。

create index on task (assignee, priority);

select * from task where assignee=314159 order by priority desc limit 1;

除非您尝试过这个简单的解决方案但它不起作用,否则这里没有什么需要定制的优化。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2018-02-22
    • 1970-01-01
    • 2018-12-25
    • 2011-12-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多