唯一索引or普通索引?阿里强制唯一索引?

唯一索引or普通索引?阿里强制唯一索引?

1、 唯一索引和普通索引区别

先谈谈两者在查询操作上的区别,假设我们对一张User表建立mobile字段的索引。

1. 查询操作

若执行查询语句select * from user where mobile=123456789;

唯一索引由于具有唯一性,当查询时将唯一字段作为条件时,查询到一个记录后将立即返回。

普通索引由于不保证唯一性,直到遇见不符合条件的才返回。

但实际上普通索引与唯一索引在性能上是微乎其微的,因为在查询语句的主要时间是花在了索引磁盘块的读取和数据页的读取上,两者读取磁盘块的个数基本一致。基本一致就是指特殊情况普通索引可能会多一个IO,即该记录正好在数据页的最后一个,那么还会读取下一个数据页(概率极低)。

所以得出的结论是唯一索引跟普通索引在查询上性能相当。(PS:该结论先打个问号???



2.更新操作

在聊更新操作之前先谈谈Change Buffer。MySQL的数据数据存储是包含两个部分的:磁盘和内存。在内存中有一个内存缓冲池,缓存数据页和索引页以提高读效率,Change Buffer以提高写效率

Change Buffer用于当索引页不在缓冲池中时,对数据页进行写操作时,并不会立即将磁盘加载到缓冲池然后写入数据,而是仅仅记录缓冲变更信息,等到读取数据时再将数据合并到缓冲池中。该数据页缓冲变更越多,提升的写操作性能越高。(PS:所以如果写入该数据后马上读取该数据,性能反而会降低)

但是,遗憾的是,change Buffer并不支持唯一索引

唯一索引在写入操作时需要做唯一性检查,change buffer无法做到!

所以得出结论:唯一索引在写操作时性能会低于普通索引。

所以在建索引选择时,尽量选择普通索引,而不去选择唯一索引。除非非常需要唯一性校验,防止插入脏数据!

(该结论先打个问号???)






2、阿里巴巴Java开发手册:强制使用唯一索引

通过前面的理论分析,得出了唯一索引和普通索引的选择问题,但是在阅读阿里巴巴Java开发手册时,有如下的强制规定,并作出了解释:

唯一索引or普通索引?阿里强制唯一索引?

该规定在索引规约的第一条,并且是强制的,可见其重要性。阿里给出了两个理由:明显提升查找速度和防止脏数据的产生。

第二条可以理解,没有唯一性校验,无论怎么校验都可能造成唯一性字段重复,自己写代码校验效率还可能低于MySQL的唯一性校验。

第一条明显提升查找速度怎么理解?查找时唯一索引找到记录立即返回能明显提升查找速度?自己建表试验如下:


实验:利用之前的一个数据库表,里面自己写入了100万条记录,id为主键,mobile字段保证唯一性。

  1. 利用mobile建立唯一性索引,并利用mobile字段走索引查询。

    唯一索引or普通索引?阿里强制唯一索引?

唯一索引or普通索引?阿里强制唯一索引?

  1. 删除索引,利用mobile字段建立普通索引。然后清除缓存…重新执行语句

唯一索引or普通索引?阿里强制唯一索引?

唯一索引or普通索引?阿里强制唯一索引?

两者的执行速度一样!!!





实验二:加大数据量重试

这时想到的是加数据,自己又生成了400万数据,加入数据库中,再次执行…

唯一索引or普通索引?阿里强制唯一索引?

使用唯一索引,查询结果如下

唯一索引or普通索引?阿里强制唯一索引?

使用普通索引,查询结果如下:

唯一索引or普通索引?阿里强制唯一索引?

多次反复试验,中间避免缓存,甚至重启MySQL,结果都是执行时间相当(1.35s)左右。

500万条数据没看出明显提升。

但阿里巴巴这句话肯定是经过多年实践磨砺出来的,是我试验哪里出了问题?还是数据量不够?希望大家指教
但唯一性索引在保证脏数据上还是非常重要的!毕竟数据库大多数读多写少,没有多大必要去提升写的微弱效率而去写脏了数据库。

个人还是比较倾向于唯一索引。