一次給市場部統計報表數據的案例:
其中有個臨時實體表的表創建的時候使用的create table table_name select xxx from ,所以並未創建主鍵
創建完成後,我還給其中字段加了索引,索引列基數爲1,所以索引選擇性是非常好的!
表結構如下:
mysql> desc tbl_userlogin_info_tmp2;
+--------+------------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+--------+------------+------+-----+---------+-------+
| userid | int(11) | YES | MUL | NULL | |
| p | bigint(21) | NO | | 0 | |
+--------+------------+------+-----+---------+-------+
字段userid上是有索引的,並且索引列基數爲1
然後看執行計劃:
mysql> desc select f.schoolid,d.schoolname,count(*) as numbers,f.manager
-> from cw_relations.cw_groupclassmember as a
-> inner join cw_relations.cw_groupclass as b on a.gcid=b.id
-> inner join cw_relations.cw_class as c on b.id=c.cid
-> inner join cw_relations.cw_school as d on c.schoolid=d.schoolid
-> inner join test.userid_info as m on a.userid=m.userid
-> inner join test.tbl_userlogin_info_tmp2 as n on a.userid=n.userid
-> right join test.school_id_new as f on d.schoolid=f.schoolid group by f.schoolid;
+----+-------------+-------+--------+-----------------------------------+------------+---------+-----------------------+--------+---------------------------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+-------------+-------+--------+-----------------------------------+------------+---------+-----------------------+--------+---------------------------------+
| 1 | SIMPLE | f | ALL | NULL | NULL | NULL | NULL | 2580 | Using temporary; Using filesort |
| 1 | SIMPLE | d | eq_ref | PRIMARY | PRIMARY | 8 | test.f.schoolid | 1 | |
| 1 | SIMPLE | n | index | idx_userid | idx_userid | 5 | NULL | 652751 | Using index |
| 1 | SIMPLE | a | ref | GCID_UserID,Index 2 | Index 2 | 5 | test.n.userid | 1 | Using index |
| 1 | SIMPLE | b | eq_ref | PRIMARY | PRIMARY | 8 | cw_relations.a.GCID | 1 | Using index |
| 1 | SIMPLE | m | eq_ref | PRIMARY | PRIMARY | 4 | cw_relations.a.UserID | 1 | |
| 1 | SIMPLE | c | eq_ref | PRIMARY,SchoolID_PeriodID_GradeID | PRIMARY | 8 | cw_relations.b.ID | 1 | |
+----+-------------+-------+--------+-----------------------------------+------------+---------+-----------------------+--------+---------------------------------+
可以看出此語句在tbl_userlogin_info_tmp2表上雖然顯示使用了索引,但掃描行數依然爲652751 條,爲全表掃描:
再看我給tbl_userlogin_info_tmp2表加上自增主鍵列
alter table tbl_userlogin_info_tmp2 add id int auto_increment primary key ;
mysql> desc tbl_userlogin_info_tmp2;
+--------+------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+--------+------------+------+-----+---------+----------------+
| userid | int(11) | YES | MUL | NULL | |
| p | bigint(21) | NO | | 0 | |
| id | int(11) | NO | PRI | NULL | auto_increment |
+--------+------------+------+-----+---------+----------------+
執行計劃:
mysql> desc select f.schoolid,d.schoolname,count(*) as numbers,f.manager
-> from cw_relations.cw_groupclassmember as a
-> inner join cw_relations.cw_groupclass as b on a.gcid=b.id
-> inner join cw_relations.cw_class as c on b.id=c.cid
-> inner join cw_relations.cw_school as d on c.schoolid=d.schoolid
-> inner join test.userid_info as m on a.userid=m.userid
-> inner join test.tbl_userlogin_info_tmp2 as n on a.userid=n.userid
-> right join test.school_id_new as f on d.schoolid=f.schoolid group by f.schoolid;
+----+-------------+-------+--------+-----------------------------------+---------------------------+---------+-------------------------+------+---------------------------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+-------------+-------+--------+-----------------------------------+---------------------------+---------+-------------------------+------+---------------------------------+
| 1 | SIMPLE | f | ALL | NULL | NULL | NULL | NULL | 2580 | Using temporary; Using filesort |
| 1 | SIMPLE | d | eq_ref | PRIMARY | PRIMARY | 8 | test.f.schoolid | 1 | |
| 1 | SIMPLE | c | ref | PRIMARY,SchoolID_PeriodID_GradeID | SchoolID_PeriodID_GradeID | 9 | cw_relations.d.SchoolID | 13 | Using index |
| 1 | SIMPLE | b | eq_ref | PRIMARY | PRIMARY | 8 | cw_relations.c.CID | 1 | Using index |
| 1 | SIMPLE | a | ref | GCID_UserID,Index 2 | GCID_UserID | 9 | cw_relations.b.ID | 58 | Using index |
| 1 | SIMPLE | m | eq_ref | PRIMARY | PRIMARY | 4 | cw_relations.a.UserID | 1 | |
| 1 | SIMPLE | n | ref | idx_userid | idx_userid | 5 | cw_relations.a.UserID | 1 | Using index |
+----+-------------+-------+--------+-----------------------------------+---------------------------+---------+-------------------------+------+---------------------------------+
可以看出執行計劃顯示走了索引,掃描行數也減少到了5行
在第一個執行計劃裏ref字段爲null,表示mysql並未使用內聯On 字段做與其它的表做匹配,而且在第二個執行計劃裏,ref裏已經使用了cw_relations.a.userid 這個字段與該表userid做匹配!
其中原理我還未曾想明白,最開始的表沒有自增主鍵列,而且我也沒有給userid這個列設主鍵列,所以innodb應該會給表創建隱藏主鍵列,所以猜想效果應該是一樣的,但事實勝於雄辯,可見自增主鍵列對Innodb表來說有多麼重要!!
問題有新的進展,今天在執行相同腳本的時候,發現創建了自增列後,執行計劃還是跟之前的一樣ref 列爲null, 奇怪了!!!! 於是想起是不是列允許爲Null值的原因,於是alter table test.tbl_userlogin_info_tmp2 modify userid int unsigned not null ,再看執行計劃,ref列已經爲cw_relations.a.userid!