MySQL-索引;视图

Posted MinggeQingchun

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了MySQL-索引;视图相关的知识,希望对你有一定的参考价值。

一、索引

mysql索引的建立对于MySQL的高效运行是很重要的,索引可以大大提高MySQL的检索速度

如:我们通过汉字字典查找汉字有两种方式

(1)一页一页挨着找,直到找到为止,这种查找方式属于全字典扫描

(2)通过汉语字典的目录页(索引),按拼音、笔画、偏旁部首等排序的目录(索引)缩小查找范围快速查找到需要的字

select * from t_user where name = 'zhangsan';

如果name字段上没有添加索引(目录),或者说没有给name字段创建索引,MySQL会进行全扫描,会将name字段上的每一个值都比对一遍。效率比较低 

上述SQL语句会去name字段上扫描

1、MySQL在查询方面主要就是两种方式

(1)全表扫描

(2)根据索引检索

2、索引语法

(1)创建索引

 create index 索引名 on table表名(字段名);

如:

 给emp表的ename字段添加索引,起名:emp_ename_index

create index emp_ename_index on emp(ename);

(2)删除索引

drop index 索引名 on table表名;

如:删除emp表中的索引emp_ename_index  

drop index emp_ename_index on emp;

(3)查看SQL是否使用索引,使用 explain关键字

explain select * from emp where ename = 'KING';
mysql> explain select * from emp where ename = 'KING';
	+----+-------------+-------+------+---------------+------+---------+------+------+-------------+
	| id | select_type | table | type | possible_keys | key  | key_len | ref  | rows | Extra       |
	+----+-------------+-------+------+---------------+------+---------+------+------+-------------+
	|  1 | SIMPLE      | emp   | ALL  | NULL          | NULL | NULL    | NULL |   15 | Using where |
	+----+-------------+-------+------+---------------+------+---------+------+------+-------------+
//多条记录,说明没有使用索引;type=ALL

//创建索引
mysql> create index emp_ename_index on emp(ename);


mysql> explain select * from emp where ename = 'KING';
	+----+-------------+-------+------+-----------------+-----------------+---------+-------+------+-------------+
	| id | select_type | table | type | possible_keys   | key             | key_len | ref   | rows | Extra       |
	+----+-------------+-------+------+-----------------+-----------------+---------+-------+------+-------------+
	|  1 | SIMPLE      | emp   | ref  | emp_ename_index | emp_ename_index | 33      | const |    1 | Using where |
	+----+-------------+-------+------+-----------------+-----------------+---------+-------+------+-------------+
type = ref

3、索引原理

在mysql数据库当中索引也是需要排序的,并且这个索引的排序和TreeSet数据结构相同

TreeSet(TreeMap)底层是一个自平衡的二叉树!

在mysql当中索引是一个B-Tree数据结构

遵循左小右大原则存放;采用中序遍历方式遍历取数据

(1)在任何数据库当中主键上都会自动添加索引对象,id字段上自动有索引(id是PK);在mysql当中,一个字段上如果有unique约束的话,也会自动创建索引对象

(2)在任何数据库当中,任何一张表的任何一条记录在硬盘存储上都有一个硬盘的物理存储编号

(3)在mysql当中,索引是一个单独的对象,不同的存储引擎以不同的形式存在

在MyISAM存储引擎中,索引存储在一个.MYI文件中

在InnoDB存储引擎中索引存储在一个逻辑名称叫做tablespace的当中

在MEMORY存储引擎当中索引被存储在内存当中

不管索引存储在哪里,索引在mysql当中都是一个树的形式存在。(自平衡二叉树:B-Tree)

4、索引分单列索引和组合索引

单列索引,即一个索引只包含单个列,一个表可以有多个单列索引,但这不是组合索引。

组合索引,即一个索引包含多个列。

创建索引时,你需要确保该索引是应用在 SQL 查询语句的条件(一般作为 WHERE 子句的条件)。

实际上,索引也是一张表,该表保存了主键与索引字段,并指向实体表的记录

5、索引失效

(1)模糊匹配当中以“%”开头

explain select * from emp where ename like '%T';

(2) 使用or的时候会失效,如果其中一边有一个字段没有索引

如果使用or那么要求or两边的条件字段都要有索引,才会走索引,如果其中一边有一个字段没有索引,那么另一个字段上的索引也不会实现。所以不建议使用or

explain select * from emp where ename = 'KING' or job = 'salesman';

(3) 使用复合索引的时候,没有使用左侧的列查找,索引失效

create index emp_job_sal_index on emp(job,sal);
		
//索引不失效
mysql> explain select * from emp where job = 'salesman';

//索引失效		
mysql> explain select * from emp where sal = 4000;

(4) 在where当中索引列参加了运算

mysql> explain select * from emp where sal+1 = 4000;

(5) 在where当中索引列使用了函数

explain select * from emp where lower(ename) = 'lilei';

6、索引缺点

过多的使用索引将会造成滥用,索引也会有它的缺点:

(1)虽然索引大大提高了查询速度,同时却会降低更新表的速度,如对表进行INSERT、UPDATE和DELETE。因为更新表时,MySQL不仅要保存数据,还要保存一下索引文件。

(2)建立索引会占用磁盘空间的索引文件。

1、普通索引

创建索引

这是最基本的索引,它没有任何限制。它有以下几种创建方式:

CREATE INDEX indexName ON table_name (column_name)

如果是CHAR,VARCHAR类型,length可以小于字段实际长度;如果是BLOB和TEXT类型,必须指定 length。

修改表结构(添加索引)

ALTER table tableName ADD INDEX indexName(columnName)

创建表的时候直接指定

CREATE TABLE mytable(  
ID INT NOT NULL,   
username VARCHAR(16) NOT NULL,  
INDEX [indexName] (username(length))  
);  

删除索引的语法

DROP INDEX [indexName] ON mytable; 

2、唯一索引

它与前面的普通索引类似,不同的就是:索引列的值必须唯一,但允许有空值。如果是组合索引,则列值的组合必须唯一。它有以下几种创建方式:

创建索引

CREATE UNIQUE INDEX indexName ON mytable(username(length)) 

修改表结构

ALTER table mytable ADD UNIQUE [indexName] (username(length))

创建表的时候直接指定

CREATE TABLE mytable(  
ID INT NOT NULL,   
username VARCHAR(16) NOT NULL,  
UNIQUE [indexName] (username(length)) 
); 

3、使用ALTER 命令添加和删除索引

有四种方式来添加数据表的索引:

ALTER TABLE tbl_name ADD PRIMARY KEY (column_list): 该语句添加一个主键,这意味着索引值必须是唯一的,且不能为NULL

ALTER TABLE tbl_name ADD UNIQUE index_name (column_list): 这条语句创建索引的值必须是唯一的(除了NULL外,NULL可能会出现多次)

ALTER TABLE tbl_name ADD INDEX index_name (column_list): 添加普通索引,索引值可出现多次

ALTER TABLE tbl_name ADD FULLTEXT index_name (column_list):该语句指定了索引为 FULLTEXT ,用于全文索引。

添加索引

ALTER TABLE user ADD INDEX (name);

 ALTER 命令中使用 DROP 子句来删除索引

ALTER TABLE user DROP INDEX name;

4、使用 ALTER 命令添加和删除主键

主键作用于列上(可以一个列或多个列联合主键),添加主键索引时,需要确保该主键默认不为空(NOT NULL)

ALTER TABLE user MODIFY age INT NOT NULL;
ALTER TABLE user ADD PRIMARY KEY (user_id);

也可以使用 ALTER 命令删除主键:

ALTER TABLE user DROP PRIMARY KEY;

删除主键时只需指定PRIMARY KEY,但在删除索引时,你必须知道索引名。

5、显示索引信息

可以使用 SHOW INDEX 命令来列出表中的相关的索引信息。可以通过添加 \\G 来格式化输出信息

SHOW INDEX FROM table_name\\G

二、视图

视图是可视化的表

在 SQL 中,视图是基于 SQL 语句的结果集的可视化的表

1、创建视图

CREATE VIEW view_name 
AS
    SELECT column_name(s)
    FROM table_name
    WHERE condition

2、删除视图

drop view view名;

注:

只有DQL(查询)语句才能以view的形式创建

create view view_name as 后面的语句必须是select语句

3、视图作用

(1)面向视图对象进行增删改查,对视图对象的增删改查,会导致原表被操作

视图的特点:

通过对视图的操作,会修改到原表数据

mysql> select * from dept2;
+--------+------------+-----------+
| DEPTNO | DEPTNAME   | CITY      |
+--------+------------+-----------+
|     10 | ACCOUNTING | BEI JING  |
|     20 | PURCHASE   | TIAN JIN  |
|     30 | SALES      | SHANG HAI |
|     40 | HR         | SU ZHOU   |
+--------+------------+-----------+
4 rows in set (0.00 sec)


//创建视图
mysql> create view dept2_view as select * from dept2;
Query OK, 0 rows affected (0.01 sec)


//面向视图查询
mysql> select * from dept2_view;
+--------+------------+-----------+
| DEPTNO | DEPTNAME   | CITY      |
+--------+------------+-----------+
|     10 | ACCOUNTING | BEI JING  |
|     20 | PURCHASE   | TIAN JIN  |
|     30 | SALES      | SHANG HAI |
|     40 | HR         | SU ZHOU   |
+--------+------------+-----------+


//面向视图插入
mysql> insert into dept2_view values(50,'RH','shanghai');
Query OK, 1 row affected (0.01 sec)


mysql> select * from dept2;
+--------+------------+-----------+
| DEPTNO | DEPTNAME   | CITY      |
+--------+------------+-----------+
|     10 | ACCOUNTING | BEI JING  |
|     20 | PURCHASE   | TIAN JIN  |
|     30 | SALES      | SHANG HAI |
|     40 | HR         | SU ZHOU   |
|     50 | RH         | shanghai  |
+--------+------------+-----------+
5 rows in set (0.00 sec)


//面向视图删除
mysql> delete from dept2_view where deptno = 50;
Query OK, 1 row affected (0.01 sec)


mysql> select * from dept2;
+--------+------------+-----------+
| DEPTNO | DEPTNAME   | CITY      |
+--------+------------+-----------+
|     10 | ACCOUNTING | BEI JING  |
|     20 | PURCHASE   | TIAN JIN  |
|     30 | SALES      | SHANG HAI |
|     40 | HR         | SU ZHOU   |
+--------+------------+-----------+
4 rows in set (0.00 sec)


//面向视图修改
mysql> update dept2_view set city='suzhou' where deptno = 40;
Query OK, 1 row affected (0.01 sec)
Rows matched: 1  Changed: 1  Warnings: 0

mysql> select * from dept2_view;
+--------+------------+-----------+
| DEPTNO | DEPTNAME   | CITY      |
+--------+------------+-----------+
|     10 | ACCOUNTING | BEI JING  |
|     20 | PURCHASE   | TIAN JIN  |
|     30 | SALES      | SHANG HAI |
|     40 | HR         | suzhou    |
+--------+------------+-----------+
4 rows in set (0.00 sec)

通过以上例子发现,不管是面向视图进行增删改,原表数据都会跟着修改,即使表关联也一样

//创建视图(以员工表 和 部门表联合查询结果创建)
mysql> create view emp_dept_view as select e.empname,e.sal,d.deptname from emp e join dept d on e.deptno = d.deptno;
Query OK, 0 rows affected (0.01 sec)


//视图查询
mysql> select * from emp_dept_view;
+------------+----------+------------+
| empname    | sal      | deptname   |
+------------+----------+------------+
| SHIWENFEI  |  4000.00 | PURCHASE   |
| AWEN       |  9000.00 | SALES      |
| WANJIANHAO |  5750.00 | SALES      |
......
15 rows in set (0.00 sec)


//更新视图数据
mysql> update emp_dept_view set sal = 10000 where deptname = 'sales';
Query OK, 6 rows affected (0.00 sec)
Rows matched: 6  Changed: 6  Warnings: 0


//查询员工原表数据
mysql> select * from emp;
+-------+------------+-----------+------+------------+----------+---------+--------+
| EMPNO | EMPNAME    | JOB       | MGR  | HIREDATE   | SAL      | BONUS   | DEPTNO |
+-------+------------+-----------+------+------------+----------+---------+--------+
|  7369 | SHIWENFEI  | CLERK     | 7902 | 2008-12-17 |  4000.00 |    NULL |     20 |
|  7499 | AWEN       | SALESMAN  | 7698 | 2011-02-20 | 10000.00 |  300.00 |     30 |
|  7521 | WANJIANHAO | SALESMAN  | 7698 | 2011-02-22 | 10000.00 |  500.00 |     30 |
......

 (2)视图在实际开发作用

如上表关联语句

create 
    view emp_dept_view 
as 
    select 
        e.empname,e.sal,d.deptname 
    from 
        emp e 
    join 
        dept d 
    on 
        e.deptno = d.deptno;

如果有一条非常复杂的SQL语句,且该SQL语句需要在不同的位置反复使用。每一次使用这个sql语句的时候都需要重新编写(导致SQL语句冗余重复),此时可以把这条复杂的SQL语句以视图对象的形式新建

在需要编写这条SQL语句的位置直接使用视图对象,可以大大简化开发。并且利于后期的维护,修改的时候也只需要修改一个位置就行,只需要 修改视图对象所映射的SQL语句。

我们以后面向视图开发的时候,使用视图的时候可以像使用table一样。可以对视图进行增删改查等操作。视图不是在内存当中,视图对象也是存储在硬盘上的,不会消失
 

以上是关于MySQL-索引;视图的主要内容,如果未能解决你的问题,请参考以下文章

mysql 索引和事务视图

Mysql 索引视图

是否可以在 MySQL 中有索引视图?

Linux云计算-MySQL-表操作-索引-外键-视图

MySQL-索引;视图

联合分组子查询视图事务python操作mysql索引