【问题标题】:Query same table multiple times多次查询同一张表
【发布时间】:2016-09-25 14:38:35
【问题描述】:

当我需要引用不同列上的相同数据时,我总是使用多个连接。像这样:

select
    a.ContactName
    ,b.ContactName
    ,c.ContactName
from
    OrderBase as o
    left join ContactBase as a on o.contactid1 = a.ContactId
    left join ContactBase as b on o.contactid2 = b.ContactId
    left join ContactBase as c on o.contactid3 = c.ContactId

我一直认为这是非常低效的。为 3 次查找加载表 3 次。有没有更有效的方法来做到这一点?我不是指编写代码,而是使用资源。 在 SQL Server 的更高版本中是否有任何好的工具可以解决这个问题?

【问题讨论】:

  • 如果您使用正确的索引,这应该是最好的方法...
  • 联系人 1,2 和 3 需要 3 列。因此没有其他方法可以获得该结果。你的数据库有多大?如果它不够大,为什么你认为这没有效率。如果您有性能问题,您可以使用 schema_binding 视图进行此特定查询。它虽然使用磁盘存储。顺便说一句,我认为您的 ContacBase 表不应该很大。如果您的 ContactBase 表很大,添加索引会提高性能,否则不会有太大提升。
  • OrderBase 可以添加contactName1、contactName2、contactName3 并存储OrderBase 更新的位置。那么,就不需要加入了……
  • @daniel,你是说他应该存储冗余数据?!!
  • @daniel,在 OLTP 数据库中有冗余数据根本不是一个好主意。还有许多其他方法可以提高性能。

标签: sql sql-server-2012 query-optimization


【解决方案1】:

第一条评论是,在多列中存储相同的值通常是一种可疑的模式。通常,使用每个“OrderBase”一行和每个“ContactId”一行的联结表更好地服务于这样的数据结构。联结表并不总是最好的解决方案,但通常是。

至于您的查询:

select a.ContactName, b.ContactName, c.ContactName
from OrderBase as o left join
     ContactBase a
     on o.contactid1 = a.ContactId left join
     ContactBase b
     on o.contactid2 = b.ContactId left join
     ContactBase c
     on o.contactid3 = c.ContactId;

这特别需要ContractBase(ContactId, ContactName) 上的索引。为此目的使用left join 是完全合理的。

有了这个索引,查询甚至不需要原始数据页,因为索引“覆盖”了查询——查询中的所有列都在索引中。您无需担心多次加载索引。虽然索引(或表)在逻辑上加载了 3 次,但称为页面缓存的东西可能会将页面保留在内存中,因此后续加载会非常快。

【讨论】:

  • 我是自学成才的,所以我还不是数据库引擎内部工作的专家。似乎没有“更好”的方法来做到这一点(还)。但是由于我一直在学习,您能详细说明一下吗?逻辑加载的索引将如何处理海量数据?它可以缓存无限量的数据吗?如果我加入 150 列并拥有数百万行,这仍然是最好的方法吗(不考虑写作的噩梦。可能会使用 xml 或动态查询来简化写作)。
  • @Sweetspot 。 . .在出现问题之前,您不应该担心性能问题。假设索引设置正确,像这样执行三个left joins 应该不是问题。
猜你喜欢
  • 2018-11-25
  • 2019-02-21
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-06-09
  • 2017-06-30
  • 2020-09-08
  • 1970-01-01
相关资源
最近更新 更多