【问题标题】:Is a query with over 50 joins slow?超过 50 个连接的查询是否很慢?
【发布时间】:2013-02-20 00:00:26
【问题描述】:

我计划使用 EAV 设计开发一个应用程序。我对EAV和第六范式做了很多研究。我什至与工作中的人交谈过,他们说如果你关心自己的理智,请避免这两种方法。我有创建包含一千多列的表的想法,但根据question,这可能不是一个好主意。所以我想做的不是在一个表中创建一千列,而是创建一千个“一列”表。这将使我能够将所有列分成“一列”表。这会给我最大的灵活性,但我担心性能会受到很大影响。

  • 我的问题是:使用 50 个内部联接(一个 到一个)?该数据库将为公共网站提供支持。

【问题讨论】:

  • 是的,我认为超过七个的查询会被认为太大。一千个一列的表?不。您需要学习如何设计关系数据库。找人来帮助你 - 听起来你有点不知所措。
  • 你需要学习如何设计一个关系数据库,如果你准备1列1000个表,你可能没有使用任何relation,那为什么还需要join呢?如果所有元素都是相关的,那么您应该仔细关注关系,这就是关系数据库的用途
  • 通过适当的索引加入 50 个表可能很有效,但单列表听起来不像 EAV。
  • @Luke101 您可以按使用 xpath 提取的值进行分组。像这样:sqlfiddle.com/#!12/af4e2/2/0
  • @ypercubeᵀᴹ 大概是“一列”表,它们的意思是 CK 加一列 (6NF) 的表,大概 CK 是 {user, entity}。 6NF 的使用是表示可空列的规范(无 NULL)关系方式。它并不意味着是 EAV,而是意味着代替 EAV。所以事实证明,它是every EAV 设计的(无NULL)关系设计替代方案。 (缺少嵌套关系和元组,允许将用户作为 CK 并将其 dbms/表的状态作为列的表。巧合的是,它也使用 6NF。)

标签: sql sql-server oracle postgresql


【解决方案1】:

这听起来像是在关系模型之外更好地解决的问题 - 使用 xmljson、数组值或 hstore 字段,或者使用针对此类工作优化的键/值或列存储。

见:

【讨论】:

    【解决方案2】:

    我在 postgresql 中遇到了实际的默认限制,它是 8 个连接。任何超过 8 的东西都加入了 postgres,你就是在玩火。

    更具体地说,join_collapse_limit 默认为 8。如果查询超出 join_collapse_limit 连接,则计划器拒绝重新排序连接。我怀疑计划时间相对于连接数大约为 O(n^2)(因此默认值较低)。您可以将 join_collapse_limit 增加到 1000,但是查询计划会变得非常慢。

    所以,是的,在 postgres 中,超过 50 个连接可能是个坏主意。而且我敢打赌,您会在其他数据库中发现类似的限制:优化连接顺序在任何平台上都可能大致为 O(n^2)。

    【讨论】:

    • 我不同意 8 个连接是 Pg 的限制,我通常会连接更多的表,尤其是在涉及复杂视图时。这取决于要连接的表的大小、查询的复杂性、是否可以计划和准备一次并保存计划等等。增加join_collapse_limit 至关重要。但这并不意味着 OP 的设计是个好主意。
    【解决方案3】:

    我看不出问题本身。这基本上就是 Vertica 等列式数据库存储数据的方式。不过,肯定有一些考虑因素。

    首先,假设您没有跨行进行原子插入、更新和删除。为此类操作管理 1000 个表将是一项挑战。

    其次,用于join的键应该是所有表的主键。我建议不要大于整数。您需要意识到这会在每列插入 4'ish 字节的开销,因此列式数据库最终可能会比列式版本大得多。在其他数据库中,这可以通过在列中进行压缩来缓解。

    您还需要意识到还有其他限制,例如视图和表中允许的列数。

    假设所有的表都可以放入内存并且通过主键连接,那么性能可能会相当不错。

    话虽如此,我不确定 1000 个单列表是否真的能满足您的需求。有许多处理宽表的网站和应用程序。很少(任何?)完全将它们分成单列。你这样做有商业原因吗?一般来说,数据库设计应该由业务需求和应用需求驱动,而不是由第一、第二或第六范式的概念来驱动。

    【讨论】:

    • 列式数据库进行了大量其他优化,但是,除了单独存储每一列。
    • ...所以,只是在数据库中创建一堆未优化的列状表不一定是一件好事。
    • @AaronBertrand 。 . .我不是说这是一件好事。我只是说这不是一个完全疯狂的想法。而且,是的,我知道列式数据库所做的优化。
    • 对我来说,您的开头段落类似于“哦,您这样做应该没有任何问题,因为这是列式数据库所做的。”
    • 这是一个很好的答案,但我会将你的最后一句话移到顶部 - 这是重要的概念。
    【解决方案4】:

    EAV 是整个应用程序的反模式。它应该只用于一小部分应用程序。看到这个:http://mikesmithers.wordpress.com/2013/12/22/the-anti-pattern-eavil-database-design/

    而且,EAV 表将至少有两列,而不是一列。

    但要回答您的问题 - 我们不知道。我已经看到加入 30 个表并且仍然很快的查询。我在一张桌子上看到了非常慢的查询。一些数据库引擎 (postgres) 甚至无法处理大量的连接,并且一些数据库版本施加了硬限制(MSSQL 有 256 个表的限制)。

    没有通用的方法来回答这个问题,只是说您几乎总是应该尽可能简单地设计事物,并且对于许多应用程序来说,使用 EAV 是不必要的复杂性,这些应用程序往往会自然地映射到宽表。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-12-13
      • 1970-01-01
      • 2016-03-11
      • 2015-02-22
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多