一、索引組織表
在InnoDB當(dāng)中,表都是根據(jù)主鍵的順序組織存放的符隙,這種存儲方式的表稱為索引組織表(Index Organized Table)。
在InnoDB表中垫毙,每張表都有主鍵霹疫,如果在創(chuàng)建時沒有顯示的指定主鍵,則會按照以下方式選擇或創(chuàng)建主鍵:
1)首先综芥,判斷表中是否有唯一且非空的索引(Unique NOT NUll)丽蝎,如果有,則將其指定為主鍵膀藐。
2)如果不符合上述屠阻,則InnoDB會自動創(chuàng)建一個6字節(jié)的指針。
當(dāng)表中存在多個唯一且非空的索引時额各,會選擇第一個創(chuàng)建的唯一且非空索引作為主鍵国觉。
_rowid可以用于查看當(dāng)前表的主鍵:
但是對于多個字段的聯(lián)合主鍵是無效的。
二虾啦、InnoDB邏輯存儲結(jié)構(gòu)
從上圖可以看出麻诀,所有的數(shù)據(jù)都被邏輯的存放在一個空間中,稱之為表空間(tablespace)缸逃。表空間由段(segment)针饥、區(qū)(extent)、頁(page)組成需频。
2.1 表空間
前面的文章記錄了在InnoDB存儲引擎當(dāng)中有一個共享表空間idata1,當(dāng)啟用innodb_file_per_table參數(shù)后筷凤,每個表有自己的獨立表空間昭殉。
獨立表空間中只存放數(shù)據(jù)、索引和插入緩沖BitMap頁藐守,其他數(shù)據(jù)挪丢,如:回滾信息,插入緩沖索引頁卢厂,系統(tǒng)事務(wù)信息乾蓬,二次寫緩沖等還是存放在共享表空間中。
2.2 段
在上面的圖中看到表空間是由段組成的慎恒。常見的段有數(shù)據(jù)段任内,索引段撵渡,回滾段等。由于InnoDB是基于索引組織表的死嗦,所以其數(shù)據(jù)段就是B+樹的葉子結(jié)點(Leaf node segment)趋距,索引段是非葉子結(jié)點(Non-leaf node segement)≡匠回滾段在后面詳細介紹节腐。段是由存儲引擎自己控制的,不需要人為進行操作摘盆。
2.3 區(qū)
區(qū)是由連續(xù)的頁組成的翼雀,每個區(qū)默認大小是1M。為了保證區(qū)種頁的連續(xù)性孩擂,InnoDB存儲引擎一次從磁盤申請4~5個區(qū)锅纺。InnoBD存儲引擎頁的大小為16K,則每個區(qū)中有64個連續(xù)的頁肋殴。
無論是修改也得大小囤锉,還是使用壓縮頁,每個區(qū)的大小都是1M护锤。
2.4 頁
頁是磁盤上管理的最小單位官地,在InnoDB中,每個頁默認最小是16k烙懦,可以通過參數(shù)innodb_page_size將大小設(shè)置為4K驱入,8K,16K等氯析。設(shè)置完成后亏较,則不許進行修改,除非通過導(dǎo)入導(dǎo)出產(chǎn)生新的庫掩缓。
InnoDB中常見的頁類型有:
1)數(shù)據(jù)頁(B+樹 Node)
2)系統(tǒng)頁
3)undo 頁
4)事務(wù)數(shù)據(jù)頁
5)插入緩沖位圖頁
6)插入緩沖空閑列表頁
7)未壓縮的二進制大對象頁
8)壓縮的二進制大對象頁
2.5 行
數(shù)據(jù)頁是按照行進行存放的雪情,并且有硬性的要求,即每個頁中的數(shù)據(jù)行數(shù)是16K/2 - 200 行你辣,即7992行巡通。
三、分區(qū)表
分區(qū)功能并不是在存儲引擎層面完成的舍哄,因此宴凉,InnoDB,MyISam表悬,NDB等都支持分區(qū)弥锄。
在mysql5.6中,可以使用以下命令查看是否開啟表分區(qū)功能:
show variables like '%partition%';
在mysql8中可以使用如下的方式:
mysql> select table_schema, table_name, partition_name,partition_method,partition_expression from information_schema.PARTITIONS where table_name = 'bssp_sys_menu';
+--------------+---------------+----------------+------------------+----------------------+
| TABLE_SCHEMA | TABLE_NAME | PARTITION_NAME | PARTITION_METHOD | PARTITION_EXPRESSION |
+--------------+---------------+----------------+------------------+----------------------+
| bssp | bssp_sys_menu | NULL | NULL | NULL |
+--------------+---------------+----------------+------------------+----------------------+
1 row in set (0.01 sec)
mysql中支持的分區(qū)類型是水平分區(qū),且其分區(qū)是局部索引分區(qū)籽暇,即一個分區(qū)即存放數(shù)據(jù)也存放索引温治。
mysql支持的幾種分區(qū)類型:
1)RANGE分區(qū):行數(shù)據(jù)屬于一個給定的連續(xù)列值的范圍,責(zé)備加入該分區(qū)图仓。
2)LIST分區(qū):和RANGE分區(qū)類型相比罐盔,只是LIST分區(qū)面向離散的值。
3)HASH分區(qū):根據(jù)用戶自定義的返回值來確定分區(qū)救崔,返回值不能為負數(shù)惶看。
4)KEY分區(qū):根據(jù)mysq提供的hash函數(shù)進行分區(qū)。
不論以何種方式創(chuàng)建分區(qū)六孵,當(dāng)表中存在主鍵或唯一索引時纬黎,唯一索引可以為空,分區(qū)列必須是其一個組成部分(比如聯(lián)合唯一索引劫窒,只要包含一個列就行)本今。
如果不指定主鍵和唯一索引,則可以用任何列創(chuàng)建分區(qū)主巍。
分區(qū)的性能
數(shù)據(jù)庫分為OLTP(在線事務(wù)處理應(yīng)用)和OLAP(在線分析應(yīng)用)冠息。
對于OLAP,可以很好的提升性能孕索。比如有一張上億的表逛艰,用戶需要根據(jù)某些列不斷的查詢。如果我們以時間段對表做分區(qū)搞旭,則只需要查詢該分區(qū)的表數(shù)據(jù)散怖。
對于OLTP,分區(qū)要相對小心肄渗。通常很少有需要獲取超過表中10%數(shù)據(jù)的要求镇眷,而對于只需要獲取幾條甚至單條數(shù)據(jù)的請求,B+樹的兩到三次的IO能夠很好的完成操作翎嫡。并不需要分區(qū)方式欠动。相反,設(shè)計不好钝的,會帶來嚴重的性能問題翁垂。