索引是一種提升數據庫查詢效率的數據結構(咱們說的通常都是B+ tree索引)html
(root@localhost) [test]> show create table l \G *************************** 1. row *************************** Table: l Create Table: CREATE TABLE `l` ( `a` int(11) NOT NULL, `b` int(11) DEFAULT NULL, `c` int(11) DEFAULT NULL, `d` int(11) DEFAULT NULL, PRIMARY KEY (`a`), -- 主鍵 UNIQUE KEY `c` (`c`), -- 惟一索引 KEY `b` (`b`) -- 普通索引 ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 1 row in set (0.08 sec)
一張表能夠有多個索引,索引就是對建立索引的這些列進行排序
優勢:
使查詢速度變得很是快,且這個快基本上和數據量不要緊
缺點:
不少索引都要排序則要對這些索引列進行維護,直接插入原本很快,可是有了索引作ddl操做則代價比較大,雖然說不能太多索引列,可是大場景下很難作到mysql
tips:
主鍵和惟一索引的區別:sql
不少人說一張表不能太大,太大要拆表?這麼說的兩個緣由(oracle沒這個說法):
a.MySQL以前的DDL操做,比較麻煩,建立了索引,再作這些會表鎖(全局讀鎖),數據量太大會鎖時間太長,也就是以前不支持online ddl嘛。之前都是先在slave上搞,搞好作個主從的切換
b.以前MySQL的索引源代碼的實現上有一把大鎖,致使性能比較通常,不過沒有淘寶這個業務量基本上影響不大,可是5.7也解決了這個問題數據庫
綜上:MySQL5.7這時候,索引自己已經實現地很完整了(管理和性能兩個方面),一億不是什麼問題數據結構
tips:併發
再強調:
1.MySQL用SSDoracle
2.拆表不會提高性能工具
3.如今不存在最多多少記錄的問題性能
B+ tree是一種基於塊(page)設備的存儲中來有效的存取,檢索數據的數據結構優化
show variables like 'innodb_page_size'; +------------------+-------+ | Variable_name | Value | +------------------+-------+ | innodb_page_size | 16384 | +------------------+-------+ 默認16k,oracle默認8k 看數據庫中.ibd文件,大小都是16k的倍數
tips:
文件系統都是基於塊的
db 16k ----------------------------------- filesystem(xfs) 4k 八個扇區 ,能夠調大提高性能 ----------------------------------- disk 512字節
該B+ tree高度爲2,每一個葉子節點存放4條記錄,扇出數爲5,葉子節點由小到大有序
tips:
上面說的有序指的是邏輯有序,不是物理的,在磁盤上作不到有序,每一個頁之間有指針告訴他下一個頁和前一個頁,可是物理上可能跨了好幾個頁
插入數據操做
如何插入28這條記錄?
先找28所在的頁,經過二分查找,找到指針指到的頁,若是頁中還有空閒就直接插
可是想插70,發現70所在的頁已經滿了,這時候就會作一個split操做(代價蠻大的),把這個頁拆成兩個頁,最經常使用的是把這個頁的中間值(這裏是60)提取出來放到上面,兩邊往下拆
插95呢,發現也滿了,想拆,可是發現上一層節點也滿了,因此要作兩次split
MySQL5.7以前split代價很是大,會把整棵樹都鎖住,這時候其餘記錄插入和更新就不方便了,可是一般分頁自己也仍是蠻快的額,也不會一直分頁,只是頁滿了的狀況纔會分,因此問題也不是很大,5.7不會一會兒鎖住,會盡可能用小的鎖控制併發
插入95以後B+ tree的高度從2變成了3
刪數據操做
若是一個頁裏面的數據不多了則會嘗試和它左邊或者右邊的頁進行合併
alter table x add index unique idx_b (b); -- 在b上建立一個惟一索引 alter table x add index index_a (a); -- 在a上建立一個普通索引 alter table x drop index index_a; -- 刪除a上面的索引
在線上就不同咯
還記得online ddl表嘛?
5.6以前建立索引並非online的,會對這個表加一個讀鎖(S lock)只能select不能insert,會阻塞
5.6開始原生支持了在線索引添加,在添加索引過程當中,應用程序對錶依然可讀可寫
online ddl的這段時間內,對錶作的操做會先記錄到alter table的日誌裏,這個日誌是內存的,若是內存大小過小記不下來就會報錯
(root@localhost) [(none)]> show variables like 'innodb_online_alter_log_max_size'; +----------------------------------+-----------+ | Variable_name | Value | +----------------------------------+-----------+ | innodb_online_alter_log_max_size | 134217728 | +----------------------------------+-----------+ 1 row in set (0.00 sec)
若是線上更新操做比較多,調大這個值set global innodb_online_alter_log_max_size = 128M,這是個全局變量,在my.cnf中也配上
在線索引添加存在的一個問題——主從延時(MySQL邏輯複製,oracle物理複製不存在這個問題)
alter table是執行完以後才告訴從機要執行(事務),從庫也順序執行,當執行到這個在線ddl,其餘並行的dml語句,也要等待這個ddl執行完畢後才能並行
同步的是二進制日誌,要等事務執行完以後才提交過去,並非物理日誌
真正在線上不多用alter table這種方式去執行ddl操做,即便5.7如今對愈來愈多的ddl操做讀寫不阻塞了,就是由於主從延時
如今就要percona toolkit出場了(備註,除了下面介紹的這個工具,裏面的其餘工具不建議使用,儘可能使用官方的)
這裏面最有用的就是pt-online-schema-change,其餘工具官方工具包utlities裏面都有了,官方也在作前面那個工具了
這個工具作在線ddl,主從延遲很是小,不是直接操做的,是經過觸發器的機制來慢慢加,還有控制延時的參數呢
關於online ddl和pt-osc詳見這裏