【问题标题】:Database Buffer for Nested SQL statement嵌套 SQL 语句的数据库缓冲区
【发布时间】:2014-08-02 09:02:33
【问题描述】:

假设我有一个关系 Employee(...) ,它存储员工的信息,包括 id、姓名、薪水等。现在我想找到薪水大于所有员工平均薪水的所有员工。于是我写了如下SQL:

SELECT *
FROM employee
WHERE salary > (SELECT AVERAGE(salary) FROM employee)

一个问题在我脑海中反复出现是:嵌套的 SELECT 注释是否会被执行,以便对 Employee 关系的每个元组进行比较(即,如果我们在 Employee 中有 100 万个元组,那么这个嵌套块将被执行 100 万次),或者它只是执行了几次,然后结果将被缓冲以进一步比较更多的元组?

【问题讨论】:

    标签: sql performance query-optimization


    【解决方案1】:

    SQL 语言是一种你告诉系统你想要什么,而不是如何去做,然后由特定数据库系统的优化器来尝试找到一种有效的方法。

    大多数健全的数据库系统会观察到子查询不以任何方式依赖外部查询(它是不相关的),因此只会运行一次子查询。


    另一方面,如果您的查询如下所示:

    SELECT *
    FROM employee e1
    WHERE salary > (SELECT AVERAGE(e2.salary) FROM employee e2
                    where e2.start_date < e1.start_date)
    

    也就是说,“找到所有薪水高于所有在他们之前开始工作的员工的平均工资的员工”——现在我们有了一个相关的子查询。优化器可能仍然能够制定一些巧妙的策略来避免做太多工作1,但现在您的工作量可能会有所不同 - 这在很大程度上取决于您的特定数据库产品。

    1我们可以按start_date 的升序扫描表一次,并维护两个变量,一个是看到的行数的计数,一个是工资的总和。在任何特定行上,我们可以使用这些变量来计算迄今为止的平均值,然后将其与当前行的薪水进行比较,以决定是否应该发放。然后将薪水加到总和中,并将计数加 1,然后继续下一行。有没有数据库产品真的做了这样的优化,我不知道。

    【讨论】:

    • 非常感谢!我只是对这件事感到好奇,因为我的老师解释说,在这个查询中,每次都必须为每个元组执行嵌套。也许,他在这里犯了一个小错误。 @Damien_The_Unbeliever
    • @DucCuong -在一般中,如果您不是在讨论特定的数据库产品,我会说老师是不正确的-如果查询与您在你的问题,不像我添加到我的答案中的例子。
    猜你喜欢
    • 2018-07-03
    • 1970-01-01
    • 2011-03-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-04-20
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多