Sql 其中(隐式内部联接)与显式内部联接-它会影响索引吗?

Sql 其中(隐式内部联接)与显式内部联接-它会影响索引吗?,sql,indexing,inner-join,implicit,Sql,Indexing,Inner Join,Implicit,用于查询 SELECT * from table_a, b WHERE table_a.id = b.id AND table_a.status ='success' 或 不知何故,我倾向于在表a上为顶级表单创建一个索引(id、状态) 而我对底部形式的自然倾向是创建两个独立的指数, 表a上的id和状态 这两个查询实际上是相同的,对吗?你能用同样的方法为两者编制索引吗? 您将如何索引表_a(假设这是系统中唯一存在的查询,以避免其他考虑)?一个或两个索引?应优化这两个查询以执行相同的方式;但是

用于查询

SELECT * from table_a, b WHERE table_a.id = b.id AND table_a.status ='success'  

不知何故,我倾向于在表a上为顶级表单创建一个索引(id、状态)
而我对底部形式的自然倾向是创建两个独立的指数, 表a上的id和状态

这两个查询实际上是相同的,对吗?你能用同样的方法为两者编制索引吗?

您将如何索引表_a(假设这是系统中唯一存在的查询,以避免其他考虑)?一个或两个索引?

应优化这两个查询以执行相同的方式;但是,联接语法符合ANSI标准,旧版本应弃用。就索引使用而言,您只需要触摸一次表(索引)。您使用的RDBMS和表格设计将确定是否需要在覆盖索引中包含主键(假设在您的示例中ID表示主键)的细节。此外,选择*可能包括,也可能不包括;最好使用特定的列名。

传统样式和SQL 92样式的内部联接在语义上是等效的,大多数DBMS都会对它们进行相同的处理(例如Oracle)。他们将对两种形式使用相同的执行计划(尽管如此,这取决于实施,并且没有任何标准的保证)

因此,索引在两种形式中的使用方式也是相同的

与您使用的语法无关,适当的索引策略取决于实现:一些DBM(如Postgres)通常更喜欢单列索引,并且可以非常有效地组合它们,而其他DBM(如Oracle)则可以从组合(甚至覆盖)索引中获得更大的优势(当然,这两种形式都适用于两个DBM)

关于示例的语法,第二个WHERE子句的位置让我有点吃惊

在大多数DBMS中,以下两个查询的处理方式相同:

SELECT * FROM table_a, b WHERE table_a.id = b.id AND table_a.status ='success'  

但是,您的第二个查询将WHERE子句移到FROM子句中,在我看来这不是有效的SQL

快速检查

SELECT * from a WHERE table_a.status ='success' JOIN b ON table_a.id = b.id

确认:MySQL 5.5、Postgres 9.3和Oracle11g都会产生语法错误。

您排除了其他查询,但仍然存在一些问题:特别是关于数据分布的问题。例如,如何将表a.status='success'与表b的表大小进行比较?根据优化器的估计,必须做出两个重要决策:

  • 使用哪种联接算法(嵌套循环;哈希或排序/合并)
  • 处理表格的顺序是什么
  • 不幸的是,这些决策会影响索引(并且会受到索引的影响!)

    示例:考虑只有一行,Table。a状态=“成功”。然后在表a.status上有一个索引就可以快速找到该行。接下来,我们希望在表_b.id上有一个索引,以便使用嵌套循环联接快速查找相应的行。考虑到您选择了*在这些索引中包含额外的列没有任何意义(不考虑系统中的任何其他查询)

    但是现在想象一下,在表a.status上没有索引,而在表a.id上有索引,并且这个表与表b相比是巨大的。为了演示,我们假设表_b只有一行(当然是极端情况)。现在最好转到表_b,获取所有行(仅一行),而不是使用索引从表_a中获取相应的行。您看到索引如何影响联接顺序了吗?(对于本例中的嵌套循环联接)

    这只是事物如何相互作用的一个简单例子。大多数数据库都有三种连接算法可供选择(MySQL除外)

    如果创建上述三个索引并查看数据库执行联接的方式(解释计划),您将注意到,对于为查询选择的特定联接算法/联接顺序,其中一个或两个索引仍然未使用。理论上,你可以删除这些索引。但是,请记住,优化器是根据可用的统计信息做出决策的,优化器的估计可能是错误的


    您可以在我的网站上找到有关索引联接的更多信息:

    您真的希望在联接子句之前使用WHERE子句吗?看起来第一部分是一个子查询,它的结果应该被连接起来,但是我错过了括号。Fabian,我想你是对的。第二个查询缺少括号。但这是否等同于将where放在末尾?请不要将任一表中的id字段视为主键。就我的问题而言,这只是一个正规场。我应该用另一个名字,比如“foo”,我已经把我的解释移到了下面的答案中。ANSI 89(“隐式”)连接语法并没有被弃用。
    SELECT * FROM a JOIN b ON table_a.id = b.id WHERE table_a.status ='success' 
    
    SELECT * from a WHERE table_a.status ='success' JOIN b ON table_a.id = b.id