通过多重连接提高最大 n 的性能

Posted

技术标签:

【中文标题】通过多重连接提高最大 n 的性能【英文标题】:Improve performance on greatest n with multiple join 【发布时间】:2021-12-05 18:13:33 【问题描述】:

所以我在玩一些 sql 索引,看看我是否可以提高我的 sql 性能。我正在使用employees表https://github.com/datacharmer/test_db中的数据,并转储employees.sql。

查了一下结构后,我的问题是我如何获得最高薪水的 10 个人以及标题是什么。我想出了一些解决方案。

select e.emp_no, e.first_name, e.last_name, e.gender, salaries.salary, titles.title from employees e
inner join ( 
    select s.emp_no, s.salary from salaries as s  
    left outer join salaries as s2
    on s.emp_no = s2.emp_no 
    and s.salary < s2.salary
    where s2.emp_no is null
) salaries on salaries.emp_no = e.emp_no 
inner join (
    select t.emp_no, t.title from titles as t  
    left outer join titles as t2
    on t.emp_no = t2.emp_no 
    and t.to_date < t2.to_date 
    where t2.emp_no is null
) titles on titles.emp_no = e.emp_no
order by salaries.salary desc
limit 10;

基本上,由于employees 的头衔和薪水是一对多的关系,我必须将salariestitles 按其最新的最大值分组,对于salaries,它将是salary 列,对于titles 将是 to_date 列。

SQL 运行良好,但速度太慢了~ 即使创建了一些索引。

create index salary_emp_no_index on salaries (salary, emp_no);
create unique index emp_first_last_name_index on employees (emp_no, first_name, last_name, gender);
create index titles_emp_title on titles (emp_no, title)

我在这里做错了什么?还有改进的余地吗?

编辑(添加 sqlfiddle)

http://sqlfiddle.com/#!9/72111d/1

【问题讨论】:

您的问题标题和标签显示每组最大 n,但您的问题文本几乎是每组最大 n,不是。你真正想问的是什么? 如果您在问题本身中包含创建表和插入与您的问题相关的特定表的示例数据(作为文本,而不是图像),您更有可能得到答案 我在这里列出了最佳技术:mysql.rjweb.org/doc.php/groupwise_max 啊,是的,对不起,我的意思是最伟大的 N。@ysth 【参考方案1】:

两点:

首先,要获得每个emp_no的最高薪水并限制为10,您根本不需要子查询或join,您可以简单地做(未经测试):

select emp_no, max(salary) max_salary
from salaries
group by emp_no
order by max_salary desc
limit 10

其次,您只需要那些(最多)10 名员工的头衔,因此将您的最高薪水查询用作 cte 或子查询,并且只查找这些员工的头衔,这应该会快得多。此外,您可以使用https://***.com/a/15422121/17389 中的方法避免标题上的自加入。

【讨论】:

以上是关于通过多重连接提高最大 n 的性能的主要内容,如果未能解决你的问题,请参考以下文章

如何使用 Eloquent ORM 进行多重连接查询

http2.0和http1.1的区别

腾讯云服务器只要操作后台老是网络重连

Netty 实现心跳机制与断线重连

Laravel 多重计数多重连接

WebSocket 断线重连引入心跳的原因