SQL - 使用连接过滤大表 - 最佳实践

Posted

技术标签:

【中文标题】SQL - 使用连接过滤大表 - 最佳实践【英文标题】:SQL - Filtering large tables with joins - best practices 【发布时间】:2011-03-31 08:06:35 【问题描述】:

我有一个包含大量数据的表,我需要将它与其他一些大表连接起来。

每次我的表中只有一小部分与我真正相关。

什么时候最好过滤我的数据?

    在 SQL 的 where 子句中。

    使用特定数据创建一个临时表,然后才加入它。

    将谓词添加到第一个内连接 ON 子句。

    其他想法。

1.

Select * 
From RealyBigTable
Inner Join AnotherBigTable On …
Inner Join YetAnotherBigTable On …
Where RealyBigTable.Type = ?

2.

Select * 
Into #temp
From RealyBigTable
Where RealyBigTable.Type = ?

Select * 
From #temp
Inner Join AnotherBigTable On …
Inner Join YetAnotherBigTable On …

3.

Select * 
From RealyBigTable
Inner Join AnotherBigTable On RealyBigTable.type = ? And … 
Inner Join YetAnotherBigTable On …

另一个问题: 首先会发生什么? JoinWhere?

【问题讨论】:

【参考方案1】:

因为您使用的是 INNER JOIN,所以 WHERE 或 JOIN 的争论只取决于您的品味和风格。就个人而言,我喜欢在 ON 子句中保留两个表之间的链接(例如外键约束),并在 WHERE 子句中对数据进行实际过滤。

SQL Server 会将查询解析为相同的标记树,因此会构建相同的查询执行计划。

如果您改用 [LEFT/RIGHT] OUTER JOINS,它会产生很大的不同,因为不仅性能可能不同,而且结果也很可能不同。


要回答您的其他问题:

什么时候最好过滤我的数据?

    在 SQL 的 where 子句中。 使用特定数据创建一个临时表,然后才加入它。 将谓词添加到第一个内连接 ON 子句。 其他一些想法。

在 WHERE 或 ON 子句中,两者被视为相同。对于 3,“first 内连接”没有相关性。在多表 INNER JOIN 场景中,哪个先执行(在查询中)实际上并不重要,因为查询优化器会根据需要调整顺序。

使用临时表是完全没有必要的,也无济于事,因为无论如何您都必须提取相关部分——这也是 JOIN 会做的事情。此外,如果您在 JOIN 条件/WHERE 过滤器上有一个良好的索引,则该索引将仅用于访问相关数据,而无需查看表的其余部分。

【讨论】:

好的。但是将数据放在临时表中然后才(内部)加入不同的表不是更好吗?【参考方案2】:

您应该将您的查询放在管理工作室中,勾选“包括实际执行计划”,然后运行它。这样,您将获得 SQL Server 对您的查询所做的确切答案。从那时起,您可以继续优化。

一般:

用于连接的列应该被索引 首先使用最具辨别力的过滤器

【讨论】:

【参考方案3】:

在一个体面的基于成本的查询计划器中会发生什么(你的情况)

    join 条件和 where 条件在同一级别解析

    连接类型和统计信息确定路径(先发生什么) - 以这样一种方式检索最小的中间结果(最少 I/O > 最快查询)

【讨论】:

以上是关于SQL - 使用连接过滤大表 - 最佳实践的主要内容,如果未能解决你的问题,请参考以下文章

连接 WPF 和 SQL Server 的最佳实践

在连接上扩展 SQL 查询的最佳实践?

连接 MongoDB 的最佳实践 [重复]

在 Spark SQL 中将多个小表与大表连接的最佳方法

雪花中实现sql“JOIN”返回策略的最佳实践

使用 JavaScript 在客户端过滤项目、隐藏或从 DOM 中删除的最佳实践?