Sql 在外部联接中vs ON的位置

Sql 在外部联接中vs ON的位置,sql,join,outer-join,Sql,Join,Outer Join,我想知道当我们决定是否复制已经在Where子句中的条件时,如何获得更好的SQL性能 我的朋友声称这是由DB引擎决定的,但我不太确定 不管DB引擎如何,通常情况下,Where子句中的条件应该在连接之前首先执行,但我假设它意味着内部连接,而不是外部连接。因为某些条件只能在外部联接之后执行 例如: Select a.*, b.* From A a Left outer join B on a.id = b.id Where b.id is NULL; Where中的条件不能在外部联接之前执行 因

我想知道当我们决定是否复制已经在Where子句中的条件时,如何获得更好的SQL性能

我的朋友声称这是由DB引擎决定的,但我不太确定

不管DB引擎如何,通常情况下,Where子句中的条件应该在连接之前首先执行,但我假设它意味着内部连接,而不是外部连接。因为某些条件只能在外部联接之后执行

例如:

Select a.*, b.* 
From A a
Left outer join B on a.id = b.id 
Where b.id is NULL;
Where中的条件不能在外部联接之前执行

因此,我假设必须在where子句之前首先执行整个ON子句,并且似乎ON子句将在外部联接之前控制表B(或表A,如果我们使用右外部联接)的大小。对我来说,这似乎与DB引擎无关

这就提出了我的问题:当我们使用外部连接时,我们是否应该在ON子句中删除我们的标准

例如(我使用一个表与一个较短版本的表进行外部联接)

临时系列安装和系列id>18940000vs临时系列安装

select sql_no_cache s.*, t.* from temp_series_installment s
left outer join temp_series_installment t on s.series_id = t.series_id and t.series_id > 18940000 and t.incomplete = 1
where t.incomplete = 1;
VS

编辑:其中t.complete=1执行以下逻辑:其中t.series\u id不为空 这是Gordon Linoff建议的内部联接 但我一直在问的是:如果它加入一个更小的表,它应该更快,对吗

我试着看看mysql的性能是否有什么不同:

但这出乎我的意料,为什么第二个更快?我认为通过外部连接一个较小的表,查询会更快

我的想法来自:

第节:

尽可能将谓词推送到外部联接子句中
尽可能为不同的表复制常量条件

不管DB引擎如何,通常情况下,Where子句中的条件应该在连接之前首先执行,但我假设它意味着内部连接,而不是外部连接。因为某些条件只能在外部联接之后执行

这根本不是事实。SQL是一种描述性语言。它没有指定如何执行查询。它只指定结果集的外观。SQL编译器/优化器确定实际的处理步骤,以满足查询描述的要求

就语义而言,
FROM
子句是第一个被“评估”的子句。因此,
FROM
WHERE
子句之前进行逻辑处理

你问题的其余部分也同样被误导了。
where
子句中的比较逻辑,例如:

from s left join
     t
    on s.series_id = t.series_id and t.series_id > 18940000
where t.incomplete = 1
将外部联接转换为内部联接。因此,逻辑与您所认为的不同

不管DB引擎如何,通常情况下,Where子句中的条件应该在连接之前首先执行,但我假设它意味着内部连接,而不是外部连接。因为某些条件只能在外部联接之后执行

这根本不是事实。SQL是一种描述性语言。它没有指定如何执行查询。它只指定结果集的外观。SQL编译器/优化器确定实际的处理步骤,以满足查询描述的要求

就语义而言,
FROM
子句是第一个被“评估”的子句。因此,
FROM
WHERE
子句之前进行逻辑处理

你问题的其余部分也同样被误导了。
where
子句中的比较逻辑,例如:

from s left join
     t
    on s.series_id = t.series_id and t.series_id > 18940000
where t.incomplete = 1

将外部联接转换为内部联接。因此,逻辑与你所想的不同。

正如戈登·林道夫所指出的,这不是真的,你的朋友完全错了

我只想添加一些开发者,他们喜欢像对待他们的交易语言(C++、VB、Java)一样思考SQL,但这些都是过程性/命令式语言。 当您编写SQL代码时,您处于另一个范例中。您只是在描述要应用于数据集的函数

让我们举一个你自己的例子:

Select a.*, b.* 
From A a
Left outer join B on a.id = b.id 
Where b.id is NULL;
如果
a.Id
b.Id
不是空列

它在语义上等于

Select a.*, null, ..., null
From A a
where not exists (select * from B b where b.Id = a.Id)
现在试着运行这些查询和配置文件。 在大多数DBMS中,我可以期望两个查询以完全相同的方式运行

这是因为引擎决定如何在数据集上实现“函数”

注:上述示例在集合数学中等效为:

给我集合A减去A和B的交点

引擎可以决定如何实现查询,因为它们有一些技巧。 它有关于您的表、索引等的度量,并且可以使用它,例如,以您编写的不同顺序“创建联接”

今天的IMHO引擎非常擅长找到实现您描述的功能的最佳方法,很少需要查询提示。 当然,您可以以过于复杂的方式结束对函数的描述,从而影响引擎决定如何运行它。
更好地描述函数、集合和管理索引的艺术就是我们所说的查询tunning。

正如Gordon Lindolf指出的那样,这不是真的,你的朋友完全错了

我只想添加一些开发者,他们喜欢像对待他们的交易语言(C++、VB、Java)一样思考SQL,但这些都是过程性/命令式语言。 当您编写SQL代码时,您处于另一个范例中。您只是在描述要应用于数据集的函数

让我们举一个你自己的例子:

Select a.*, b.* 
From A a
Left outer join B on a.id = b.id 
Where b.id is NULL;
如果
a.Id
b.Id
不是空列

它在语义上等于

Select a.*, null, ..., null
From A a
where not exists (select * from B b where b.Id = a.Id)
现在试着运行这些查询和配置文件。 在大多数DBMS中,我可以期望两个查询以完全相同的方式运行

这是因为引擎决定如何在数据集上实现“函数”

注:上述示例在集合数学中等效为:

给我集合A减去A和B的交点

引擎可以决定如何实现您的查询,因为它们在其下面有一些技巧