63-MySQL普通索引与唯一索引比较

一、准备数据

  • 创建表
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的优化机制,因此如果 业务可以接受 ,从性能角度出发建议优先考虑非唯一索引。但是如果"业务可能无法确保"的情况下,怎么处理呢?

    • 首先业务正确性优先 。我们的前提是“业务代码已经保证不会写入重复数据”的情况下,讨论性能问题。如果业务不能保证,或者业务就是要求数据库来做约束,那么没得选,必须创建唯一索引。这种情况下,本节的意义在于,如果碰上了大量插入数据慢、内存命中率低的时候,给你多提供一个排查思路
    • 然后,在一些“ 归档库 ”的场景,你是可以考虑使用唯一索引的。比如,线上数据只需要保留半年,然后历史数据保存在归档库。这时候,归档数据已经是确保没有唯一键冲突了。要提高归档效率,可以考虑把表里面的唯一索引改成普通索引

你可能感兴趣的:(63-MySQL普通索引与唯一索引比较)