查询过程
1,查询语句在索引树上查找过程,先通过B+树从树根开始按层搜索到叶子节点,数据页内部通过二分法定位记录。
1)对于普通索引,查找到满足条件的第一个记录后,需要查找下一个记录,直到第一个不满足条件的记录。
2)对于唯一索引,由于索引定义了唯一性,查询到第一个满足条件的记录后,就会停止搜索。
2,两种不同方式带来的性能差距比较小,InnoDB数据是按数据页为单位来读写的,当需要读一条记录时,不是将这条记录从磁盘读出,而是将这条记录的数据页整体读入内存。
1)InnoDB中,每个数据页的大小默认是16KB。
2)普通索引查找和判断下一条记录,只需要一次指针寻找和一次计算,但查找的记录刚好是数据页的最后一条记录,则取下一条记录时必须读取下一个数据页,操作稍微复杂一些。
3)对于整型字段,一个数据页可以存放近千个key,读取下一个数据页的概率比较低,所以在计算平均性能差异时忽略不计。
更新过程
1,更新语句,如果数据页在内存中直接更新,数据页不在内存中,在不影响数据一致性的前提下,InnoDB将更新缓存在change buffer中。
1)不从磁盘读入数据页,在下次查询需要访问数据页时再将数据页读入内存,然后执行change buffer中与数据页有关的操作,保证数据逻辑的正确性。
2)change buffer中的操作应用到原数据页的过程为merge,访问数据页会触发merge,系统后台线程也会定期merge,数据库正常关闭也会执行merge操作。
2,change buffer是可以持久化的数据,在内存中有拷贝,也会写入到磁盘。
1)数据读入内存需要占用buffer pool,使用change buffer可减少读磁盘,提升语句执行速度,还可避免占用内存,提高内存利用率。
2)change buffer占用的buffer pool的内存,大小可通过参数innodb_change_buffer_max_size动态设置,设置为50时,表示最多只能占buffer pool的50%。
change buffer
1,唯一索引不使用change buffer,普通索引使用。
1)唯一索引,所有的更新都要先判断索引的唯一性,例如插入数据时需要先判断表中key是否存在,则必须将数据页读入内存,没有冲突则插入数据,语句执行结束,也就没必要使用change buffer了。
2)普通索引可以使用change buffer,将更新记录在change buffer中,语句执行结束。
2,将数据从磁盘读入内存涉及随机IO的访问,是数据库中成本最高的操作之一,change buffer减少了随机磁盘的访问,对更新的性能提升比较明显。
3,merge才是真正数据更新过程,数据页merge之前,change buffer记录的变更越多,性能提升越明显。
1)在帐单类、日志类写多读少的业务中,页面写完立即访问的概率较小,change buffer使用效果佳。
2)业务更新之后立刻查询,更新记录在change buffer里,但立刻访问这个数据页触发merge过程,随机访问IO次数并不会减少,反而增加了change buffer的维护代价,可以关闭change buffer。
3)普通索引和唯一索引尽量选择普通索引,配合使用change buffer,更新优化明显。
change buffer和redo log
1,执行一条更新语句:
1)如果数据页在内存中,直接更新内存同时记录到redo log,之后执行查询操作直接从内存返回;
2)如果数据页不在内存中,将更新记录到内存change buffer区域,并记录到redo log中,之后执行查询操作,需要从磁盘读入数据页到内存,再应用change buffer操作,最后返回正确结果。
2,一条更新语句插入多个记录,按以上原则写到内存或change buffer中,写了两处内存,多条记录顺序写入redo log,写一次磁盘。
3,redo log主要节省随机写磁盘的IO消耗(转成顺序写),change buffer主要节省随机读磁盘的IO消耗。