We read every piece of feedback, and take your input very seriously.
To see all available qualifiers, see our documentation.
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
业务代码已经保证了不会写入两个重复的信息
InnoDB 的数据是按数据页为单位来读写的。也就是说,当需要读一条记录的时候,并不是将这个记录本身从磁盘读出来,而是以页为单位,将其整体读入内存。在 InnoDB 中,每个数据页的大小默认是 16 KB。
因此,对于普通索引来说,要多做的那一次“查找和判断下一条记录”的操作,就只需要一次指针寻找和一次计算。
当需要更新一个数据页时,如果数据页在内存中就直接更新,而如果这个数据页还没有在内存中的话,在不影响数据一致性的前提下,InooDB 会将这些更新操作缓存在 change buffer 中,这样就不需要从磁盘中读入这个数据页了。 在下次查询需要访问这个数据页的时候,将数据页读入内存,然后执行 change buffer 中与这个页有关的操作。通过这种方式就能保证这个数据逻辑的正确性。 change buffer 是可以持久化的数据,在内存中有拷贝,也会被写入到磁盘上。 将 change buffer 中的操作应用到原数据页,得到最新结果的过程称为 merge。 除了访问这个数据页会触发 merge 外,系统有后台线程会定期 merge。在数据库正常关闭(shutdown)的过程中,也会执行 merge 操作。 change buffer 用的是 buffer pool 里的内存,因此不能无限增大。 change buffer 的大小,可以通过参数 innodb_change_buffer_max_size 来动态设置。这个参数设置为 50 的时候,表示 change buffer 的大小最多只能占用 buffer pool 的 50%。 change buffer 只能二级索引使用,因为唯一索引需要判断数据是否存在,需要把数据页读取到内存中,也就没有使用 change buffer 的必要了
第一种情况是,这个记录要更新的目标页在内存中。这时,InnoDB 的处理流程如下:
第二种情况是,这个记录要更新的目标页不在内存中。这时,InnoDB 的处理流程如下:
将数据从磁盘读入内存涉及随机 IO 的访问,是数据库里面成本最高的操作之一。change buffer 因为减少了随机磁盘访问,所以对更新性能的提升是会很明显的
适合写多读少的场景,在一个数据页做 merge 之前,change buffer 记录的变更越多(也就是这个页面上要更新的次数越多),收益就越大
建议你尽量选择普通索引,如果所有的更新后面,都马上伴随着对这个记录的查询,那么你应该关闭 change buffer。而在其他情况下,change buffer 都能提升更新性能
执行以下语句的操作过程
mysql> insert into t(id,k) values(id1,k1),(id2,k2);
select * from t where k in (k1, k2)
redo log 主要节省的是随机写磁盘的 IO 消耗(随机写磁盘转成顺序写redo log),而 change buffer 主要节省的则是随机读磁盘的 IO 消耗(写操作不用先读数据页到内存)
The text was updated successfully, but these errors were encountered:
分为两种情况:
Sorry, something went wrong.
git-zjx
No branches or pull requests
前提
业务代码已经保证了不会写入两个重复的信息
对查询过程的影响
InnoDB 的数据是按数据页为单位来读写的。也就是说,当需要读一条记录的时候,并不是将这个记录本身从磁盘读出来,而是以页为单位,将其整体读入内存。在 InnoDB 中,每个数据页的大小默认是 16 KB。
因此,对于普通索引来说,要多做的那一次“查找和判断下一条记录”的操作,就只需要一次指针寻找和一次计算。
关于 change buffer
当需要更新一个数据页时,如果数据页在内存中就直接更新,而如果这个数据页还没有在内存中的话,在不影响数据一致性的前提下,InooDB 会将这些更新操作缓存在 change buffer 中,这样就不需要从磁盘中读入这个数据页了。
在下次查询需要访问这个数据页的时候,将数据页读入内存,然后执行 change buffer 中与这个页有关的操作。通过这种方式就能保证这个数据逻辑的正确性。
change buffer 是可以持久化的数据,在内存中有拷贝,也会被写入到磁盘上。
将 change buffer 中的操作应用到原数据页,得到最新结果的过程称为 merge。
除了访问这个数据页会触发 merge 外,系统有后台线程会定期 merge。在数据库正常关闭(shutdown)的过程中,也会执行 merge 操作。
change buffer 用的是 buffer pool 里的内存,因此不能无限增大。
change buffer 的大小,可以通过参数 innodb_change_buffer_max_size 来动态设置。这个参数设置为 50 的时候,表示 change buffer 的大小最多只能占用 buffer pool 的 50%。
change buffer 只能二级索引使用,因为唯一索引需要判断数据是否存在,需要把数据页读取到内存中,也就没有使用 change buffer 的必要了
对更新过程的影响
第一种情况是,这个记录要更新的目标页在内存中。这时,InnoDB 的处理流程如下:
第二种情况是,这个记录要更新的目标页不在内存中。这时,InnoDB 的处理流程如下:
将数据从磁盘读入内存涉及随机 IO 的访问,是数据库里面成本最高的操作之一。change buffer 因为减少了随机磁盘访问,所以对更新性能的提升是会很明显的
change buffer 的使用场景
适合写多读少的场景,在一个数据页做 merge 之前,change buffer 记录的变更越多(也就是这个页面上要更新的次数越多),收益就越大
索引选择和实践
建议你尽量选择普通索引,如果所有的更新后面,都马上伴随着对这个记录的查询,那么你应该关闭 change buffer。而在其他情况下,change buffer 都能提升更新性能
change buffer 和 redo log
执行以下语句的操作过程
将上述两个动作记入 redo log 中(图中 3 和 4)。
执行以下语句的操作过程
redo log 主要节省的是随机写磁盘的 IO 消耗(随机写磁盘转成顺序写redo log),而 change buffer 主要节省的则是随机读磁盘的 IO 消耗(写操作不用先读数据页到内存)
The text was updated successfully, but these errors were encountered: