上文提到了用自增主键作聚簇索引列,能够方便插入操做。但高并发场景下,主键的上界集中了全部的插入,可能致使间隙锁竞争(间隙锁是innodb中行锁的一种, 可是这种锁锁住的却不止一行数据,他锁住的是多行,是一个数据范围。间隙锁的主要做用是为了防止出现幻读;对符合条件的已有数据记录的索引项加锁;对于键值在条件范围内但并不存在的记录,叫作“间隙(GAP)”,InnoDB也会对这个“间隙”加锁,这种锁机制就是所谓的间隙锁(Next-Key锁))。同时,自增字段的锁机制也可能成为热点。mysql
指包含了全部须要查询字段的索引。覆盖索引的优点以下sql
覆盖索引的核心是:索引结构保存相关列的值。因此,通常用在B+树索引。并发
前篇提到,索引的三个用途是:SELECT、ORDER BY、GROUP BY。高并发
若是索引不能覆盖全部列,则读取数据的过程是:...->索引中读取n行相关信息->查找n行->索引读取n+1行数据->...。这样比顺序扫描全表还慢。因此使用索引扫描排序须知足条件:性能
CREATE TABLE test ( ID INT NOT NULL PRIMARY KEY, A INT NOT NULL, B text NOT NULL, UNIQUE(ID), INDEX(ID) ) ENGINE=InnoDB;
上述表的主键限制、惟一限制都是经过索引实现的。因此,这张表的ID列上,存在三个索引。这种冗余是没有意义的。优化
或者说,把(A)索引扩展为(A, ID),这样也是没有意义的。聚簇索引的二级索引的叶节点,自己就包含主键信息。spa
SELECT A,B from test where A=2;
对上述查询,若是咱们扩展索引(A)为(A, B),就能够利用覆盖索引,加速查询。但B字段很长,会致使只取A字段时性能降低。此时,能够同时保留(A)和(A, B)索引,虽然对A列来讲是冗余索引,但总体查询的性能提高了 。code
减小锁的行数,有两个直接好处:1.减小加锁开销 2.减小事务间的竞争。排序
InnoDB在访问行时才会加锁;因此若是索引能帮助筛选掉不须要访问的行,就能减小加锁量。索引
不然,InnoDB须要作全表扫描,锁住全部的行。
InnoDB在二级索引上使用共享锁,在访问主键索引时用排他锁。因此,在二级索引访问时,其余事务依然能够写入数据,那么就没法使用覆盖索引。
mysql> SELECT <cols> FROM profiles WHERE sex='M' ORDER BY rating LIMIT 10;
这个查询中,可建立(sex, rating)索引帮助排序,不要局限于where后的条件。
翻页查询
mysql> SELECT <cols> FROM profiles WHERE sex='M' ORDER BY rating LIMIT 100000, 10; mysql> SELECT <cols> FROM profiles INNER JOIN ( -> SELECT <primary key cols> FROM profiles -> WHERE x.sex='M' ORDER BY rating LIMIT 100000, 10 -> ) AS x USING(<primary key cols>);
偏移量越大,会须要更多的扫描来丢弃不须要的数据;能够在业务上限制翻页数量。下面一条是一种优化查询,先用覆盖索引(3中创建的索引)快速查询到主键,而后取值。