MySQL视图与索引

1、 视图

1.1什么是视图

视图通过以定制的方式显示来自一个或多个表的数据

视图是一种数据库对象,用户可以像查询普通表一样查询视图

视图内其实没有存储任何数据,它只是对表的一个查询

视图的定义保存在数据字典内,创建视图所基于的表称为“基表”

1.2 为什么需要视图

例如经常要对emp和dept表进行连接查询,每次都要做表的连接,写同样的一串语句,同时由于工资列队数据比较敏感,对外要求不可见。对这样的问题就可以通过视图来解决。

1.3 视图的作用和优点

作用:

  • 控制安全

  • 保存查询数据

优点:

  • 提供了灵活一致级别安全性。

  • 隐藏了数据的复杂性

  • 简化了用户的SQL指令

  • 通过重命名列,从另一个角度提供数据

1.4 创建视图

CREATE [OR REPLACE] VIEW 视图名 [(列名[, 列名]...)]
AS select statement
[WITH [CASCADED | LOCAL] CHECK OPTION];
说明:
(1)as select statement表示select语句;
(2)WITH [CASCADED | LOCAL] CHECK OPTION表示视图在更新时,保证在视图的权限范围之内,CASCADED为默认值,表示更新视图时要满足所有相关视图和表的条件,local表示更新视图时满足该视图本身定义的条件即可。

#创建视图, emp_view_2, 包括2号部门的所有雇员信息:
mysql8.0 [chap04]>create view emp_view_2 as select employ_id,salary from employee where dept_id=2;
mysql8.0 [chap04]>select * from emp_view_2;
+-----------+--------+
| employ_id | salary |
+-----------+--------+
|       101 |  10000 |
|       102 |   9000 |
|       104 |   5000 |
+-----------+--------+

1.5 视图使用规则

  1. 视图必须有唯一命名。

  1. 在mysql中视图的数量没有限制。

  1. 创建视图必须从管理员那里获得必要的权限。

  1. 视图支持嵌套,也就是说可以利用其他视图检索出来的数据创建新的视图。

  1. 在视图中可以使用ORDER BY,但是如果视图内已经使用该排序子句,则视图的ORDER BY将覆盖前面的ORDER BY。

  1. 视图不能索引,也不能关联触发器或默认值。

  1. 视图可以和表同时使用。

1.6 修改视图

#使用CREATE OR REPLACE VIEW 语句修改emp_view_2 视图,为每个列指定列名。或在子查询中指定别名使用ALTER VIEW 语句修改EMP_V_10 视图,为每个列指定列名,也可以在select查询中指定别名。在以上语句中字段与子查询中的字段必须一一对应,否则就别指定。
mysql8.0 [chap04]>create or replace view emp_view_2 (id,salary) as select employ_id,salary from employee where dept_id=2;
mysql8.0 [chap04]>alter view emp_view_2 (id,salary,dept_id) as select employ_id,salary,dept_id from employee;

#创建复杂视图,创建一个从两个表中查询数据,并进行分组计算的复杂视图。
mysql8.0 [chap04]>select e.dept_id,group_concat(e.employ_id) employee,d.dept_name,avg(e.salary),min(e.salary),max(e.salary) from employee e,dept d  where d.dept_id=e.dept_id group by e.dept_id,d.dept_name;
mysql8.0 [chap04]>create view emp_view_salary as select e.dept_id,group_concat(e.employ_id) employee,d.dept_name,avg(e.salary),min(e.salary),max(e.salary) from
employee e,dept d  where d.dept_id=e.dept_id group by e.dept_id,d.dept_name;
mysql8.0 [chap04]>select * from emp_view_salary;
+---------+-------------+-----------+---------------+---------------+---------------+
| dept_id | employee    | dept_name | avg(e.salary) | min(e.salary) | max(e.salary) |
+---------+-------------+-----------+---------------+---------------+---------------+
|       1 | 100         | boss      |          NULL |          NULL |          NULL |
|       2 | 101,102,104 | sale      |     8000.0000 |          5000 |         10000 |
|       3 | 105         | hr        |     8000.0000 |          8000 |          8000 |
|       4 | 103,106     | tech      |    11000.0000 |         10000 |         12000 |
+---------+-------------+-----------+---------------+---------------+---------------+

1.7 删除视图

#删掉视图不会导致数据的丢失,因为视图是基于数据库的表之上的一个查询定义.
DROP VIEW view_name;
mysql8.0 [chap04]>drop view emp_view_2;

2、 索引

索引是一种特殊的数据库结构,可以用来快速查询数据库表中的特定记录。索引是提高数据库性能的重要方式。

2.1 什么是索引

模式(schema)中的一个数据库对象
在数据库中用来加速对表的查询
通过使用快速路径访问方法快速定位数据,减少了磁盘的I/O
与表独立存放,但不能独立存在,必须属于某个表
由数据库自动维护,表被删除时,该表上的索引自动被删除。
索引的作用类似于书的目录,几乎没有一本书没有目录,因此几乎没有一张表没有索引。

2.2 索引优缺点

索引的优点是可以提高检索数据的速度,这是创建索引的最主要的原因;对于有依赖关系的子表和父表之间的联合查询时,可以提高查询速度;使用分组和排序子句进行数据查询时,同样可以显著节省查询中分组和排序的时间。

索引的缺点是创建和维护索引需要耗费时间,耗费的时间随着数据量的增加而增加;索引需要占用物理空间,每一个索引要占一定的物理空间;增加、删除和修改数据时,要动态的维护索引,造成数据的维护速度降低了。

2.3 索引分类

按物理存储分类,索引分为聚簇索引和非聚簇索引两种,聚簇索引是按照数据存放的物理位置为顺序的,而非聚簇索引就不一样了;聚簇索引能提高多行检索的速度,而非聚簇索引对于单行的检索很快。

按字段特性,MySQL的索引包括普通索引、惟一性索引、全文索引、单列索引、多列索引和空间索引等。

2.4 索引的设计原则

为了使索引的使用效率更高,在创建索引的时候必须考虑在哪些字段上创建索引和创建什么类型的索引。索引的设计原则:

  1. 选择惟一性索引

  1. 为经常需要排序、分组和联合操作的字段建立索引

  1. 为常作为查询条件的字段建立索引

  1. 限制索引的数目

  1. 尽量使用数据量少的索引

  1. 尽量使用前缀来索引

  1. 删除不再使用或者很少使用的索引

2.5 创建索引

创建索引是指在某个表的一列或多列上建立一个索引,以便提高对表的访问速度。创建索引有三种方式,这三种方式分别是创建表的时候创建索引、在已经存在的表上创建索引和使用ALTER TABLE语句来创建索引。

#创建表的时候可以直接创建索引,这种方式最简单、方便。其基本形式如下:
CREATE TABLE 表名 ( 
    列名 数据类型 [完整性约束条件],列名 数据类型 [完整性约束条件],…,
[UNIQUE | FULLTEXT | SPATIAL]  [INDEX | KEY] [index_name]  (key_part,...) [index_option] 
);

#在已经存在的表上,可以直接为表上的一个或几个字段创建索引。基本形式如下:
CREATE [ UNIQUE | FULLTEXT | SPATIAL ]  INDEX 索引名
ON 表名 (属性名 [ (长度) ]);


#在已经存在的表上,可以通过ALTER TABLE语句直接为表上的一个或几个字段创建索引。基本形式如下:
ALTER  TABLE 表名  ADD  [ UNIQUE | FULLTEXT | SPATIAL ]  INDEX [索引名] (属性名 [ (长度) ]);

1、创建普通索引

# 创建表的时候同时创建索引
mysql8.0 [chap06]>create table index1(
    -> id int,
    -> name char(30),
    -> gender char(1),
    -> index(id)
    -> );
#查看创建表的信息
mysql8.0 [chap06]>show create table index1;
#查看表的索引信息:show index from 索引名;
mysql8.0 [chap06]>show index from index1;
#在表里面插入数据
mysql8.0 [chap06]>insert into index1 values (1,'xiaoming','M'),(2,'xiaohong','F'),(3,'xiaohei','M'),(4,'xiaobai','M'),(5,'xiaolan','F'),(6,'xiaolv','F');
mysql8.0.30 [example]>create table t1 select * from index1;
#查看MySQL如何在内部执行查询
mysql8.0.30 [example]>explain select * from t1 where id=1\G
*************************** 1. row ***************************
           id: 1
  select_type: SIMPLE
        table: t1
   partitions: NULL
         type: ALL
possible_keys: NULL
          key: NULL
      key_len: NULL
          ref: NULL
         rows: 6
     filtered: 16.67
        Extra: Using where
1 row in set, 1 warning (0.01 sec)

#如上所示,mysql必须扫描包含6行数据的整个表数据才能查找到name=xiaoming的数据
mysql8.0 [chap06]>explain select * from index1 where id=1\G
*************************** 1. row ***************************
           id: 1
  select_type: SIMPLE
        table: index1
   partitions: NULL
         type: ref
possible_keys: id
          key: id
      key_len: 5
          ref: const
         rows: 1
     filtered: 100.00
        Extra: NULL
#如上所示,通过索引,mysql只需要扫描一行数据就扫描到了id=1的行

#给已经存在的index1表创建索引:CREATE  INDEX 索引名 ON 表名 (属性名 [ (长度) ]);
mysql8.0 [chap06]>create index n on index1 (name);
mysql8.0 [chap06]>explain select * from index1 where name='xiaohong'\G
*************************** 1. row ***************************
           id: 1
  select_type: SIMPLE
        table: index1
   partitions: NULL
         type: ref
possible_keys: n
          key: n
      key_len: 121
          ref: const
         rows: 1
     filtered: 100.00
        Extra: Using index condition
1 row in set, 1 warning (0.00 sec)

#在已经存在的index表上创建索引:ALTER TABLE table_name ADD INDEX [index_name] (column(length))
mysql8.0 [chap06]>alter table index1 add index (gender);

# 删除索引:DROP INDEX index_name ON table
mysql8.0 [chap06]>drop index id on index1;

2、创建唯一性索引

#创建表时创建唯一性索引
mysql8.0 [chap06]>create table index2(
    -> id int unique,
    -> name char(20),
    -> unique key (id)
    -> );

#在已经存在的表上创建索引:CREATE UNIQUE INDEX 索引名 ON 表名(column(length));
mysql8.0 [chap06]>create unique index name on index2 (name);
#在已经存在的表上创建索引:ALTER TABLE 表名 ADD UNIQUE [index] [indexName] (column(length));

3、创建全文索引(FULLTEXT)

全文索引主要用来查找文本中的关键字,只能在 CHAR、VARCHAR 或 TEXT 类型的列上创建;

全文索引允许在索引列中插入重复值和空值;

对于较大的数据集,将你的资料输入一个没有FULLTEXT索引的表中,然后创建索引,其速度比把资料输入现有FULLTEXT索引的速度更快;

不过切记对于大容量的数据表,生成全文索引是一个非常消耗时间非常消耗硬盘空间的做法。

#只能创建在char,varchar或text类型的字段上
mysql8.0 [chap06]>create table index3(
    -> id int,
    -> info char(20),
    -> fulltext index (info)
    -> );
mysql8.0 [chap06]>insert into index3 values (1,'test'),(2,'english test'),(3,'tech');
    
#为已有表添加全文索引:CREATE FULLTEXT INDEX 索引名称 ON 表名(column(length));

#为已有表添加全文索引:ALTER TABLE 表名 add fulltext index [索引名](column(length));

4、创建单列索引

mysql8.0 [chap06]>create table index4( id int, name char(30), index (name) );


#为已有表创建单列索引
mysql8.0 [chap06]>create index id on index4 (id);
    
#为已有表创建单列索引:ALTER TABLE 表名 add index [索引名](column(length));

5、创建多列索引

使用多列索引时一定要特别注意,只有使用了索引中的第一个字段时才会触发索引。如果没有使用索引中的第一个字段,那么这个多列索引就不会起作用。也就是说多个单列索引与单个多列索引的查询效果不同,因为执行查询时,MySQL只能使用一个索引,会从多个索引中选择一个限制最为严格的索引。

mysql8.0 [chap06]>create table index5(
    -> id int,
    -> name char(30),
    -> gender char(1),
    -> age int,
    -> index (name,gender)
    -> );

6、创建空间索引

空间索引主要是对地理空间数据类型的字段建立的索引,使用 SPATIAL 关键字进行创建。创建空间索引时,索引字段必须有非空约束。

#空间数据类型包括geometry,point,linestring和polygon类型等。geometry字段类型可以存储坐标点信息并进行一系列的关系计算。平时很少用到。
mysql8.0 [chap06]>create table index6(
    -> point geometry not null,
    -> SPATIAL KEY (point)
    -> );
mysql8.0 [chap06]>insert into index6 values (ST_geomfromtext('point(1 2)'));
mysql8.0 [chap06]>select ST_AsText(point) from index6;
+------------------+
| ST_AsText(point) |
+------------------+
| POINT(1 1)       |
| POINT(1 2)       |
+------------------+
mysql8.0 [chap06]>select ST_AsText(point) from index6 where ST_AsText(point)='point(1 1)';

2.6 删除索引

删除索引是指将表中已经存在的索引删除掉。一些不再使用的索引会降低表的更新速度,影响数据库的性能。对于这样的索引,应该将其删除。

#对应已经存在的索引,可以通过DROP语句来删除索引。基本形式如下:
DROP  INDEX 索引名  ON 表名 ;

3、练习:

学生表:Student (Sno, Sname, Ssex , Sage, Sdept)

学号,姓名,性别,年龄,所在系 Sno为主键

课程表:Course (Cno, Cname)

课程号,课程名 Cno为主键

学生选课表:SC (Sno, Cno, Score)

学号,课程号,成绩 Sno,Cno为主键

1.用SQL语句创建学生表student,定义主键,姓名不能重名,性别只能输入男或女,所在系的默认值是 “计算机”。

2.修改student 表中年龄(age)字段属性,数据类型由int 改变为smallint。

3.为SC表建立按学号(sno)和课程号(cno)组合的升序的主键索引,索引名为SC_INDEX 。

4.创建一视图 stu_info,查询全体学生的姓名,性别,课程名,成绩。

student表:
mysql8.0 [happy]>create table student(
    -> Sno int unique primary key,
    -> Sname varchar(20) unique NOT NULL,
    -> Ssex varchar(10) check(Ssex in ('男','女')),
    -> Sage int NOT NULL,
    -> Sdept varchar(20) default '计算机'
    -> );


Course表:
mysql8.0 [happy]>create table Course(
    -> Cno int primary key not null,
    -> Cname varchar(20) not null
    -> );


sc表:
mysql8.0 [happy]>create table SC(
    -> Sno int not null,
    -> Cno int not null,
    -> Score int not null,
    -> primary kry (Sno,Cno)
    -> );
MySQL视图与索引_第1张图片
MySQL视图与索引_第2张图片
MySQL视图与索引_第3张图片
2.修改student 表中年龄(age)字段属性,数据类型由int 改变为smallint。
mysql8.0 [happy]>alter table student modify Sage smallint;
MySQL视图与索引_第4张图片
3.为SC表建立按学号(sno)和课程号(cno)组合的升序的主键索引,索引名为SC_INDEX 。
mysql8.0 [happy]>create unique index SC_INDEX on SC(Sno,Cno,Score);
MySQL视图与索引_第5张图片
4.创建一视图 stu_info,查询全体学生的姓名,性别,课程名,成绩。
mysql8.0 [happy]>create view stu_info
    -> as
    -> select Sname,Ssex,Cname,Score from student,Course,SC
    -> where student.Sno=SC.Sno and SC.Cno=Course.Cno;
MySQL视图与索引_第6张图片

你可能感兴趣的:(mysql,数据库,sql)