mysql github week2_week2-MySQL实践一

MySQL实践一

所有结论都基于InnoDB引擎,参考丁奇的MySQL45讲

唯一索引与普通索引的选择

查询

在查询中:

对于普通索引,当查询到满足条件的一条记录后,数据库会继续查询下一条记录,知道不满足为止。

对于唯一索引,当查询到满足条件的一条记录后,就终止了。

计算机时按页读取的,一般满足条件的数据是在这同一页的。对于普通索引来说,要多做的那一次“查找和判断下一条记录”的操作,就只需要一次指针寻找和一次计算。因此,在查询上两者差距微乎其微。

更新

情况一:需要更新的数据页在内存中,则两者差距不大。

情况二:需要更新的数据页在磁盘上。

在利用普通索引做更新操作时,如果数据页在磁盘上,InnoDB会引入change buffer记录下对该数据页的更新操作。当需要读取该数据页的记录时,读取该数据页到内存,根据change buffer再对数据页进行merge。change buffer 减少了随机访问磁盘的操作。

利用唯一索引时,为了保证唯一性,引擎一定会进行I/O操作取出数据页。

change buffer 用的是 buffer pool 里的内存,因此不能无限增大。change buffer 的大小,可以通过参数 innodb_change_buffer_max_size 来动态设置。这个参数设置为 50 的时候,表示 change buffer 的大小最多只能占用 buffer pool 的 50%。

所作的事情上,change buffer和redo log是一样的,但它们两者的功能是不同,change buffer是减少随机访问磁盘,而redo log是减少随机写磁盘。

当然,change buffer并非永远有效,当我更新记录后,立即查询,会立即触发 merge 过程。随机访问磁盘没有减少,反而增加了change buffer的维护成本。

给字符串加索引

邮箱一般有字符串进行存储,如执行select f1, f2 from SUser where email='xxx';如果没有建立索引,则会进行全表扫描。而以整个字符串建立索引,数据页存储行数变少影响数据库性能。

前缀索引

前缀索引会损失区分度,选择合适长度,是建立前缀索引的关键。观察前缀区分的sql如下:

count(distinct left(email,4))as L4,

count(distinct left(email,5))as L5,

count(distinct left(email,6))as L6,

count(distinct left(email,7))as L7,

前缀索引会对覆盖索引索引产生影响,即使email(max_len) 的前缀索引,这时候虽然前缀索引已经包含了所有的信息,但 InnoDB 还是要回到 id 索引再查一下,因为系统并不确定前缀索引的定义是否截断了完整信息。

如果遇到身份证号码类似的情况,前缀索引的区分度不高。

可以将身份证号倒序后再存储。

mysql> select field_list from t where id_card = reverse('input_id_card_string');

使用hash字段。新建一列,存储身份证号码的hash值。

而这两种方法相同点:都不支持范围查询。

数据库刷脏页

当内存数据页跟磁盘数据页内容不一致的时候,我们称这个内存页为“脏页”。内存数据写入到磁盘后,内存和磁盘上的数据页的内容就一致了,称为“干净页”。

什么情况会引发数据库的(刷脏页) flush 过程呢?

1、redo log 满了,系统不得不将进行写磁盘操作,将redo log空出一部分。

2、系统内存不足了。需要淘汰一部分数据页,如果淘汰的是干净页,直接释放,如果是脏页,就 需要将脏页写到磁盘。

3、空闲时间,清理redo log写磁盘。

4、MySQL正常关闭,将内存中所有脏页写到磁盘。

后两者,对MySQL运行时的效率没有影响。

出现第一种情况时,所有的更新操作都会被阻塞,知道redo log有空余。

第二种情况时,InnoDB 用缓冲池(buffer pool)管理内存,缓冲池中的内存页有三种状态:没有使用的页、使用了是干净页、使用了是脏页。

InnoDB 刷脏页的控制策略

首先我们需要告诉InnoDB所在主机的IO能力。需要设置innodb_io_capacity参数,一般情况下,将innodb_io_capacity设置成磁盘的IOPS。

测试磁盘随机读写的命令如下:

fio -filename=$filename -direct=1 -iodepth 1 -thread -rw=randrw -ioengine=psync -bs=16k -size=500M -numjobs=10 -runtime=10 -group_reporting -name=mytest

InnoDB控制刷脏页速度,有两个参考因素,一个是缓冲池中脏页比例,一个是 redo log 写盘速度。参数 innodb_max_dirty_pages_pct 是脏页比例上限,默认值是 75%。

根据这两个因素分别计算出两个(0-100)的数R1与R2,选择

Max(R1,R2)%*innodb_io_capacity作为当前刷脏页的速度。

合理地设置 innodb_io_capacity 的值,并且平时要多关注脏页比例,不要让它经常接近 75%。

脏页比例是通过 Innodb_buffer_pool_pages_dirty/Innodb_buffer_pool_pages_total得到

mysql> select VARIABLE_VALUE into @a from global_status where VARIABLE_NAME = 'Innodb_buffer_pool_pages_dirty';

select VARIABLE_VALUE into @b from global_status where VARIABLE_NAME = 'Innodb_buffer_pool_pages_total';

select @a/@b;

另外再刷脏页时,MySQL有一个连坐机制:如果准备刷的脏页旁边恰好也是脏页,那就把邻居一起刷掉。这种连坐机制可以一直蔓延,比如邻居的邻居也是脏页,一起刷掉。

在 InnoDB 中,innodb_flush_neighbors 参数就是用来控制这个行为的,值为 1 的时候会有上述的“连坐”机制,值为 0 时表示不找邻居。

机械硬盘IOPS一般不大,连坐机制可以有效减少随机IO次数。但对SSD硬盘IOPS不是瓶颈,需要关闭连坐机制,减少响应时间。在MySQL8.0中,innodb_flush_neighbors默认为0。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值