一次innodb自增主鍵與索引列null或者not null重要性案例

一次給市場部統計報表數據的案例:

其中有個臨時實體表的表創建的時候使用的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!



發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章