1.视图讲解与优缺点的分析
1.1.什么是视图?
MySQL 视图(View)是一种虚拟存在的表,同真实表一样,视图也由列和行构成,但视图并不实际存在于数据库中。行和列的数据来自于定义视图的查询中所使用的表,并且还是在使用视图时动态生成的。
数据库中只存放了视图的定义,并没有存放视图中的数据,这些数据都存放在定义视图查询所引用的真实表中。使用视图查询数据时,数据库会从真实表中取出对应的数据。因此,视图中的数据是依赖于真实表中的数据的。一旦真实表中的数据发生改变,显示在视图中的数据也会发生改变。
视图可以从原有的表上选取对用户有用的信息,那些对用户没用,或者用户没有权限了解的信息,都可以直接屏蔽掉,作用类似于筛选。这样做既使应用简单化,也保证了系统的安全。
1.2.视图与数据表的区别有哪些?
- 视图不是数据库中真实的表,而是一张虚拟表,其结构和数据是建立在对数据中真实表的查询基础上的。
- 存储在数据库中的查询操作 SQL 语句定义了视图的内容,列数据和行数据来自于视图查询所引用的实际表,引用视图时动态生成这些数据。
- 视图没有实际的物理记录,不是以数据集的形式存储在数据库中的,它所对应的数据实际上是存储在视图所引用的真实表中的。
- 视图是数据的窗口,而表是内容。表是实际数据的存放单位,而视图只是以不同的显示方式展示数据,其数据来源还是实际表。
- 视图是查看数据表的一种方法,可以查询数据表中某些字段构成的数据,只是一些 SQL 语句的集合。从安全的角度来看,视图的数据安全性更高,使用视图的用户不接触数据表,不知道表结构。
- 视图的建立和删除只影响视图本身,不影响对应的基本表。
1.3.视图的优点
1) 定制用户数据,聚焦特定的数据
在实际的应用过程中,不同的用户可能对不同的数据有不同的要求。
例如,当数据库同时存在时,如学生基本信息表、课程表和教师信息表等多种表同时存在时,可以根据需求让不同的用户使用各自的数据。学生查看修改自己基本信息的视图,安排课程人员查看修改课程表和教师信息的视图,教师查看学生信息和课程信息表的视图。
2) 简化数据操作
在使用查询时,很多时候要使用聚合函数,同时还要显示其他字段的信息,可能还需要关联到其他表,语句可能会很长,如果这个动作频繁发生的话,可以创建视图来简化操作。
3) 提高数据的安全性
视图是虚拟的,物理上是不存在的。可以只授予用户视图的权限,而不具体指定使用表的权限,来保护基础数据的安全。
4) 共享所需数据
通过使用视图,每个用户不必都定义和存储自己所需的数据,可以共享数据库中的数据,同样的数据只需要存储一次。
5) 更改数据格式
通过使用视图,可以重新格式化检索出的数据,并组织输出到其他应用程序中。
6) 重用 SQL 语句
视图提供的是对查询操作的封装,本身不包含数据,所呈现的数据是根据视图定义从基础表中检索出来的,如果基础表的数据新增或删除,视图呈现的也是更新后的数据。视图定义后,编写完所需的查询,可以方便地重用该视图。
1.4.视图的语法
CREATE VIEW <视图名> AS <SELECT语句> • 1
语法说明如下。
<视图名>
:指定视图的名称。该名称在数据库中必须是唯一的,不能与其他表或视图同名。<SELECT语句>
:指定创建视图的 SELECT 语句,可用于查询多个基础表或源视图。
对于创建视图中的 SELECT 语句的指定存在以下限制:
- 用户除了拥有 CREATE VIEW 权限外,还具有操作中涉及的基础表和其他视图的相关权限。
- SELECT 语句不能引用系统或用户变量。
- SELECT 语句不能包含 FROM 子句中的子查询。
- SELECT 语句不能引用预处理语句参数。
2.索引
2.1.什么是索引
索引是一种特殊的数据库结构,由数据表中的一列或多列组合而成,可以用来快速查询数据表中有某一特定值的记录。通过索引,查询数据时不用读完记录的所有信息,而只是查询索引列。否则,数据库系统将读取每条记录的所有信息进行匹配。
可以把索引比作新华字典的音序表。例如,要查“库”字,如果不使用音序,就需要从字典的 400 页中逐页来找。但是,如果提取拼音出来,构成音序表,就只需要从 10 多页的音序表中直接查找。这样就可以大大节省时间。
因此,使用索引可以很大程度上提高数据库的查询速度,还有效的提高了数据库系统的性能。
2.2.为什么要使用索引
索引就是根据表中的一列或若干列按照一定顺序建立的列值与记录行之间的对应关系表,实质上是一张描述索引列的列值与原表中记录行之间一 一对应关系的有序表。
索引是 MySQL 中十分重要的数据库对象,是数据库性能调优技术的基础,常用于实现数据的快速检索。
在 MySQL 中,通常有以下两种方式访问数据库表的行数据:
1) 顺序访问
顺序访问是在表中实行全表扫描,从头到尾逐行遍历,直到在无序的行数据中找到符合条件的目标数据。
顺序访问实现比较简单,但是当表中有大量数据的时候,效率非常低下。例如,在几千万条数据中查找少量的数据时,使用顺序访问方式将会遍历所有的数据,花费大量的时间,显然会影响数据库的处理性能。
2) 索引访问
索引访问是通过遍历索引来直接访问表中记录行的方式。
使用这种方式的前提是对表建立一个索引,在列上创建了索引之后,查找数据时可以直接根据该列上的索引找到对应记录行的位置,从而快捷地查找到数据。索引存储了指定列数据值的指针,根据指定的排序顺序对这些指针排序。
简而言之,不使用索引,MySQL 就必须从第一条记录开始读完整个表,直到找出相关的行。表越大,查询数据所花费的时间就越多。如果表中查询的列有一个索引,MySQL 就能快速到达一个位置去搜索数据文件,而不必查看所有数据,这样将会节省很大一部分时间。
2.3.优缺点
索引有其明显的优势,也有其不可避免的缺点。
优点
索引的优点如下:
- 通过创建唯一索引可以保证数据库表中每一行数据的唯一性。
- 可以给所有的 MySQL 列类型设置索引。
- 可以大大加快数据的查询速度,这是使用索引最主要的原因。
- 在实现数据的参考完整性方面可以加速表与表之间的连接。
- 在使用分组和排序子句进行数据查询时也可以显著减少查询中分组和排序的时间
缺点
增加索引也有许多不利的方面,主要如下:
- 创建和维护索引组要耗费时间,并且随着数据量的增加所耗费的时间也会增加。
- 索引需要占磁盘空间,除了数据表占数据空间以外,每一个索引还要占一定的物理空间。如果有大量的索引,索引文件可能比数据文件更快达到最大文件尺寸。
- 当对表中的数据进行增加、删除和修改的时候,索引也要动态维护,这样就降低了数据的维护速度。
索引可以提高查询速度,但是会影响插入记录的速度。因为,向有索引的表中插入记录时,数据库系统会按照索引进行排序,这样就降低了插入记录的速度,插入大量记录时的速度影响会更加明显。这种情况下,最好的办法是先删除表中的索引,然后插入数据,插入完成后,再创建索引。
2.4.何时不使用索引
- 表记录太少
- 经常增删改的表
- 数据重复且分布均匀的表字段,只应该为经常查询和最经常排序的数据列建立索引(如果某个数据类包含太多的重复数据,建立索引没有太大意义)
- 频繁更新的字段不适合创建索引(会增加IO负担)
- where条件里用不到的字段不创建索引
2.5.索引何时失效
- like以通配符%开头索引失效
- 当全表扫描比走索引查询的快的时候,会使用全表扫描,而不走索引
- 字符串不加单引号索引会失效
- where中索引列使用了函数(例如substring字符串截取函数)
- where中索引列有运算(用了< or > 右边的索引会失效,用<= or >= 索引不会失效)
- is null可以走索引,is not null无法使用索引(取决于某一列的具体情况)
- 复合索引没有用到左列字段(最左前缀法则,如果没用用到最左列索引,或中间跳过了某列有索引的列,索引会部分失效)
- 条件中有or,前面的列有索引,后面的列没有,索引会失效。想让索引生效,只能将or条件中的每个列都加上索引
-- 1.视图 select * from t_mysql_student; select * from t_mysql_score; select * from t_mysql_course; select * from t_mysql_teacher; -- 直接创建视图报错,因为有重复的列段 CREATE view v_student_score as select * from t_mysql_student s, t_mysql_score sc, t_mysql_course c, t_mysql_teacher t where s.sid = sc.sid and sc.cid = c.cid and c.tid = t.tid -- 去重重复列段 CREATE view v_student_score as select s.*,sc.cid,sc.score,c.cname,t.* from t_mysql_student s, t_mysql_score sc, t_mysql_course c, t_mysql_teacher t where s.sid = sc.sid and sc.cid = c.cid and c.tid = t.tid; -- 视图依然可以行转列 SELECT * from v_student_score; SELECT sid,sname, sum(if(cid='01',score,0)) 语文, sum(if(cid='02',score,0)) 数学, sum(if(cid='03',score,0)) 英语 FROM v_student_score GROUP BY sid,sname • 1 • 2 • 3 • 4 • 5 • 6 • 7 • 8 • 9 • 10 • 11 • 12 • 13 • 14 • 15 • 16 • 17 • 18 • 19 • 20 • 21 • 22 • 23 • 24 • 25 • 26 • 27 • 28 • 29 • 30 • 31 • 32 • 33 • 34 • 35 • 36 • 37 • 38 • 39 • 40 • 41 • 42 • 43 • 44
2.6.索引分类
MySQL索引分为普通索引、唯一索引、主键索引、组合索引、全文索引。索引不会包含有null值的列,索引项可以为null(唯一索引、组合索引等),但是只要列中有null值就不会被包含在索引中。
2.6.1.普通索引
普通索引是最基本的索引,它没有任何限制;
- 创建索引语法:
create index 索引名称 on table(索引字段); • 1
- 修改表结构方式添加索引:
ALTER TABLE table_name ADD INDEX index_name ON (column(length)) • 1
- 删除索引
DROP INDEX index_name ON table • 1
2.6.2.唯一索引
唯一索引与前面的普通索引类似,不同的就是:索引列的值必须唯一,但允许有空值。如果是组合索引,则列值的组合必须唯一。
CREATE UNIQUE INDEX indexName ON table(column(length)) • 1
2.6.3.主键索引
主键索引是一种特殊的唯一索引,一个表只能有一个主键,不允许有空值。简单来说:主键索引是加速查询 + 列值唯一(不可以有null)+ 表中只有一个。
CREATE TABLE mytable( ID INT NOT NULL, username VARCHAR(16) NOT NULL, PRIMARY KEY(ID) ); • 1 • 2 • 3 • 4 • 5
2.6.4.组合索引
组合索引指在多个字段上创建的索引,只有在查询条件中使用了创建索引时的第一个字段,索引才会被使用。使用组合索引时遵循最左前缀集合。
ALTER TABLE `table` ADD INDEX name_city_age (name,city,age); • 1
2.6.5.全文索引
- 概念
全文索引主要用来查找文本中的关键字,而不是直接与索引中的值相比较。fulltext索引跟其它索引大不相同,它更像是一个搜索引擎,而不是简单的where语句的参数匹配。
fulltext索引配合match against操作使用,而不是一般的where语句加like。它可以在create table,alter table ,create index使用,不过目前只有char、varchar,text 列上可以创建全文索引。
值得一提的是,在数据量较大时候,现将数据放入一个没有全局索引的表中,然后再用CREATE index创建fulltext索引,要比先为一张表建立fulltext然后再将数据写入的速度快很多。
- 版本支持
Mysql 5.6之前版本,只有MyISAM支持全文索引,5.6之后,Innodb和MyISAM均支持全文索引。另外,只有字段的数据类型为 char、varchar、text 及其系列才可以建全文索引。
- 案例
创建数据表t_articles
CREATE TABLE t_articles ( id INT UNSIGNED AUTO_INCREMENT NOT NULL PRIMARY KEY, title VARCHAR(200), body TEXT, FULLTEXT (title,body) ); • 1 • 2 • 3 • 4 • 5 • 6
给现有的article表的title和body字段创建全文索引,索引名称为fulltext_article
ALTER TABLE t_articles ADD FULLTEXT INDEX fulltext_article (title, body); • 1
导入测试数据
INSERT INTO t_articles VALUES (NULL,'MySQL Tutorial', 'DBMS stands for DataBase ...'), (NULL,'How To Use MySQL Efficiently', 'After you went through a ...'), (NULL,'Optimising MySQL','In this tutorial we will show ...'), (NULL,'1001 MySQL Tricks','1. Never run mysqld as root. 2. ...'), (NULL,'MySQL vs. YourSQL', 'In the following database comparison ...'), (NULL,'MySQL Security', 'When configured properly, MySQL ...'); INSERT INTO t_articles VALUES (NULL,'abc', 'zs red blue ...'), (NULL,'xyz', 'ls white'); INSERT INTO t_articles VALUES (NULL,'aaa', 'zs red blue ...'), (NULL,'bbb', 'ls white red'); • 1 • 2 • 3 • 4 • 5 • 6 • 7 • 8 • 9 • 10 • 11 • 12 • 13 • 14 • 15 • 16 • 17
- 示例一:自然语言模式(IN NATURAL LANGUAGE MODE,默认模式)
SELECT * FROM t_articles where MATCH (title,body) AGAINST ('database') • 1
- 示例二:布尔搜索模式(IN BOOLEAN MODE)
符号 | 含义 |
+ | 必须包含此字符串 |
- | 必须不包含此字符串 |
“” | 双引号内作为整体不能拆词 |
> | 提高该词的相关性,查询的结果靠前 |
< | 降低该词的相关性,查询的结果靠后 |
* | 通配符,只能接在词后面 |
#包含red或者blue SELECT * FROM t_articles where MATCH (title,body) AGAINST ('red blue' IN BOOLEAN MODE ); #包含red,但是必须包含blue SELECT * FROM t_articles where MATCH (title,body) AGAINST ('red +blue' IN BOOLEAN MODE ); #包含red,但是一定不能包含blue SELECT * FROM t_articles where MATCH (title,body) AGAINST ('red -blue' IN BOOLEAN MODE ); • 1 • 2 • 3 • 4 • 5 • 6
注意:长度超过2的英文关键字才会生效
- 示例三:中文搜索
5.6之后MySQL自带ngram解析器,可以解析中日韩三国文字,如果不使用ngram解析器,则MySQL默认使用空格与符号作为分隔符(对于英文自然够用了,但对于中日韩文字就不好用了,所以才需要ngram解析器)。
查看数据库版本
select version(); • 1
查看数据库引擎
show engines; • 1
修改MySQL全文检索最小许可字符
[mysqld] ft_min_word_len = 2 • 1 • 2
全文检索的最小许可字符(默认4,通过 SHOW VARIABLES LIKE ‘ft_min_word_len’ 可查看),中文通常是两个字就是一个词,所以做中文的话需要修改这个值为2最好。services.msc
注意:必须要重启Mysql服务
创建全文索引并设置ngram解析器
ALTER TABLE t_book ADD FULLTEXT INDEX fulltext_bookname_type (bookname, booktype) WITH PARSER ngram; • 1 • 2
基于t_book表中的bookname和booktype字段创建全文索引并设置ngram解析器,让其支持中文检索。
关键词搜索:
SELECT * FROM t_book where MATCH (bookname, booktype) AGAINST ('三国') • 1
-- 2.索引分类 CREATE TABLE `t_log` ( `id` varchar(32) NOT NULL COMMENT '唯一标识', `ip` varchar(15) NOT NULL COMMENT 'IP地址', `userid` varchar(32) NOT NULL COMMENT '用户ID', `moduleid` varchar(32) NOT NULL COMMENT '模块ID', `content` varchar(500) NOT NULL COMMENT '日志内容', `createdate` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建日期', `url` varchar(100) DEFAULT NULL COMMENT '请求URL地址', PRIMARY KEY (`id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8; -- 1) 普通索引:是最基本的索引,它没有任何限制; -- 0.762s select * from t_log; -- 建索引前 0.12s select * from t_log where moduleid = '10040199'; -- 创建索引所花费的时间:1.593s Create index idx_moduleid on t_log(moduleid); -- 建索引前 0.001s select * from t_log where moduleid = '10040199'; -- 可以查看走过的索引 EXPLAIN select * from t_log where moduleid = '10040199'; -- 2) 唯一索引:与前面的普通索引类似,不同的就是:索引列的值必须唯一,但允许有空值。如果是组合索引,则列值的组合必须唯一; -- Duplicate entry '/quartz/queryJobLst' for key 'idx_url' 有重复列段 create UNIQUE index idx_url on t_log(url); drop index idx_url on t_log; -- 3) 主键索引:是一种特殊的唯一索引,一个表只能有一个主键,不允许有空值; -- 主键索引所花费的时间:0s select * from t_log where id = '07489cdafd6d4a3489884cd3c00c7b27'; EXPLAIN select * from t_log where id = '07489cdafd6d4a3489884cd3c00c7b27'; -- 4) 组合索引:指多个字段上创建的索引,只有在查询条件中使用了创建索引时的第一个字段,索引才会被使用。使用组合索引时遵循最左前缀集合; -- 花费的时间:3.959s create index idx_userid_moduleid_url on t_log(userid,moduleid,url); -- 走组合索引 EXPLAIN select * from t_log where userid = '' and moduleid = '' and url = ''; EXPLAIN select * from t_log where userid = '' and moduleid = ''; EXPLAIN select * from t_log where userid = '' ; EXPLAIN select * from t_log where userid = '' and url = ''; -- 不走组合索引 EXPLAIN select * from t_log where moduleid = ''; EXPLAIN select * from t_log where url = ''; EXPLAIN select * from t_log where moduleid = '' and url = ''; -- 4.创建索引 -- CREATE [UNIQUE|FULLTEXT] INDEX 索引名 ON 表名(字段名[(长度)][ASC|DESC]) • 1 • 2 • 3 • 4 • 5 • 6 • 7 • 8 • 9 • 10 • 11 • 12 • 13 • 14 • 15 • 16 • 17 • 18 • 19 • 20 • 21 • 22 • 23 • 24 • 25 • 26 • 27 • 28 • 29 • 30 • 31 • 32 • 33 • 34 • 35 • 36 • 37 • 38 • 39 • 40 • 41 • 42 • 43 • 44
3.数据的导入导出
3.1 使用工具,类似Sqlyog、Navicat等导入导出数据。
-- DELETE/TRUNCATE -- 花费的时间:10.597s DELETE FROM t_log; -- 花费的时间:0.121s TRUNCATE TABLE t_log; -- 1.使用工具,类似Sqlyog、Navicat等导入导出数据。 -- 使用Navicat工具导入 t_log 共耗时 45s; -- 使用mysqldump导入 包含t_log表的整个数据库 共耗时 20s; -- 使用单表数据导入load data infile 的方式,共耗时 7.502s • 1 • 2 • 3 • 4 • 5 • 6 • 7 • 8 • 9 • 10 • 11
3.2 使用mysqldump导入导出
-- 2.1 导出 -- 2.1.1 导出表数据和表结构 -- mysqldump -u用户名 -p密码 数据库名 > 数据库名.sql(这个名字随便叫) D:\SoftwareInstallPath\mysql-8.0.13-winx64\bin>mysqldump -uroot -p123456 mybatis_ssm > 1234567.sql -- 2.1.2 只导出表结构 -- mysqldump -u用户名 -p密码 -d 数据库名 > 数据库名.sql # mysqldump -uroot -p -d abc > abc.sql -- 注:导出的数据在mysql的bin目录下 -- 2.2 导入 -- 注意:首先建立空数据库 -- mysql>create database abc; -- 2.2.1 方法一 -- mysql>use abc; #选择数据库 -- mysql>set names utf8; #设置数据库编码 -- mysql>source /D:/SoftwareInstallPath/mysql-8.0.13-winx64/bin/1234567.sql; #导入数据 -- 2.2.2 方法二 -- mysql -u用户名 -p密码 数据库名 < 数据库名.sql #mysql -uabc_f -p abc < abc.sql • 1 • 2 • 3 • 4 • 5 • 6 • 7 • 8 • 9 • 10 • 11 • 12 • 13 • 14 • 15 • 16 • 17 • 18 • 19 • 20 • 21 • 22
3.3 .LOAD DATA INFILE 导入导出
-- 可先通过SELECT INTO OUTFILE方式,将数据导出到Mysql的C:\ProgramData\MySQL\MySQL Server 5.5\data目录下,再通过LOAD DATA INFILE方式导入。 -- 1) select * from 表名 into outfile '/文件名.sql'; -- 2) load data infile '/文件名.sql' into table 表名(列名1,...); -- 这时候就可以在 mysql.ini 文件的 [mysqld] 代码下增加 secure_file_priv=E:/TEST 再重启 mysql 就可以了。然后在导出的地址下面写上刚才配置的这个地址 eg: select * from tb_test into outfile "E:/TEST/test.txt";就可以了。 select * from t_log into outfile 'E:/12345678.sql'; load data infile 'E:/12345678.sql' into table t_log(id,ip,userid,moduleid,content,createdate,url); show variables like 'secure%' desc t_log; select * FROM t_log; • 1 • 2 • 3 • 4 • 5 • 6 • 7 • 8 • 9 • 10 • 11 • 12 • 13 • 14
要在my文件给D盘权限
D:\mySQL\mysql-8.0.18-winx64
[mysql] # 设置mysql客户端默认字符集 default-character-set=utf8 [mysqld] secure_file_priv=D: #设置3306端口 port = 3306 # 设置mysql的安装目录 basedir=D:/mySQL/mysql-8.0.18-winx64 # 设置mysql数据库的数据的存放目录 datadir=D:/mySQL/mysql-8.0.18-winx64/data # 允许最大连接数 max_connections=200 # 服务端使用的字符集默认为8比特编码的latin1字符集 character-set-server=utf8 # 创建新表时将使用的默认存储引擎 default-storage-engine=INNODB • 1 • 2 • 3 • 4 • 5 • 6 • 7 • 8 • 9 • 10 • 11 • 12 • 13 • 14 • 15 • 16 • 17 • 18