阿里巴巴JAVA开发手册里有三个以上的表禁止加入。为什么?
二、问题分析你对这个结论有疑问吗?我不知道哪个圣人说过不要听从别人的建议。今天我设计了sql来验证这个结论。(实验不是从代码角度分析,目前无法实现。可以用mysql作为黑匣子来验证这个结论。)当你验证结论的时候,你会发现很多东西。请往后看。
三、 实验环境vmware10+centos7.4+mysql5.7.22
centos7内存4.5G,4核,50G硬盘。mysql配置为2G,特别说明硬盘是SSD。四、我概述下我的实验一共有四个表,学生表、教师表、课程表、sc中间关系表,记录学生的选修课和成绩。具体的sql脚本,见文末。我附上它。中间写了自己的脚本创建数据,也在最后。
实验是为了解决一个问题:在选修tname553老师所教课程的学生中,查询分数最高的学生的姓名和成绩。
该查询是:
我来分析一下这个说法:四个表等于连接,有一个子查询。是一个比较简单的sql语句(相比ERP需要10个表,已经很简单了)。我还将把这个语句分解成3个简单的sql语句:
我来分析一下:第一句是查询最高分,得到最高分590。第二句是找出分数最高的学号,得到
第三句是找出学生的名字和分数。这样就可以通过这三句话查出分数最高的学生的名字和成绩。
接下来我再分别做数据:1000万选课记录(一个学生上两门课),500万学生,100万老师(一个老师带五个学生,相当高端),1000门课。使用上面的查询语句进行查询。其中我测试了带索引和不带索引的sc表。有关详细信息,请参见下表。
接下来我要做1亿次选课记录(一个学生选修两门),5000万学生,1000万老师,1000门课程。然后分别执行以上语句。最后,我将在oracle数据库上执行上述语句。
五、下面两张表是测试结果六、仔细看上表,可以发现:1.在步骤3.1中,连接键没有添加索引,所以查询非常慢,表示:“查询多个表时,确保相关字段需要有索引”;
2.步骤6.1,6.2,6.3,换成简单sql,数据量过亿查询时间勉强可以接受。这一点上,mysql查询有点难,但还是嫩了点。
3.步骤5.1,mysql查询不出来,连接4个表。对于我的原生mysql来说,1.5亿的数据超过了极限(我调过这个sql,执行计划和索引都没了。没有问题。显示配置文件显示在发送数据中。这个问题将在另一篇文章中详细讨论。)
4.比较步骤1.1和5.1中的sql查询,连接了4个表。对于我的原生mysql来说,1500万的数据查询流畅度,是mysql数据流畅度的一个分水岭。(这只是一个现象,不是很准确,桌子的容量需要同时计算)。
5.相对于步骤5.1中的6.1、6.2、6.3,多表连接对于mysql来说有点难以处理。
6.禁止对三个以上的表进行联接。这个规则是针对mysql的。后面我会看到,用同样的机器,同样的数据量,同样的内存,我可以完美的计算出1.5亿个数据join。对于这样的规则,对于开发来说,需要在应用层放一些逻辑来查询。
摘要:在该规则中,禁止对三个以上的表进行联接。因为数据量太大,mysql根本无法查询,导致阿里制定了这样的规则。(其实如果表格数据量小的话,10个表格不成问题。你可以自己试试。)而我们公司的支付系统是朝着大规模、高并发的目标设计的。因此,遵循这一规定。
在业务层面,写简单的sql,在应用层放更多的逻辑,会让我更清楚自己的需求,在应用层实现具体的join就容易很多。
七、让我们来看看oracle数据库的优秀表现:再看第7.1步,就是在没有索引,有很多连接表的情况下,oracle仍然在26秒内找到结果。所以我会说mysql的加入很弱。那么问题来了,为什么现在很多人用mysql?这是另一个问题。我换个方式说说我的想法。
看完这篇文章,另外,送你一份礼物,所谓“猎草猎兔”。就是快速做数据。您可以先编写自己的脚本来创建数据。看我怎么创造数据,你就知道我的技术了。
八、附上部分截图九、附上sql语句和造数据脚本usestu;droptableifexistsstudent;createtablestudent(s_idint(11)notnullauto_increment,snoint(11),snamevarchar(50),sageint(11),ssexvarchar(8),father_idint(11),mather_idint(11),notevarchar(500),primarykey(s_id),uniquekeyuk_sno(sno))engine=innodbdefaultcharset=utf8mb4;truncatetablestudent;delimiter$$dropfunctionifexistsinsert_student_data$$createfunctioninsert_student_data()returnsintdeterministicbegindeclareiint;seti=1;whilei