涨知识了!阿里规定超过三张表禁止join,为啥?

阿里开发规范禁止超过三张表 join,我们如何规避? 超过三张表的 JOIN 是否合适取决于具体的场景和需求。 阅读详情

点击上方“菜鸟学Python”,选择“星标”公众号

重磅干货,第一时间送达

作者:e71hao

blog.itpub.net/30393770/viewspace-2650450/


一、 问题提出

《阿里巴巴JAVA开发手册》里面写超过三张表禁止join,这是为什么?


二、问题分析

对这个结论,你是否有怀疑呢?也不知道是哪位先哲说的不要人云亦云,今天我设计sql,来验证这个结论。(实验没有从代码角度分析,目前达不到。可以把mysql当一个黑盒,使用角度来验证这个结论) 验证结论的时候,会有很多发现,各位往后看。


三、 实验环境

vmware10+centos7.4+mysql5.7.22

  • centos7内存4.5G,4核,50G硬盘。

  • mysql配置为2G,特别说明硬盘是SSD。

四、我概述下我的实验

有4张表,student学生表,teacher老师表,course课程表,sc中间关系表,记录了学生选修课程以及分数。具体sql脚本,看文章结尾,我附上。中间我自己写了造数据的脚本,也在结尾。

实验是为解决一个问题的:查询选修“tname553”老师所授课程的学生中,成绩最高的学生姓名及其成绩。

查询sql是:

select Student.Sname,course.cname,score 
    from Student,SC,Course ,Teacher 
    where Student.s_id=SC.s_id and SC.c_id=Course.c_id  and sc.t_id=teacher.t_id 
    and Teacher.Tname='tname553' 
    and SC.score=(select max(score)from SC where sc.t_id=teacher.t_Id);

我来分析一下这个语句:4张表等值join,还有一个子查询。算是比较简单的sql语句了(相比ERP动就10张表的哦,已经很简单了)。我 还会分解这个语句成3个简

单的sql:

 select max(score)  from SC ,Teacher where sc.t_id=teacher.t_Id and Teacher.Tname='tname553';
   select sc.t_id,sc.s_id,score   from SC ,Teacher 
   where sc.t_id=teacher.t_Id 
   and score=590  
   and Teacher.Tname='tname553';
    select Student.Sname,course.cname,score 
    from Student,SC ,course
    where Student.s_id=SC.s_id and  sc.s_id in (20769800,48525000,26280200) and course.c_id = sc.c_id;

我来分析下:第一句,就是查询最高分,得到最高分590分。第二句就是查询出最高分的学生id,得到

20769800,48525000,26280200

第三句就是查询出学生名字和分数。这样这3个语句的就可以查询出来 成绩最高的学生姓名及其成绩 。

接下来我会分别造数据:1千万选课记录(一个学生选修2门课),造500万学生,100万老师(一个老师带5个学生,挺高端的吧),1000门课,。用上面查询语句查询。其中sc表我测试了下有索引和没有索引情况,具体见下表。

再接下来,我会造1亿选课记录(一个学生选修2门课),5000万学生,1000万老师,1000门课。然后分别执行上述语句。最后我会在oracle数据库上执行上述语句。

五、下面两张表是测试结果


六、仔细看上表,可以发现:

1).步骤3.1没有在连接键上加索引,查询很慢,说明:“多表关联查询时,保证被关联的字段需要有索引”;

2).步骤6.1,6.2,6.3,换成简单sql,在数据量1亿以上, 查询时间还能勉强接受。此时说明mysql查询有些吃力了,但是仍然嫩查询出来。

3).步骤5.1,mysql查询不出来,4表连接,对我本机mysql来说,1.5亿数据超过极限了(我调优过这个SQL,执行计划和索引都走了,没有问题,show profile显示在sending data.这个问题另外文章详谈)。

4).对比1.1 和5.1 步骤sql查询,4表连接,对我本机mysql来说 ,1.5千万数据查询很流利,是一个mysql数据量流利分水岭。(这个只是现象,不太准确,需要同时计算表的容量)。

5).步骤5.1对比6.1,6.2,6.3,多表join对mysql来说,处理有些吃力。

6).超过三张表禁止join,这个规则是针对mysql来说的。后续会看到我用同样机器,同样数据量,同样内存,可以完美计算 1.5亿数据量join。针对这样一个规则,对开发来说 ,需要把一些逻辑放到应用层去查询。

总结: 这个规则 超过三张表禁止join ,由于数据量太大的时候,mysql根本查询不出来,导致阿里出了这样一个规定。(其实如果表数据量少,10张表也不成问题,你自己可以试试)而我们公司支付系统朝着大规模高并发目标设计的,所以,遵循这个规定。

在业务层面来讲,写简单sql,把更多逻辑放到应用层,我的需求我会更了解,在应用层实现特定的join也容易得多。

七、让我们来看看oracle数据库的优秀表现:

看步骤7.1,就是没有索引,join表很多的情况下,oracle仍然26秒查询出结果来。所以我会说mysql的join很弱。那么问题来了,为什么现在使用很多人使用mysql呢?这是另外一个问题,我会另外说下我的思考。

看完本篇文章,另外我还附加赠送,所谓搂草打兔子。就是快速造数据。你可以自己先写脚本造数据,看看我是怎么造数据的,就知道我的技巧了。

八、附上部分截图


九、附上sql语句和造数据脚本

use stu;
drop table if exists student;
create table student 
  (  s_id int(11) not null auto_increment ,
     sno    int(11), 
     sname varchar(50), 
     sage  int(11), 
     ssex  varchar(8) ,
     father_id int(11),
      mather_id int(11),
      note varchar(500),
     primary key (s_id),
   unique key uk_sno (sno)
  ) engine=innodb default charset=utf8mb4;
truncate table student;
  delimiter $$
drop function if exists   insert_student_data $$
create function insert_student_data()
 returns  int deterministic
    begin
    declare  i int;
      set i=1;
      while  i<50000000 do 
      insert into student  values(i ,i, concat('name',i),i,case when floor(rand()*10)%2=0 then 'f' else 'm' end,floor(rand()*100000),floor(rand()*1000000),concat('note',i) );
      set i=i+1;
      end while;
      return 1;
    end$$
delimiter ;    
select  insert_student_data();
select count(*) from student;
use stu;
create table course 
  ( 
     c_id int(11) not null auto_increment ,
     cname varchar(50)
     note varchar(500), primary key (c_id)
  )  engine=innodb default charset=utf8mb4;
truncate table course;
  delimiter $$
drop function if exists   insert_course_data $$
create function insert_course_data()
 returns  int deterministic
    begin
    declare  i int;
      set i=1;
      while  i<=1000 do 
      insert into course  values(i , concat('course',i),floor(rand()*1000),concat('note',i) );
      set i=i+1;
      end while;
      return 1;
    end$$
delimiter ;    
select  insert_course_data();
select count(*) from course;
use stu;
drop table if exists sc;
create table sc 
  ( 
     s_id    int(11), 
     c_id    int(11), 
     t_id    int(11),
     score int(11) 
  )  engine=innodb default charset=utf8mb4;
truncate table sc;
  delimiter $$
drop function if exists   insert_sc_data $$
create function insert_sc_data()
 returns  int deterministic
    begin
    declare  i int;
      set i=1;
      while  i<=50000000 do 
      insert into sc  values( i,floor(rand()*1000),floor(rand()*10000000),floor(rand()*750)) ;
      set i=i+1;
      end while;
      return 1;
    end$$
delimiter ;    
select  insert_sc_data();
commit;
select  insert_sc_data();
commit;
create index idx_s_id  on sc(s_id)   ; 
create index idx_t_id  on sc(t_id)   ; 
create index idx_c_id  on sc(c_id)   ; 
select count(*) from sc;
use stu;
drop table if exists teacher;
create table teacher 
  ( 
    t_id  int(11) not null auto_increment ,
     tname varchar(50) ,
     note varchar(500),primary key (t_id)
  )  engine=innodb default charset=utf8mb4;

  truncate table teacher;
  delimiter $$
drop function if exists   insert_teacher_data $$
create function insert_teacher_data()
 returns  int deterministic
    begin
    declare  i int;
      set i=1;
      while  i<=10000000 do 
      insert into teacher  values(i , concat('tname',i),concat('note',i) );
      set i=i+1;
      end while;
      return 1;
    end$$
delimiter ;    
select  insert_teacher_data();
commit;
select count(*) from teacher;

这个是oracle的测试和造数据脚本

create tablespace scott_data  datafile  '/home/oracle/oracle_space/sitpay1/scott_data.dbf'  size 1024m autoextend on; 
create tablespace scott_index   datafile  '/home/oracle/oracle_space/sitpay1/scott_index.dbf'  size 64m  autoextend on; 
create temporary tablespace scott_temp  tempfile  '/home/oracle/oracle_space/sitpay1/scott_temp.dbf'  size 64m autoextend on; 
drop user  scott cascade;
create user  scott  identified by  tiger  default tablespace scott_data  temporary tablespace scott_temp  ;
grant resource,connect,dba to  scott;
drop table student;
create table student  
  (  s_id number(11) ,
     sno    number(11) , 
     sname varchar2(50), 
     sage  number(11), 
     ssex  varchar2(8) ,
     father_id number(11),
      mather_id number(11),
      note varchar2(500)
  ) nologging;
truncate table student;
create or replace procedure insert_student_data
 is 
   q number(11);
    begin 
     q:=0;
      for i in  1..50 loop 
      insert /*+append*/ into student   select rownum+q as s_id,rownum+q  as sno, concat('sutdent',rownum+q ) as sname,floor(dbms_random.value(1,100)) as sage,'f' as ssex,rownum+q  as father_id,rownum+q  as mather_id,concat('note',rownum+q ) as note from dual connect by level<=1000000;
      q:=q+1000000;
      commit;
      end loop; 
end insert_student_data;
/
call insert_student_data();
alter table student  add constraint  pk_student primary key (s_id);
commit;    
select count(*) from student;
create table course 
  ( 
     c_id number(11) primary key,
     cname varchar2(50),
     note varchar2(500) 
  )  ;
truncate table course;
 create or replace procedure insert_course_data
 is 
   q number(11);
    begin 

      for i in  1..1000 loop 
      insert /*+append*/ into course  values(i , concat('name',i),concat('note',i) );      
      end loop; 
end insert_course_data;
/
call insert_course_data();
commit;    
select count(*) from course;
create table sc 
  ( 
     s_id    number(11), 
     c_id    number(11), 
     t_id    number(11),
     score number(11) 
  ) nologging;
truncate table sc;
 create or replace procedure insert_sc_data
 is 
   q number(11);
    begin 
     q:=0;
      for i in  1..50 loop 
      insert /*+append*/ into sc   select rownum+q as s_id, floor(dbms_random.value(0,1000))  as c_id,floor(dbms_random.value(0,10000000)) t_id,floor(dbms_random.value(0,750)) as score from dual connect by level<=1000000;
      q:=q+1000000;
      commit;
      end loop; 
end insert_sc_data;
/
call insert_sc_data();
create index idx_s_id  on sc(s_id)   ; 
create index idx_t_id  on sc(t_id)   ; 
create index idx_c_id  on sc(c_id)   ; 
select count(*) from sc;
create table teacher 
  ( 
    t_id  number(11) ,
     tname varchar2(50) ,
     note varchar2(500)
  )nologging ;
    truncate table teacher;
create or replace procedure insert_teacher_data
 is 
   q number(11);
    begin 
     q:=0;
      for i in  1..10 loop 
      insert /*+append*/ into teacher   select rownum+q as t_id, concat('teacher',rownum+q ) as tname,concat('note',rownum+q ) as note from dual connect by level<=1000000;
      q:=q+1000000;
      commit;
      end loop; 
end insert_teacher_data;
/
call insert_teacher_data();
alter table teacher  add constraint  pk_teacher primary key (t_id);
select count(*) from teacher;
end

近期八大热门:
发现一个舔狗福利!这个Python爬虫神器太爽了,自动下载妹子图片!
盗墓热再起!我爬取了6万条《重启之极海听雷》的评论,发现了这些秘密
用Python一键生成炫酷九宫格图片,火了朋友圈
菜鸟也疯狂!8分钟用Python做一个酷炫的家庭随手记
Github获8300星!用Python开发的一个命令行的网易云音乐
一道Python面试题,硬是没憋出来,最后憋出一身汗!卧槽!Pdf转Word用Python轻松搞定!教你6招,不错的Python代码技巧!
由菜鸟学Python原班人马打造的公众号:菜鸟编程大本营,现已正式上线!每个程序员都是从菜鸟开始成长起来的,没有人一开始就是程序员高手。菜鸟爱编程,专注于分享趣味的编程技巧,不限于Java, Python ,Go, Javascript等语言,让菜鸟爱上编程,进阶成为高手。

我们在B站上录制了大量的视频,欢迎大家交流学习

1). 花木兰到底好看不,我用Python爬取上万条评论

2). 80行Python代码一键轻松把Pdf转word

3). 用Python一键把图片转漫画

4). 再见付费软件,我用70行Python搞定

5). 用Python分析“青春有你2”

6). 用Python三步制作短视频

7). 用Python实现一个弹球游戏

8). 10行代码实现美图秀秀

9). 50行代码用Python批量做海量小姐姐素描图

点这里,直达菜鸟B站
阿里规定超过三张表禁止JOIN,为啥呢? 《阿里巴巴JAVA开发手册》里面写超过三张表禁止join,这是为什么? 二、问题分析 对这个结论,你是否有怀疑呢?也不知道是哪位先哲说的不要人云亦云,今天我设计sql,来验证这个结论。(实验没有从代码角度分析,目前达不到。可以把mysql当一个黑盒,使用角度来验证这个结论) 验证结论的时候,会有很多发现,各位往后看。 三、 实验环境 vmware10+centos7.4+mysql5.7.22 ,centos7内存4.5G,4核,50G硬盘。mysql配置为2G,特别说明硬盘是SSD。 四、概 阅读详情

相关推荐

【NIFI】实现HANA->ORACLE数据同步

实现 HANA->ORACLE数据同步。

weixin_43159039的博客 1510

【MySQL】拓展:为什么不要超过三表关联查询?

其实阿里有一个数据库的规范,那就是禁止三表以上的关联查询。那么目前为止我所接触过的一些项目,也的确是差不多的,有部分可以放宽到四表查询,但是超过四张表就不允许了,因为的确是会有性能影响的。除非是传统行业,对性能要求不是特别大,那么这个规约可以无所谓。那么绝大多数互联网公司也的确这么做,少数公司不按照这个规范呢也问题不大的。

qq_50446805的博客 1144

STM32F407硬件SPI驱动ADS1220避坑指南:从寄存器读不到数据到采样值异常的完整解决流程

本文详细解析了STM32F407硬件SPI驱动ADS1220的常见问题与解决方案,包括SPI配置、寄存器读取异常、采样值优化等关键环节。通过CubeMX配置技巧和Keil调试经验,帮助开发者快速排查从通信失败到数据异常的各种问题,实现高精度数据采集系统的稳定运行。

weixin_26878995的博客 158

为什么说MySQL单表数据不要超过500万行

个人总结:   1)如果单表容量大(大于2G),但是索引少(只通过主键ID查),性能也不会慢   2)如果数据量大(大于500W),但是索引容量小(都是小字节字段),性能也不会慢   3)所以,单表查询的性能取决于索引的大小(因为会放内存里),而索引的查询速度又受硬件的影响。   4)建议:大表(数据量大、容量大)。先拆成主表(字段多)、detail表(容量高)。主表严格控制索引的质量,detail表只能用主键ID查(后期可以通过主键ID分表)。 以下是正文: 今天,探讨一个有趣的话题:MySQ

3806

转录组PCA分析3大常见误区:数据标准化、离群样本与批次效应处理

本文深入探讨转录组PCA分析中的三大常见误区:数据标准化、离群样本识别与批次效应处理。通过实战案例和R代码演示,揭示如何优化PCA结果以提升生物学解释力,特别关注数据标准化策略的选择和批次校正方法的应用,帮助研究者避免常见陷阱并获得可靠的转录组分析结果。

weixin_28362173的博客 373

【2025最新版】间接平差——以水准网平差为例 (python详细过程版)

水准网间接平差的python代码实现。博客长期更新,本文最新更新时间为:2025年5月20日。

点云侠的博客 1702

为什么禁止超过三张表 join,原理是什么?

概述前段时间在跟其他公司DBA交流时谈到了mysql跟PG之间在多表关联查询上的一些区别,相比之下mysql只有一种表连接类型:嵌套循环连接(nested-loop),不支持排序-合并连接...

独行侠梦的博客 3505

基于改进Unet的多场景水果图像分割与分类研究

本文针对复杂场景下的水果图像分割问题,提出了一种改进Unet模型。通过构建包含8类水果、3种成熟度及多种干扰场景的数据集,采用ResNet50与MobileNetV3作为骨干网络,并在跳跃连接层集成CBAM注意力机制。实验表明,改进模型在测试集上达到91.6%的mIoU,推理速度提升23%,特别在重叠水果和低光照场景表现突出。研究为农业视觉检测提供了有效解决方案。

AI的内部世界的博客 304

大表join大表_阿里开发规范:超过三张表,禁止join骚操作

来源zhihu.com/question/56236190喜马拉雅山脉的钱德拉塔尔湖,印度 (© f9photos)前 言最近在看《阿里巴巴开发手册》,发现一个很有趣的编程规约,即《阿里巴巴开发手册中》第五章第二节第二条中明确规定了:超过三个表禁止 join。需要 join 的字段,数据类型必须绝对一致;多表关联查询时,保证被关联的字段需要有索引。不信你看:这让人突然想起了这张神...

weixin_39713841的博客 2395

cuMotion 入门教程(一)面向机器人学的GPU加速运动生成技术

NVIDIA cuMotion是一款高性能机器人运动生成库,专注于机械操作任务,利用GPU加速技术提升性能。开发者预览版支持运动学/逆运动学、碰撞感知路径规划、轨迹优化等功能,兼容任意自由度机器人。该库提供C++和Python接口,支持从URDF/XRDF文件加载机器人模型,包含世界建模、碰撞检测等工具。教程详细介绍了安装配置、机器人描述加载、运动学计算、世界建模、逆运动学求解以及轨迹优化等核心功能。cuMotion整合了Lula和cuRobo库的技术优势,将成为Isaac ROS的核心组件,适用于工业机器

2506_90492529的博客 2203

【项目解析】2KW 230V 数字逆变器控制系统(二)

【项目解析】 2KW 230V 数字逆变器控制系统(一) 项目的 交流输出电压 并不是单纯一个电压环就能控制好的,而是典型的 双环控制架构:最终占空比控制量会经过计算: 然后写入 单片机 TMM 定时器的比较寄存器 (TMGRA0/TMGRD0/TMGRC1), → 定时器输出互补 PWM, → 驱动 IGBT 全桥, → 经过 LC 滤波形成 230 VAC / 50Hz 的正弦电压。总结交流电压是双环控制的结果:目标/作用:把输出 RMS 电压稳到目标(例如 230 VAC);在母线波动与负载变化下

Naiva的博客 1299

阿里规定超过三张表禁止join,为啥?

点击上方“朱小厮的博客”,选择“设为星标”后台回复”加群“加入公众号专属技术群来源:https://dwz.cn/LuowUpuc最近,在知乎上看到一个有意思的问题,我个...

朱小厮的博客 1万+

Outlook Express 6 (OE6) for Win7/Win8/Win10

英文版 Outlook Express6.0, 兼容Win7/Win10/WinXP,解压就可用。

阿里规定超过三张表禁止join,Why?

一、 问题提出 《阿里巴巴JAVA开发手册》里面写超过三张表禁止join,这是为什么? 二、问题分析 对这个结论,你是否有怀疑呢?也不知道是哪位先哲说的不要人云亦云,今天我设计sql,来验证这个结论。 (实验没有从代码角度分析,目前达不到。可以把mysql当一个黑盒,使用角度来验证这个结论) 验证结论的时候,会有很多发现,各位往后看。 三、 实验环境 vmware10+centos7.4+mysql5.7.22 centos7内存4.5G,4核,50G硬盘。 mysql配置为

Pastxu的小屋 1059

霍尼韦尔SoftMaster使用说明

霍尼韦尔SoftMaster使用说明

老版QQ原生表情gif动态

这是老版的QQ表情,不过全是动态的的,Windows照片查看器是不会动的,可以右击用浏览器打开查看,再说一遍是老版的,只是分享给宁愿用老版也要动态的人。

三张表关联查询统计_阿里规定超过三张表禁止 join,为啥?

点击蓝色“最码农”关注我哟加个“星标”,每天下午18:03,一起学技术作者:e71haoblog.itpub.net/30393770/viewspace-2650450/一、 问题提出《阿里巴巴JAVA开发手册》里面写超过三张表禁止join,这是为什么?二、问题分析对这个结论,你是否有怀疑呢?也不知道是哪位先哲说的不要人云亦云,今天我设计sql,来验证这个结论。(实验没有从代码角度分析...

weixin_39853843的博客 1105

假人有限元模型

假人模型,车辆碰撞假人有限元模型,适合做乘员安全的研究者利用

阿里规定超过3张表,禁止join,为何?

点击上方“码农突围”,马上关注这里是码农充电第一站,回复“666”,获取一份专属大礼包真爱,请设置“星标”或点个“在看”来源:http://blog.itpub.net/30393770...

欢迎关注公众号:【码农突围】,回复9999,可以获取一份LeetCode刷题笔记 1257

为什么阿里巴巴规定禁止超过三张表 join?

最近,在知乎上看到一个有意思的问题,我个人觉得不错,挺有收获,在这里跟大家分享一下。 题目:《阿里巴巴JAVA开发手册》里面写超过三张表禁止join 这是为什么?这样的话那sql要怎么写? 一般,我对于这种问题,解决方案是查询官方文档,要么查看我的工具书《高性能的MySQL》,在本书的6.3节:重构查询的方式里面提到,需要考虑实际情况,看看是否有必要将一个复杂的查询分解成多个简单的查询,并不一定要把所有的工作全都移交给数据库(转换思路)!!! 其实Join拆解的核心就是利用In关键字,这个也是

勇往直前的专栏 684

阿里规定超过三张表时禁止使用 JOIN 关联查询,为什么呢?

>>号外:关注“Java精选”公众号,回复“面试资料”,免费领取资料!“Java精选面试题”小程序,3000+道面试题在线刷,最新、最全Java面试题!一、问题提出《阿里...

Java精选 4393

mysql禁用join_阿里规定超过三张表禁止JOIN,为啥呢?

作者:e71hao一、 问题提出《阿里巴巴JAVA开发手册》里面写超过三张表禁止join,这是为什么?关注我回复嵩山可以获取这个完整版。二、问题分析对这个结论,你是否有怀疑呢?也不知道是哪位先哲说的不要人云亦云,今天我设计sql,来验证这个结论。(实验没有从代码角度分析,目前达不到。可以把mysql当一个黑盒,使用角度来验证这个结论) 验证结论的时候,会有很多发现,各位往后看。三、 实验环境vmw...

weixin_39637256的博客 1095

mysql禁止三张表的连接_为什么阿里巴巴规定禁止超过三张表 join?

一:为什么做这种限制?二:在这种限制下SQL怎么写?最近,在知乎上看到一个有意思的问题,我个人觉得不错,挺有收获,在这里跟大家分享一下。题目:《阿里巴巴JAVA开发手册》里面写超过三张表禁止join 这是为什么?这样的话那sql要怎么写?一般,我对于这种问题,解决方案是查询官方文档,要么查看我的工具书《高性能的MySQL》,在本书的6.3节:重构查询的方式里面提到,需要考虑实际情况,看看是否有必要...

weixin_42466868的博客 1109
上一篇: PanDownload复活了!60MB/s!附下载地址
下一篇: 经验干货!竞赛比完,代码、模型怎么处理?Kaggle大神:别删,这都是宝藏
菜鸟学Python
博客等级 码龄9年 8081粉丝 571原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值