查询执行涉及的步骤

时间:2018-07-15 10:56:47

标签: mysql sql performance greatest-n-per-group

请考虑下表:

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进行比较)。现在,它将复制原始表,并删除包含此(400)值的元组,因为它不满足约束条件,并重复此过程,直到找到所需的结果。

很可能我错了,但是我写了以上过程只是为了澄清我的问题。

3 个答案:

答案 0 :(得分:1)

出现在WHERE子句中的子查询与外部查询不相关,因此优化程序很可能会对其进行一次计算,然后将结果缓存到某个位置。此后,最大值将用于过滤掉具有该最大值的一个或多个记录。然后,这只是一个典型的最大查询。为了确认这一点,或者发现我可能错过的东西,您可以对查询运行EXPLAIN

顺便说一句,您也可以使用LIMITOFFSET编写此查询:

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

这还应该返回排名第二高的薪水(即,对于相同薪水中有不止一个薪水是稳健的)。但是这种方法可以很容易地找到薪水的任何等级,而子查询方法却不能很好地扩展。

答案 1 :(得分:0)

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

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 Demo

答案 2 :(得分:0)

您想要“密集排名”。

以下公式 可能会得到更好的优化,因此如果您的表很大,则会更快:

chunkSize

这需要

bytesRead