MySQL5 6 Internals 隱藏的索引列

2021-06-14 21:36:31 字數 2861 閱讀 8653

今天本來想跟蹤mysql5.6中的新特性index merge,結果在跟蹤的過程中,發現了乙個問題,即innodb的二級索引中 可能會包含主索引,當然這裡的包含並不是說二級索引的row裡面會有pk的記錄,這一點是一直存在的,這裡的包含 是指,二級索引也會包含主索引進行排序。

mysql> show create table index_merge\g

*************************** 1. row ***************************

table: index_merge

create table: create table `index_merge` (

`c1` int(11) not null auto_increment,

`c2` int(11) default null,

`c3` varchar(100) default null,

primary key (`c1`),

key `c2` (`c2`)

) engine=innodb auto_increment=10002 default charset=latin1

1 row in set (0.00 sec)

mysql> show create procedure fill_index_merge\g

*************************** 1. row ***************************

procedure: fill_index_merge

sql_mode: no_engine_substitution

create procedure: create definer=`root`@`127.0.0.1` procedure `fill_index_merge`(c1_cnt int, c2_cnt int)

begin

declare i,j int default 1;

repeat

repeat

insert into index_merge(c2,c3) values(j, repeat('a', 64));

set j = j+1;

until j > c2_cnt

end repeat;

set i = i + 1;

set j = 1;

until i > c1_cnt

end repeat;

endcharacter_set_client: utf8

collation_connection: utf8_general_ci

database collation: latin1_swedish_ci

1 row in set (0.00 sec)

mysql> call fill_index_merge(100, 100);

mysql> explain select * from index_merge where c1 < 100 and c2 = 50\g

*************************** 1. row ***************************

id: 1

select_type: ******

table: index_merge

type: range

possible_keys: primary,c2

key: c2

key_len: 9

ref: null

rows: 1

extra: using index condition

1 row in set (0.00 sec)

可以看到,計畫中竟然是range的查詢,我的第一直覺應該是ref const的查詢,但是確實是range,使用c2的range, 但是c2的key_len竟然是9,我去,各種疑惑啊,於是跟蹤計畫生成,發現key有兩個(primary, c2),但是c2的index上的列確有兩列,(c2,c1)。 瞬間凌亂了,竟然隱式的修改我的index,還把使用者蒙在鼓裡。

由上面的分析,可以知道c2的index在生成時,其實被mysql隱式修改為(c2,c1)的index了,那我們就看下**吧。

一開始我以為這些修改是在建立表的時候就隱式的修改了,我又錯了,木有,看遍了mysql_create_frm()都沒找到**修改了, frm檔案還是那個frm檔案。

ok,不是建立的時候修改,那只能是載入frm時候修改了,也就是記憶體的修改。看看資料字典的載入函式open_binary_frm(),bingo, 5.6相比5.5確實做了修改,重點**如下:

open_binary_frm()

share->key_parts+= keyinfo->hidden_key_parts;

}...

}  ...

}

重點來了,首先只有innodb引擎才支援隱式修改second index,然後是通過add_pk_parts_to_sk()函式將pk的列 加入到second index中,當然加入過程中有些限制,如對key中可列數和key的長度的限制。

innodb引擎原本的二級索引中的記錄就會包含pk的列,之前只是為了通過二級索引去定位主索引,也就時pk和second key之間資料 的一一對映,並沒有別的用途,現在增加了在sk中對pk的排序,可以說是在沒有增加儲存開銷的情況下,使得記錄有序性更強,也就是 更加有利於最優計畫的生成。當然代價可能就是插入時候key compare的時間會稍微變長。

總的來說,innodb在不斷完善,oracle也可以說是功不可沒吧,雖然我個人很討厭oracle現在把mysql搞的沒什麼活力了,很多東西不再那麼open了, 比如mysql-test的test case,bug系統等,希望oracle能把mysql做的更好吧。

from :  (原始碼大牛)

mysql5 6亂碼 mysql5 6亂碼

安裝mysql5.6版本遇到乙個問題,字符集亂碼,如下圖 由於是新安裝的本地資料庫,所以一定是配置的事情,查詢資料庫字符集配置,如下 有兩個是latin1的字符集,本人是window7環境,在網路找了很多資料,都顯示為修改 c program files mysql mysql server 5.6...

編譯mysql5 6 編譯安裝mysql5 6

mysqlwget tar zxvf mysql 5.6.33.tar.gz tar zxvf cmake 2.8.5.tar.gz cd cmake 2.8.5 安裝編譯工具.bootstrap prefix usr local cmake sudo gmake sudo gmake instal...

mysql5 6cmd亂碼 mysql5 6亂碼

安裝mysql5.6版本遇到乙個問題,字符集亂碼,如下圖 由於是新安裝的本地資料庫,所以一定是配置的事情,查詢資料庫字符集配置,如下 有兩個是latin1的字符集,本人是window7環境,在網路找了很多資料,都顯示為修改 c program files mysql mysql server 5.6...