【问题标题】:Possible large data set from subquery?可能来自子查询的大型数据集?
【发布时间】:2012-12-10 00:52:38
【问题描述】:

由于其复杂性,我无法向您展示我的确切问题和查询,但我会将问题简化为另一个类似的问题。

这里是:

有 5 个表格,包含有关苹果、汽车、书籍、电脑和衣服的信息。上面的每个表都可以有 cmets,所有 cmets 都存储在一个名为 Comments 的表中(带有 user_id 列)。为了将这 5 个表与它们自己的 cmets 链接,我必须创建 5 个其他链接表名称 AppleComments、CarComments、BookComments,等等。

我的查询想要从这 5 个类别类型中检索我的所有 cmets。

我能想到两种方法,一种比另一种快。

  1. 我可以将 5 个表与其链接表连接起来,然后使用 cmets where comments.user_id = me,然后将所有结果联合到 1 个结果集中:

    SELECT <column_names> FROM AppleComments
    INNER JOIN Comments ON AppleComments.comment_id = Comments.comment_id
    WHERE Comments.user_id = me
    
    UNION ALL
    
    SELECT <column_names> FROM CarComments
    INNER JOIN Comments ON CarComments.comment_id = Comments.comment_id
    WHERE Comments.user_id = me
    etc...
    
  2. 我可以使用 union all 从链接表中选择所有评论 ID,然后将此子查询与 Comments 表进行内部连接以获取有关它们的其他信息。

    SELECT <column_names> 
    FROM (
       Select AppleComments.comment_id FROM AppleComments
       UNION ALL
       Select CarComments.comment_id FROM CarComments
       UNION ALL
       Select BookComments.comment_id FROM BookComments
       UNION ALL
       Select ComputerComments.comment_id FROM ComputerComments
       UNION ALL
       Select ClothesComments.comment_id FROM ClothesComments) AS items
    INNER JOIN Comments ON items.comment_id = Comments.comment_id
    WHERE Comments.user_id = me
    

第二个速度更快,生成的执行计划更小。

问题是,因为来自 ex 的子查询“项目”。 2 实际上从数据库中选择所有 cmets 然后与 cmets 表进行内部连接,我担心在处理太多行时它会表现不佳。可能是内存太多了?

现在我无法确定,因为 90% 的 cmets 是我的,但从每个示例的角度来看,我会说第一个是检索较少数据量(总计)的那个。

如果数据库中有 100 万个 cmets 而我的只有 100 个会怎样...

谢谢。

【问题讨论】:

    标签: sql-server subquery


    【解决方案1】:

    你的直觉是正确的。 UNION ALL 将几乎消除未来优化的机会。在加入工会之前尽你所能;第一种方法是正确的。

    除了它提出的问题是为什么您在五个不同的表中有相似的东西,为什么您甚至在看似一对 N 的关系中还有链接表?带有itemtype 字段的单个表是否不够?如果你有额外的数据,那么有可选的外部链接到额外的数据表,这就是我要做的......

    当然,这是一个虚构的宇宙,我不知道你原来的问题:)

    【讨论】:

    • 感谢您的回答,但第二个速度更快,执行计划更小。我不知道为什么。第一个几乎是两倍,我在想的原因是因为它有更多的连接。
    • 我在这里可能错了,但我认为这是较小数据集的效果。 AFAIK 联合数据没有索引,因此即使只有一个连接,当您的数据膨胀时也会减慢速度。较小的执行计划是意料之中的 - 你正在做的更少(尽管,IMO,越少最终成为一个更大的苦差事)。
    • 我建议你注意 Amadan 非常有效的 cmets。如果这是您的问题和数据库设计的准确表示,并且您现在有机会更改设计,我建议您遵循 Amadam 的建议并更改您的数据库设计。例如,您通常最好使用表分区(透明的)等性能调整技术,而不是创建以后永远需要在应用程序代码中允许使用的特殊表。
    猜你喜欢
    • 2017-07-16
    • 1970-01-01
    • 1970-01-01
    • 2019-09-17
    • 1970-01-01
    • 2013-05-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多