【问题标题】:LEFT OUTER JOIN needs improving due to poor performance由于性能不佳,LEFT OUTER JOIN 需要改进
【发布时间】:2013-01-30 05:30:46
【问题描述】:

我有一个表,其中包含一个名称列以及 3 个标识符,这些标识符引用同一个表中的其他条目。我的查询将这 3 个标识符解析为它们所引用的记录的实际名称。到目前为止,我只管理了以下...

SELECT mt.Name, mt2.Name, mt3.Name, mt4.Name 
FROM MyTable AS mt1
LEFT OUTER JOIN MyTable AS mt2 ON mt2.Id = mt1.RefId1
LEFT OUTER JOIN MyTable AS mt3 ON mt3.Id = mt1.RefId2
LEFT OUTER JOIN MyTable AS mt4 ON mt4.Id = mt1.RefId3

...它有效并且确实返回了三个参考记录的名称。请注意,在某些情况下,RefId1/2/3 值可能为空,因此并非始终使用所有 RefId 字段。它可以工作,但不是很快,我相信真正了解 SQL 的人可以显着改善这一点。有什么想法吗?

【问题讨论】:

  • ID可以对应1个以上的refID吗?
  • 执行计划是什么样的?
  • 每个 RefId 列在表中是否都有索引?
  • RefId1/2/3 永远不会指向相同的其他记录。它们将始终为空或指向唯一记录。
  • 目前唯一的索引是 MyTable.Id 列。

标签: sql left-join outer-join


【解决方案1】:

为了改进您的查询,您可以使用 INNER JOIN 而不是 LEFT OUTER JOIN。如果我正确理解您的评论,mt2、mt3 或 mt4 都会返回一个值。

所以,一个有效的查询就可以这样写。这样可以确保一旦找到匹配项,它就会停止向前看。

SELECT mt.Name, mt2.Name
FROM MyTable mt, MyTable mt2
WHERE mt2.id = mt.RefId1
OR mt2.id = mt.RefId2
OR mt2.id = mt.RefId3

让我知道这是否有效。

【讨论】:

  • 所有三个 RefId 字段都可能指向不同的记录,因此我可能需要取回所有三个名称。
  • 好的,在这种情况下,您只需将查询中的 LEFT OUTER JOIN 替换为 INNER JOIN。 INNER JOIN 致力于与结果集相交的概念,因此应该为您完成。
  • 不幸的是,如果任何交叉点为空,则内部连接会省略行,因此您需要对所有 refId 添加一个空检查。我正在尝试找到解决方法,并会更新答案,或者在我找到某些内容后回复评论。
【解决方案2】:

你试过indexing你的桌子吗?

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2016-10-31
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-08-10
    • 2013-03-10
    • 2010-09-29
    相关资源
    最近更新 更多