其實我想說:mysql的join真的很low
一、 問題提出: 《阿里巴巴JAVA開發手冊》裡面寫超過三張表禁止join,這是為什麼?
二、問題分析:對任何結論,我首先持懷疑態度的,也不知道是哪位先哲說的不要人云亦云。要怎麼驗證這個問題呢?今天我就設計了一個實驗來驗證,為什麼 超過三張表禁止join。各位可以看看我這個實驗是怎麼做的。
三、 實驗環境:vmware10+centos7.4+mysql5.7.22 ,centos7記憶體4.5G,4核,50G硬碟。 mysql配置為2G,特別說明硬碟是SSD。
四、首先我選取了5張表:學生表_課程表_成績表_授課表—_教師表
表結構關係,資料量如下:
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<5000000 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()*100000),concat('note',i) ); set i=i+1; end while; return 1; end$$ delimiter ; select insert_student_data(); select count(*) from student;
create table course ( c_id int(11) not null auto_increment , cname varchar(50), t_id int(11) , 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()*1000000),concat('note',i) ); set i=i+1; end while; return 1; end$$ delimiter ; select insert_course_data(); select count(*) from course;
drop table if exists sc; create table sc ( s_id int(11), cname varchar(50), 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<=5000000 do insert into sc values( i,concat('course',floor(rand()*1000)),floor(rand()*100)) ; set i=i+1; end while; return 1; end$$ delimiter ; select insert_sc_data(); select count(*) from sc;
create table tc ( t_id int(11), cname varchar(50) ) engine=innodb default charset=utf8mb4; truncate table tc; delimiter $$ drop function if exists insert_tc_data $$ create function insert_tc_data() returns int deterministic begin declare i int; set i=1; while i<=1000000 do insert into tc values( i,concat('course',floor(rand()*1000))) ; set i=i+1; end while; return 1; end$$ delimiter ; select insert_tc_data(); select count(*) from tc;
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<=1000000 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(); select count(*) from teacher;
這5張表,容易不容易,簡單不簡單?這些表的關係如你們所料,就是關係圖。同時每個表插入資料。如下表:
表 | 數量 |
student | 500萬 |
teacher | 100萬 |
course | 1000 |
sc | 1000萬 |
tc | 200萬 |
一個學生選修了2門課程,每個老師教2門課程。總共有1000門課程。student有2個索引,teacher有2個索引,sc和tc暫時沒有索引,等下,隨著我的實驗深入,我會擇機加入索引。
表的數量:
五、實驗過程如下:
五、解決一個問題:查詢選修“tname553”老師所授課程的學生中,成績最高的學生姓名及其成績
這個sql怎麼寫呢?思考1分鐘。
給出答案:
select Student.Sname,score from Student,SC,tc,Course ,Teacher where Student.s_id=SC.s_id and SC.cname=Course.cname and sc.cname=tc.cname and tc.t_id=teacher.t_id and Teacher.Tname='tname553' and SC.score=(select max(score)from SC where cname=Course.cname );
然後我放到mysql去執行,執行了很長時間,超過5分鐘,沒有得到結果。
六、我換個方式去執行:分步驟,一個一個步驟找出我要的資料來。
select tc.t_id,tc.cname from tc,Course ,Teacher where tc.cname=course.cname and tc.t_id=teacher.t_id and Teacher.Tname='tname553' ;
耗時:2min53sec
select Student.Sname,score from Student,SC where Student.s_id=SC.s_id and cname in ('course735','course502') and score=(select max(score) from sc where cname in ('course735','course502'));
204 rows in set (7.72 sec)
分成2個sql,耗時3min。
七、在換一種方式,單個sql執行:
select t_id from teacher where tname='tname553'; select * from tc where tc.t_id=553; select * from course where cname in ('course735','course502'); select max(score) from sc where cname in ('course735','course502'); select Student.Sname,score from Student,SC where Student.s_id=SC.s_id and cname in ('course735','course502') and score=99;
總耗時:15秒
八、sc表和tc表加上索引會怎麼樣呢?
來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/30393770/viewspace-2650450/,如需轉載,請註明出處,否則將追究法律責任。
相關文章
- 我想說:mysql 的 join 真的很弱MySql
- 關於996,我想說996
- MySQL Join的底層實現原理MySql
- MySQL LEFT JOIN/ INNER JOIN/RIGHT JOINMySql
- Mysql join 的本質,Nested Loop Join 和 Hash JoinMySqlOOP
- MySQL JOIN的使用MySql
- mysql中的left join、right join 、inner join的詳細用法MySql
- mysql left join轉inner joinMySql
- Paxos協議其實說的就是Paxos協議
- mysql + left joinMySql
- MySQL Join語法MySql
- MySQL實戰 | 06/07 簡單說說MySQL中的鎖MySql
- MySQL 的 join 功能弱爆了?MySql
- 資料庫實踐丨MySQL多表join分析資料庫MySql
- 一張圖說明SQL的join用法SQL
- mysql的left join和inner join的效率對比,以及如何優化MySql優化
- Spring Security實戰三:說說我的認識Spring
- 【MySQL】LEFT JOIN 踩坑MySql
- 使用MySQL的遞延Join連線實現高效分頁 - AaronMySql
- 說實話,玩過這款敘事解謎遊戲後,我想奶奶了......遊戲
- 面了三十個人,說說我的真實感受
- Mysql實現全外部連線(mysql無法使用full join的解決辦法)MySql
- 簡陋到極致便成了經典,看似很Low的開羅遊戲其實並不簡單遊戲
- MySQL表關聯join方式MySql
- join、inner join、left join、right join、outer join的區別
- MySQL系列6 - join語句的優化MySql優化
- 過於“直白”的《大多數》,其實並未想讓無數玩家“破防”
- 你以為我在玩遊戲?其實我在學 Java遊戲Java
- MySQL鎖這塊石頭似乎沒有我想的那麼重MySql
- 面試官:說說你對Fork/Join的平行計算框架的瞭解?面試框架
- MySQL join連表查詢示例MySql
- mysql left join 優化學習MySql優化
- mysql update join,insert select 語法MySql
- MySQL 之 LEFT JOIN 避坑指南MySql
- 2020年我想對你說(蘋果開發者賬號)蘋果
- 老師說不懂就要問,我有個疑惑想請教各位
- 我的北大故事:犯其至難圖其至遠!
- mysql INNER JOIN、LEFT JOIN、RIGHT JOIN;內連線(等值連線)、左連線、右連線MySql