索引是一种提升数据库查询效率的数据结构(咱们说的通常都是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详见这里