数据库:mysql基础(七)--视图和索引
-
视图
-
什么是视图?
- 举个例子:假如你是数据库的管理员,数据库中存的着前面我们一直用的emp员工信息表.这时候有个用户客户端希望查看这个表,但是这个表中的sal工资字段的内容,你不希望他看到,那么用什么办法解决这个问题呢?我们很容易想到的方法是,我创建另外一张emp_bak(名字随意,只是举例)表.将emp表中不含有sal字段的内容复制过来,供你查看.
- 但是上面的处理方法有什么缺点?一:两张表只有很少的部分不同,其他的一模一样,这就造成了存储空间的浪费.二.最主要的还是在维护方面.假如emp维护了,emp_bak也要跟进维护,这样维护的成本就提高了.那除了这种方式还有其他方式么?这就引出了下面我们将要说的视图.
- 概念:视图是一张虚拟表,并不在数据库中以存储数据值集的形式存在--没有真实的物理存在;在引用过程中依据基表动态生成。
- 虽然没有真实的物理存储,但是虚拟表也是表,完全可以当做表来用.但是视图一般不做增删改,绝大多数都是作为查询使用的.
-
语法:
-
#查看10号部门所有员工信息.. create view view_emp as select * from emp where deptno = 10; #查询上面视图中的内容,这样就只显示部门编号为10号员工信息,其他的信息就看不到了 #调用视图,因为它没有物理存在,其实就是可以理解为它是一段sql select * from view_emp; #既然视图是以底层基表为基础的,那么我们能不能通过视图将基表修改呢? update view_emp set ename = 'kitty' where empno = 7839; #上面这段修改语句是否能执行呢?视图数据是否会被修改?基表数据是否能被修改呢?--思考一下这三个问题 #三个问题答案都是肯定的.. #注: #1.通过视图可以修改基表数据 #2.一般视图只做查询 #那么思考一下下面的语句结果: create view view_emp as select * from emp where deptno = 10; update view_emp set deptno = 20; select * from view_emp; #结果是什么呢? #第二句会通过视图把基表的deptno都修改为20,但是第三句语句执行后,发现结果是空的,为什么呢? #因为通过视图将基表修改后,不存在depntno=10的数据了,但是视图创建的语句中映射的还是根据deptno=10来进行的,我们创建视图的时候永远只是映射当时创建时候的条件.这里只找10号部门的,但是这里没有10号了,疾苦为空了.
上面的问题主要是:视图修改的条件和创建视图的条件一样,这样的事情我们不应该让它发生.虽然可以修改视图,但是创建视图的条件是不应该修改的.为了防止这样的问题发生,就可以在创建视图的时候再后面加上with check opton.
-
#痛痒是查询部门编号为10的员工信息,但是后面加上了with check option create view view_emp as select * from emp where deptno = 10 with check option; #这样做的目的就是保证视图里面的查询条件不能被修改 #此时如果再执行 update view_emp set deptno = 20; #就会报错,不能执行了,但是除了这个字段,其他的字段是可以修改的.保证视图的安全.
如果创建的视图中带有where等条件,则with check option 子句可以保证让你只能在视图的条件之内对视图进行DML。
-
删除视图
-
drop view view_emp;
-
-
-
视图的优点
- 安全性:保证数据不泄密.那么直接将表给出来进行操作将会造成泄密,那么可以通过创建视图,把相应视图的权限给出来即可保证数据的安全。
- 高效性:多表连接效率较低.复杂的连接查询,每次执行时效率比较低,可以考虑新建视图,每次从视图中获取,将会提高效率。
- 定制化数据:将常用的字段放置视图
-
-
索引
-
- 上表是我们一直在用的员工表,后面的部门信息有些差异,但不影响我们下面说的东西,empno是主键
-
#我们要查询一条员工SCOTT的信息,他的编号是7788,那么我们可以用下面的方法查询 select * from emp where empno = 7788; select * from emp where ename = 'SCOTT'; #这两个都是可以查询到他信息的语句.那么有没有差别呢?
下面介绍一个东西:性能指标
-
一般情况下,查询至少要达到range级别,最好达到ref.这样效率会快一些.
-
接下来我们继续说上面的两条语句的差异:
-
虽然都是查询,但是查询和查询之间是有差异的.为什么会有差异呢?下面给大家介绍一个东西:解释器(解释计划任务)--查看sql执行的性能的.可以在sql语句前面加上explain关键字来查看该sql语句性能的 .
-
那我们可以发现,假如表的记录很多很多,那这个的效率就很低了.下面再看一下用empno做为查询条件的情况
-
我们看到 type 的值是const,rows的值是1..显而易见的是这个的效率很快..我们将上面的两种方式结合起来看,我们发现,如果使用主键进行查询的话,它的效率会比使用普通字段作为查询条件高很多.随着数据量的增大,这个差距会随之增大.那为什么会产生这么一个差距呢?那就是我们下面要说的索引.
-
-
什么是索引?
-
提升查询效率创建的数据解耦---我们可以类比一下书的目录.(表就是类比为一本书.如果书没有目录,查找东西就要一页一页翻找,页数少还可以,但是很厚的书逐页翻找效率太低了.如果这本书存在目录,这样我需要找内容的时候们可以先看目录,大概知道了需要的内容在那一页,再去翻到这一页就行了.效率快很多)
-
默认是B-Tree索引(当然还有很多其他的:比如位图,反向等等.).
-
这里我们说一下B-Tree索引是如何提高查询效率的:
-
假如说有一张emp表,记录数为1024.如果我们没有设置索引的情况下,从这张表中随机查询一条数据的速度平均值大致为多少呢?因为没有索引,我们要全表扫描,无论查询哪一个数据都要从开头一个一个查找,故存在目标项在第一个,那我们就只查询1次,最惨的就是在最后一个,要查1024次.所以我们大致可以估计为1024/2;
-
上面是没有索引的情况下的查询,下面说一下使用B-TREE索引的情况.其是使用二叉树实现的,我想有学过数据结构的同学们到这里就可以联想到为什么效率会快了吧.没有基础的朋友可以搜索一下二叉树的信息了解一下.那么结合这个emp表的1024条记录,理想状态下我们最多只需要查找10次(2的10次方是1024)就可以找到了.那么和上边的比较一下我们发现,使用索引的效率要大大提高.
-
而mysql中准确来说使用的是B+树.也就是分支不止两个,有可能有多个,这样树的深度会更浅,查找速度更快.另外一个,在每个节点当中存储的是记录的地址.通过记录地址直接找到记录.
-
-
-
索引的语法
-
索引可以分为
-
普通索引--为了提高效率
-
#创建索引:create index index_name on tname(fie1...);
-
create index index_name on emp(ename);
-
- #删除索引:drop index index_name on tname;
-
drop index index_name on emp;
-
-
唯一索引--和普通索引最大的区别:这个索引列必须唯一
- #创建索引:create unique index index_name on tname(fie);
- 大家发下没有,上面举得例子中,我们并没有显示的穿件索引,那为什么查询效率会变高呢?那是因为我们在设置主键,唯一约束的时候就自动创建了索引.主键索引,唯一索引等.索引.我们以前添加的唯一约束,其实就是唯一索引.alter table方式添加的约束也是添加索引.
- 这里标注一下:主键,唯一约束,外键等都会添加索引
-
-
-
适合场景
- 表的数据量足够大---索引页需要单独空间进行维护的,表的数据量大才值得去维护.
- 增删改较少的表 --- 索引列不能经常变化,索引维护需要花费时间
- 高基数列---列的---这一列的数据大多数不能相同.
- 注意:
- 1.索引需要单独维护,索引不宜添加过多。
- 2.将条件列设置索引
- 3.索引失效状况--....具体哪些情况会失效,后面我们说优化的时候再介绍.
-