一、准备数据
- 创建表
CREATE TABLE test
(
id INT PRIMARY KEY,
k INT NOT NULL,
name VARCHAR(16),
INDEX (k)
);
- 插入数据
INSERT INTO test(id, k)
VALUES (100,1),
(200,2),
(300,3),
(400,4),
(500,5),
(600,6);
二、查询过程
- SQL
SELECT id
FROM test
WHERE k = 5;
- 对于
普通索引
来说,查找到满足条件的第一个记录(5,500)后
,需要查找下一个记录
,直到碰到第一个不满足k=5
条件的记录 - 对于
唯一索引
来说,由于索引定义了唯一性
,查找到第一个满足条件的记录后,就会停止继续检索 - 那么,这个不同带来的性能差距会有多少呢?答案是, 微乎其微
三、更新过程
为了说明
普通索引
和唯一索引
对更新语句
性能的影响这个问题,介绍一下change buffer
3.1、普通索引更新过程
-
1、当需要更新一个
数据页
时,如果数据页在内存中
就直接更新,而如果这个数据页还没有在内存
中的话,在不影响数据一致性的前提下, InooDB会将这些更新操作缓存在change buffer
中 ,这样就不需要从磁盘
中读入这个数据页了。 -
2、在下次查询需要访问这个
数据页
的时候,将数据页
读入内存,然后执行change buffer
中与这个页有关的操作。通过这种方式就能保证这个数据逻辑的正确性。 -
3、将
change buffer
中的操作应用到原数据页,得到最新结果的过程称为merge
。除了访问这个数据页
会触发merge外,系统有后台线程会定期
merge。在数据库正常关闭(shutdown)
的过程中,也会执行merge操作 -
4、如果能够将更新操作先记录在
change buffer
,减少读磁盘
,语句的执行速度会得到明显的提升。而且,数据读入内存是需要占用buffer pool
的,所以这种方式还能够避免占用内存
,提高内存利用率
3.2、唯一索引更新过程
唯一索引
的更新就不能使用change buffer
四、change buffer 的使用场景
-
1、
普通索引
和唯一索引
应该怎么选择?其实,这两类索引在查询能力上是没差别的,主要考虑的是对更新性能
的影响。所以,建议你尽量选择普通索引
-
2、在实际使用中会发现,
普通索引
和change buffer
的配合使用,对于数据量大
的表的更新优化还是很明显的 -
3、如果所有的更新后面,都马上
伴随着对这个记录的查询
,那么你应该关闭change buffer
。而在其他情况下,change buffer
都能提升更新性能 -
4、由于
唯一索引
用不上change buffer
的优化机制,因此如果业务可以接受
,从性能角度出发建议优先考虑非唯一索引
。但是如果"业务可能无法确保"的情况下,怎么处理呢?-
首先
,业务正确性优先
。我们的前提是“业务代码已经保证不会写入重复数据”的情况下,讨论性能问题。如果业务不能保证,或者业务就是要求数据库来做约束,那么没得选,必须创建唯一索引
。这种情况下,本节的意义在于,如果碰上了大量插入数据慢、内存命中率低的时候,给你多提供一个排查思路 -
然后
,在一些“ 归档库 ”的场景,你是可以考虑使用唯一索引的。比如,线上数据只需要保留半年,然后历史数据保存在归档库。这时候,归档数据已经是确保没有唯一键冲突了。要提高归档效率,可以考虑把表里面的唯一索引改成普通索引
-
网友评论