Sql 执行嵌套查询的次数

Sql 执行嵌套查询的次数,sql,database-agnostic,Sql,Database Agnostic,此嵌套子查询将执行多少次 SELECT CID, CNAME FROM CUSTOMER WHERE EXISTS ( SELECT CID FROM RENTALS WHERE CUSTOMER.CID = RENTALS.CID AND PICKUP = 'CARY' ) 这是一个理论问题,也就是说,它可以在我的书中找到。提供的答案是6,但我不明白为什么会这样 好的,

此嵌套子查询将执行多少次

SELECT CID, CNAME 
  FROM CUSTOMER
 WHERE EXISTS ( SELECT CID 
                  FROM RENTALS 
                 WHERE CUSTOMER.CID = RENTALS.CID 
                   AND PICKUP = 'CARY' )
这是一个理论问题,也就是说,它可以在我的书中找到。提供的答案是6,但我不明白为什么会这样



好的,我认为这本书本身有一些问题。我会翻阅这本书,也许稍后会问这个问题。

查询不会以这种方式执行。查询计划器将把它转换成这样的东西,它将针对另一个查询的结果运行一个查询,而不是反复运行子查询

查询的查询计划很可能与执行左联接并检查现有记录的查询的查询计划相同:

select c.CID, c.CNAME
from CUSTOMER c
left join RENTALS r on c.CID = r.CID and r.PICKUP = 'CARY'
where r.CID is not null

查询不会以这种方式执行。查询计划器将把它转换成这样的东西,它将针对另一个查询的结果运行一个查询,而不是反复运行子查询

查询的查询计划很可能与执行左联接并检查现有记录的查询的查询计划相同:

select c.CID, c.CNAME
from CUSTOMER c
left join RENTALS r on c.CID = r.CID and r.PICKUP = 'CARY'
where r.CID is not null
这个问题没有正确的理论答案。智能查询优化器可以将查询转换为联接:

SELECT CID, CNAME
FROM Customer
LEFT JOIN (SELECT DISTINCT CID FROM Rentals WHERE PICKUP = 'CARY') as Rentals
ON Customer.CID = Rentals.CID
WHERE Rentals.CID IS NOT NULL
现在子查询只执行一次。

这个问题没有正确的理论答案。智能查询优化器可以将查询转换为联接:

SELECT CID, CNAME
FROM Customer
LEFT JOIN (SELECT DISTINCT CID FROM Rentals WHERE PICKUP = 'CARY') as Rentals
ON Customer.CID = Rentals.CID
WHERE Rentals.CID IS NOT NULL

现在子查询只执行一次。

正如其他人所指出的,这个相关的子查询可以重写为联接,但这还不完全是问题的全部,因为未转换的EXISTS的执行计划看起来很像联接。所以这实际上不是一个语法问题,而是一个查询优化问题

EXISTS实际上只是“连接到此数据集,但即使有1000000个匹配项,也只连接到其中的一行”的语法简写,或者也被称为

因此,EXISTS谓词针对相关或不相关子查询所需的半连接可以通过多种方式实现,这在很大程度上取决于两个表中的数字或记录

如果您假设客户估计只有一行,而乐观主义者估计租金中有数千行皮卡=卡里,那么乐观主义者很可能从客户表中读取该行,并对租金表执行单个查找

如果估计有一百万个客户,并且RENTALS表中只有一行,那么该执行计划将是疯狂的——乐观主义者可以通过引导RENTALS表并对照CUSTOMER表查找要返回的单行来反转联接。在这种情况下,可以说根本没有执行子查询

在这两个极端之间,还有各种其他优化。例如,将RENTAL.CID列的唯一值构建到内存中的哈希表中,其中PICKUP='CARY'和full扫描CUSTOMER表以探测每一行的哈希表,这将是一个哈希半联接。同样,不执行可识别的子查询。(Barmer建议的查询重写可能会导致这种计划,但也可能会限制乐观主义者看到适合其他数据分布和基数的其他计划)

因此,正如其他答案所说,这个问题确实没有意义,因为我认为这里有两个重要的教训:

  • 许多不同的SQL语句可以导致相同的执行计划,而单个SQL语句也可以导致多个执行计划
  • 您应该编写以语法方式表示所需结果的查询,而不是一般地抢占和限制查询优化人员的选择
  • 第二点很重要,因为它反对一些开发人员为了提供自己的优化而避免编写相关子查询(尤其是存在或不存在的子查询)的本能。特别是,考虑到正确/错误的数据分布,用外部联接替换EXISTS可能是非常不理想的

    为了直接回答这个问题,我想说:

    • 0
    • 一,
    • 然而,客户中有许多行
    • 可能是别的

    正如其他人所指出的,这个相关子查询可以重写为联接,但这还不完全是问题的全部,因为未转换的EXISTS的执行计划看起来很像联接。所以这实际上不是一个语法问题,而是一个查询优化问题

    EXISTS实际上只是“连接到此数据集,但即使有1000000个匹配项,也只连接到其中的一行”的语法简写,或者也被称为

    因此,EXISTS谓词针对相关或不相关子查询所需的半连接可以通过多种方式实现,这在很大程度上取决于两个表中的数字或记录

    如果您假设客户估计只有一行,而乐观主义者估计租金中有数千行皮卡=卡里,那么乐观主义者很可能从客户表中读取该行,并对租金表执行单个查找

    如果估计有一百万个客户,并且RENTALS表中只有一行,那么该执行计划将是疯狂的——乐观主义者可以通过引导RENTALS表并对照CUSTOMER表查找要返回的单行来反转联接。在这种情况下,可以说根本没有执行子查询

    在这两个极端之间,还有各种其他优化。例如,将RENTAL.CID列的唯一值构建到内存中的哈希表中,其中PICKUP='CARY'和full扫描CUSTOMER表以探测每一行的哈希表,这将是一个哈希半联接。同样,不执行可识别的子查询。(Barmer建议的查询重写可能会