索引
为何要有索引?
索引的功能就是加速查找
一般的应用系统,读写比例在10:1左右,而且插入操作和一般的更新操作很少出现性能问题,在生产环境中,我们遇到最多的,也是最容易出问题的,还是一些复杂的查询操作,因此对查询语句的优化显然是重中之重。说起加速查询,就不得不提到索引了。
什么是索引?
索引在MySQL中也叫做“键”,是存储引擎用于快速找到记录的一种数据结构。索引对于良好的性能非常关键,尤其是当表中的数据量越来越大时,索引对于性能的影响愈发重要。
B+Tree
B+树是一个平衡的多叉树。
InnoDB存储引擎就是用B+Tree实现其索引结构。
在B+Tree中,所有的数据都是存放在叶子节点上的,并且是按照键值大小顺序存放的,而非叶子节点上只存储键值信息,这样可以有效的加大每个节点存储的键值数量,从而降低B+Tree的高度。
数据库中的B+树索引可以分为聚集索引(clustered index)和辅助索引(secondary index)
相同点:
其内部都是B+树的形式,即高度是平衡的,叶子结点存放着所有的数据。
不同点:
聚集索引的叶子结点存放的是整张表的行记录数据
辅助索引的叶子节点不包含行记录的全部数据。
MySQL常用索引
普通索引INDEX:加速查找 唯一索引: -主键索引 PRIMARY KEY:加速查找+约束(不为空、不能重复) -唯一索引 UNIQUE:加速查找+约束(不能重复) 联合索引: -PRIMARY KEY(id,name):联合主键索引 -UNIQUE(id,name):联合唯一索引 -INDEX(id,name):联合普通索引
创建/删除索引的语法
#方法一:创建表时 CREATE TABLE 表名 ( 字段名1 数据类型 [完整性约束条件…], 字段名2 数据类型 [完整性约束条件…], [UNIQUE | FULLTEXT | SPATIAL ] INDEX | KEY [索引名] (字段名[(长度)] [ASC |DESC]) ); #方法二:CREATE在已存在的表上创建索引 CREATE [UNIQUE | FULLTEXT | SPATIAL ] INDEX 索引名 ON 表名 (字段名[(长度)] [ASC |DESC]) ; #方法三:ALTER TABLE在已存在的表上创建索引 ALTER TABLE 表名 ADD [UNIQUE | FULLTEXT | SPATIAL ] INDEX 索引名 (字段名[(长度)] [ASC |DESC]) ; #删除索引:DROP INDEX 索引名 ON 表名字;
删除主键索引
如果一个主键是自增长的,不能直接删除该列的主键索引,应当先取消自增长,再删除主键索引。
alter table 表名 drop primary key; 当主键为自增长时 alter table t1 modify id int ; 【重新定义列类型】 alter table t1 drop primary key;
正确使用索引
1、应该选择区分度高的字段作为索引字段
2、范围问题(:>、>=、<、<=、!= 、between...and...、like、),范围过大,即便是有索引速度也会很慢
3、索引字段一定不能参与计算:select * from s1 where salary*12 > 200000;
4、最左前缀匹配原则:
应该把范围查询字段往右放
联合索引的第一个字段必须出现在查询条件中,顺序无所谓,否则无法命中索引。换句话说只要联合索引的第一个字段出现在查询条件中,即可命中索引。
注意事项
- 避免使用select * - 使用count(1)或count(列) 代替 count(*) - 创建表时尽量使用 char 代替 varchar - 表的字段顺序,固定长度的字段优先 - 组合索引代替多个单列索引(经常使用多个条件查询时) - 尽量使用短索引 - 使用连接(JOIN)来代替子查询(Sub-Queries) - 连表时注意条件类型需一致 (select name from user where email=66666)
视图
视图(View)是一种虚拟存在的表,对于使用视图的用户来说基本上是透明的。视图并不在数据库中实际存在,行和列数据来自定义视图的查询中使用的表,并且是在使用视图时动态生成的。
使用视图我们就可以将一些复杂的查询结果存到了一张临时表中,以后我们再次使用这些数据时,不用进行复杂的查询,直接使用视图就行。
但视图有明显地效率问题,并且视图是存放在数据库中的,如果我们程序中使用的sql过分依赖数据库中的视图,即强耦合,也就意味着扩展sql极为不便,因此并不推荐使用。
创建视图或修改视图。
创建视图需要有 create view的权限,并且对于查询涉及的列有 SELECT 权限。如果使用create or replace或者alter 修改视图,那么还需要该视图的 drop 权限。
语法:create view 视图名称 as SQL语句 create view teacher_view as select tid from teacher where tname='李平老师'; #于是查询李平老师教授的课程名的sql可以改写为 select course_name from course where teacher_id = (select tid from teacher_view);