查询执行中涉及的步骤

8oomwypt  于 2021-06-20  发布在  Mysql
关注(0)|答案(3)|浏览(285)

考虑下表:

name     salary
-----   --------
a       100
b       200
c       300
d       300   -- note the duplicate max

现在我们要使用以下查询计算第二个最高工资:

SELECT max(salary)
FROM emptable
WHERE salary < (SELECT max(salary)
                FROM emptable);

那么mysql将如何确定这个查询的结果呢?例如,我假设它首先在 where 条款并确定最高工资,称之为 M1 (这将是 400 )并将其存储在某个变量中。然后,它将从原始表中找到最大工资 400 ,但不满足中的约束 where 条款(即与 M1 ). 现在它将复制原始表,其中tuple包含( 400 )值被删除,因为它不满足约束,并重复此过程,直到找到所需的结果。
很可能我错了,但我写上面的过程只是为了澄清我的问题。

093gszye

093gszye1#

查询优化器可以自由地进行任何优化(基于索引/数据分布/…)。您应该始终检查实际执行计划:

explain
SELECT max(salary)
FROM emptable
WHERE salary < (SELECT max(salary)
                FROM emptable);

输出:

┌────┬─────────────┬──────────┬──────┬───────────────┬──────┬─────────┬──────┬──────┬─────────────┐
│ id │ select_type │  table   │ type │ possible_keys │ key  │ key_len │ ref  │ rows │    Extra    │
├────┼─────────────┼──────────┼──────┼───────────────┼──────┼─────────┼──────┼──────┼─────────────┤
│  1 │ PRIMARY     │ emptable │ ALL  │ null          │ null │ null    │ null │    4 │ Using where │
│  2 │ SUBQUERY    │ emptable │ ALL  │ null          │ null │ null    │ null │    4 │             │
└────┴─────────────┴──────────┴──────┴───────────────┴──────┴─────────┴──────┴──────┴─────────────┘

INDEX 工资方面:

create index idx ON emptable(salary);

┌────┬─────────────┬───────┬──────┬───────────────┬──────┬─────────┬──────┬──────┬──────────────────────────────┐
│ id │ select_type │ table │ type │ possible_keys │ key  │ key_len │ ref  │ rows │            Extra             │
├────┼─────────────┼───────┼──────┼───────────────┼──────┼─────────┼──────┼──────┼──────────────────────────────┤
│  1 │ PRIMARY     │ null  │ null │ null          │ null │ null    │ null │ null │ Select tables optimized away │
│  2 │ SUBQUERY    │ null  │ null │ null          │ null │ null    │ null │ null │ Select tables optimized away │
└────┴─────────────┴───────┴──────┴───────────────┴──────┴─────────┴──────┴──────┴──────────────────────────────┘

dbfiddle演示

lf5gs5x2

lf5gs5x22#

出现在 WHERE 子句与外部查询不相关,因此优化器很可能只计算一次,然后将结果缓存到某个地方。在此之后,max值将用于过滤一个或多个具有该max值的记录。然后就是一个典型的max查询。为了证实这一点,或者找到一些我可能错过的东西,你可以跑 EXPLAIN 你的问题。
顺便说一下,您也可以使用 LIMIT 以及 OFFSET :

SELECT DISTINCT salary
FROM emptable
ORDER BY salary DESC
LIMIT 1
OFFSET 1;

这还应返回排名第二的薪资(即,对于同一薪资中有多个是可靠的)。但是这种方法很容易找到工资的任何等级,而子查询方法扩展得不好。

ccgok5k5

ccgok5k53#

你想要“密集排名”。
以下公式可能会得到更好的优化,因此如果您有一个较大的表,则会更快:

SELECT salary
    FROM emptable
    WHERE salary < (SELECT max(salary)
                    FROM emptable)
    ORDER BY salary DESC
    LIMIT 1,1;

它需要

INDEX(salary)

相关问题