一、索引的常见模型
1.哈希表
哈希表适用于等值查询的场景,其优点是插入和删除快,但是范围查询需要遍历整个储存的值,所以查询比较慢。
比如 Memcached 及其他一些 NoSQL 引擎用的就是哈希表
2.数组
数组在等值查询和范围查询表现都比较优秀,查询的时间复杂度为O(log(N)),但是其缺点就是插入和删除需要挪动数据,其成本比较大,所以数组结构适用于静态储存引擎。
3.多叉树
为什么不用二叉树的原因是,二叉树在数据量比较大时,进行查找时会增加数据块,引擎的寻址时间比较慢,大概是10ms,这样就会占用大量的时间。
二、InnoDB索引模型
InnoDB索引的数据结构是B+tree,分为主键索引和普通索引。
1.建索引语句
mysql> create table T(
id int primary key,
k int not null,
name varchar(16),
index (k))engine=InnoDB;
2.主键索引和普通索引的区别
主键索引在InnoDB引擎里面又称为聚族索引,非主键索引在InnoDB里面又称为二级索引。
每个索引都对应一个B+tree,聚族索引只需要查次,而二级索引需要回表(二级索引需要先在自己的B+tree找到主键,再用主键在主键B+tree再搜索一次)。
所以优先考虑用聚族索引。
三、索引维护
1.什么时候索引的效率会降低?
-a.从中间插入的时候,原本中间的数据会往后移动。
-b.页分裂:当一页放不下数据的时候,会申请一个新的页,并且会把原本在改页的数据分一部分过去,效率会降低约50%。
-c.没有用主键自增。
2.主键自增固然好,什么时候不用呢?
当只有一个索引,并且该索引必须是唯一索引,也就是所说的KV场景。
3.以下重建二级索引和重建主键索引有什么不妥?
//重建二级索引
alert table T drop index k;
alert table T add index(k);
//重建主键索引
alert table T drop primary key;
alert table T add primary key(id);
四、覆盖索引
由于覆盖索引可以减少树的搜索次数,显著提升查询性能,所以使用覆盖索引是一个常用的性能优化手段。覆盖索引是指,索引上的信息足够满足查询请求,不需要再回到主键索引上去取数据
//建表语句
mysql> create table T (
ID int primary key,
k int NOT NULL DEFAULT 0,
s varchar(16) NOT NULL DEFAULT '',
index k(k))
engine=InnoDB;
insert into T values(100,1, 'aa'),(200,2,'bb'),(300,3,'cc'),(500,5,'ee'),(600,6,'ff'),(700,7,'gg');
1.怎么优化如下sql?
select * from T where k between 3 and 5
以上sql的执行流程
a.在 k 索引树上找到 k=3 的记录,取得 ID = 300;
b.再到 ID 索引树查到 ID=300 对应的 R3;
c.在 k 索引树取下一个值 k=5,取得 ID=500;
d.再回到 ID 索引树查到 ID=500 对应的 R4;
e.在 k 索引树取下一个值 k=6,不满足条件,循环结束。(为什么有这步?)
//优化后的sql及原理
select ID from T where k between 3 and 5
因为上面的sql进行查询需要进行回表,如果只查询ID,就不用进行回表。也就是说,在这个查询里面,索引 k 已经“覆盖了”我们的查询需求,我们称为覆盖索引。
2.建立联合索引的意义?
建立联合索引:比如身份证和姓名的联合索引,在进行根据姓名查询身份证或者反之,就可以进行覆盖索引,从而提高效率,但是这会付出维护成本。
四、索引优化的三个原则
覆盖索引、最左前缀原则、索引下推。
覆盖索引:可以覆盖二级索引回表从而提高效率
最左前缀原则:联合索引从左往右字段M或者索引是从左往右的N依次使用的,只有使用了左边的索引右边的索引才会生效。
因而索引从左往右的排序也尤为重要
索引下推:是MYSQL5.6之后才推出的功能,在sql语句进行条件查询的时候,先根据索引项的条件进行筛选,把不满足的条件给过滤掉,减少了回表,从而提高了效率。
五、思考题
以下建表语句使用了多个主键
CREATE TABLE
geek
(
a
int(11) NOT NULL,b
int(11) NOT NULL,
c
int(11) NOT NULL,d
int(11) NOT NULL,
PRIMARY KEY (a
,b
),
KEY c
(c
),
KEY ca
(c
,a
),
KEY cb
(c
,b
)
) ENGINE=InnoDB;
因为业务员需求需要做a,b联合主键,但是"ca"和"cb"为什么要创建呢?同事给出的解释是因为有两条查询语句,你认为合理吗?
select * from geek where c=N order by a limit 1;
select * from geek where c=N order by b limit 1;
解答:建议cb保留,ca去掉,因为,ab是联合索引排序规则是先按a排序再按b排序,有c为主键,所以ca本来就是有序的,但是不能保证cb所以cb要保留。
六、sql优化问题
1.下面两条语句有什么区别,为什么都提倡使用2:
1.select * from T where k in(1,2,3,4,5)
2.select * from T where k between 1 and 5
因为1树要搜索5次,2只搜索一次。(为什么2只搜索一次)
2.关于军规
一张表的索引最好不要超过5个。