存储引擎就是存储数据、建立索引、更新、查询数据等技术的实现方式。存储引擎是基于表的,而不是基于库的,所有存储引擎又称为表类型。
-- -------------------------------------------------进阶
-- 查询创建表语句
show create table dept;
-- 查询支持的存储引擎
show engines ;
-- 创建一个my_MyISAMy表,用MyISAM引擎
create table my_MyISAM(
id int,
name varchar(10)
)engine=MyISAM;
在选择存储引擎时,应该根据应用系统的特点选择合适的存储引擎。对于复杂的应用系统,还可以根据实际情况选择多种存储引擎进行组 合。
索引(index)是帮助MySQL高效获取数据的数据结构(有序)。在数据之外,数据库系统还维护着满足特定查找算法的数据结构,这些 数据结构以某种方式引用(指向)数据,这样就可以在这些数据结构上实现高级查找算法,这种数据结构就是索引。
优势
劣势
MySQL的索引是在存储引擎层实现的,不同的存储引擎有不同的结构,主要包含以下几种:
索引结构 | 描述 |
B+Tree索引 | 最常见的索引类型,大部分引擎都支持B+树索引 |
Hash索引 | 底层数据结构是用哈希表实现的,只有精确匹配索引列的查询才有效,不支持范围查询 |
R-tree(空间索引) | 空间索引是MylSAM引擎的一个特殊索引类型,主要用于地理空间数据类型,通常使用较少 |
Full-text(全文索引) | 是一种通过建立倒排索引,快速匹配文档的方式。类似于Lucene,Solr,ES |
我们平常所说的索引,如果没有特别指明,都是指B+树结构组织的索引。
索引 | InnoDB | MyISAM | Memory |
B+tree索引 | 支持 | 支持 | 支持 |
Hash索引 | 不支持 | 不支持 | 支持 |
R-tree索引 | 不支持 | 支持 | 不支持 |
Full-text | 5.6版本之后支持 | 支持 | 不支持 |
以一颗最大度数(max-degree)为5(5阶)的b-tree为例(每个节点最多存储4个key,5个指针):
具体动态变化的过程可以参考网站:https://www.cs.usfca.edu/~galles/visualization/BTree.html
相对于B-Tree区别:
MySQL索引数据结构对经典的B+Tree进行了优化。在原B+Tree的基础上,增加一个指向相邻叶子节点的链表指针,就形成了带有顺序指针的B+Tree,提高区间访问的性能。
哈希索引就是采用一定的hash算法,将键值换算成新的hash值,映射到对应的槽位上,然后存储在hash表中。 如果两个(或多个)键值,映射到一个相同的槽位上,他们就产生了hash冲突(也称为hash碰撞),可以通过链表来解决。
Hash索引特点
存储引擎支持
在MySQL中,支持hash索引的是Memory引擎,而InnoDB中具有自适应hash功能,hash索引是存储引擎根据B+Tree索引在指定条件下自动构建的。
在InnoDB存储引擎中,根据索引的存储形式,又可以分为以下两种:
聚集索引选取规则:
回表查询:先在二级索引中找到对应的主键值,再到聚集索引中拿到这一行的行数据。
创建索引
create [unique|fulltext] index index_name on table_name(index_col_name);
查看索引
show index from table_name;
删除索引
drop index index_name on table_name
MySQL客户端连接成功后,通过show[sessionlglobal] status命令可以提供服务器状态信息。通过如下指令,可以查看当前数据库的 INSERT、UPDATE、DELETE、SELECT的访问频次:
show global status like 'Com_______';
慢查询日志记录了所有执行时间超过指定参数(long_query_time, 单位:秒,默认10秒)的所有SQL语句的日志。
查询慢查询日志状态:
show variables like 'slow_query_log';
MySQL的慢查询日志默认没有开启,需要在MySQL的配置文件(/etc/my.cnf)中配置如下信息:
#开启MySQL慢日志查询开关
slow_query_log=1
#设置慢日志的时间为2秒,SQL语句执行时间超过2秒,就会视为慢查询,记录慢查询日志
long_query_time=2
执行一系列的业务SQL的操作,然后通过如下指令查看指令的执行耗时:
#查看每一条SQL的耗时基本情况
show profiles;
#查看指定query_id的SQL语句各个阶段的耗时情况
show profile for query query_id;
#查看指定query_id的SQL语句CPU的使用情况
show profile cpu for query query_id;
explain执行计划
EXPLAIN 或者 DESC命令获取 MySQL如何执行SELECT语句的信息,包括在SELECT语句执行过程中表如何连接和连接的顺序。
语法:
#直接在select语句之前加上关键字explain/ desc
EXPLAIN SELECT 字段列表 FROM 表名 WHERE 条件
视图(View)是一种虚拟存在的表。视图中的数据并不在数据库中实际存在,行和列数据来自定义视图的查询中使用的表,并且是在使用视图时动态生成的。
通俗的讲,视图只保存了查询的SQL逻辑,不保存查询结果。所以我们在创建视图的时候,主要的工作就落在创建这条SQL查询语句上。
CREATE [OR REPLACE] VIEW 视图名称[(列名列表)]AS SELECT语句[WITH[CASCADED|LOCAL]CHECK OPTION]
查看创建视图语句:SHOW CREATE VIEW 视图名称;
查看视图数据:SELECT*FROM 视图名称.…;
方式一:CREATE OR REPLACE VIEW 视图名称[(列名列表)]AS SELECT语句[WITH[CASCADED|LOCAL]CHECK OPTION]
方式二:ALTER VIEW 视图名称[(列名列表)]AS SELECT语句[WITH[CASCADED|LOCAL]CHECK OPTION]
DROP VIEW [IF EXISTS] 视图名称[视图名称]…
当使用WITH CHECK OPTION子句创建视图时,MySQL会通过视图检查正在更改的每个行,例如插入,更新,删除,以使其符合视图的定 义。
MySQL允许基于另一个视图创建视图,它还会检查依赖视图中的规则以保持一致性。为了确定检查的范围,mysql提供了两个选项: CASCADED和LOCAL,默认值为CASCADED。 CASCADED :
create or replace view stu_v1 as select sid, sname from student where sid<20;
select * from stu_v1;
insert into stu_v1 values (21,'hi');-- 插入成功
insert into stu_v1 values (19,'ho');-- 插入成功,不会检查增删改操作
create or replace view stu_v3 as select sid, sname from stu_v1 where sid>5 with cascaded check option ;
select * from stu_v3;
insert into stu_v3 values (21,'hii');-- 插入失败
insert into stu_v3 values (3,'hoo');-- 插入失败
insert into stu_v3 values (11,'hio');-- 插入成功
create or replace view stu_v5 as select sid, sname from stu_v3 where sid<=15;
insert into stu_v5 values (17,'hii');-- 插入成功
insert into stu_v5 values (21,'hoo');-- 插入失败
insert into stu_v5 values (5,'hio');-- 插入失败
创建视图时加with cascaded(级联的) check option的话,会检查当前视图还会检查当前视图所以依赖的所有视图它的条件是否满足;
local
create or replace view stu_v2 as select sid, sname from student where sid<20;
select * from stu_v2;
insert into stu_v2 values (21,'hi');-- 插入成功,不满足v2
insert into stu_v2 values (19,'ho');-- 插入成功,不会检查增删改操作
create or replace view stu_v4 as select sid, sname from stu_v2 where sid>5 with local check option ;
select * from stu_v4;
insert into stu_v4 values (21,'hii');-- 插入成功,不满足v2
insert into stu_v4 values (3,'hoo');-- 插入失败,不满足v4
insert into stu_v4 values (11,'hio');-- 插入成功
create or replace view stu_v6 as select sid, sname from stu_v4 where sid<=15;
insert into stu_v6 values (17,'hii');-- 插入成功,不满足v6
insert into stu_v6 values (21,'hoo');-- 插入成功,不满足v2
insert into stu_v6 values (5,'hio');-- 插入失败,不满足v4
定义视图时,有检查条件,就进行检查,没有就不进行检查;递归的检查依赖
要使视图可更新,视图中的行与基础表中的行之间必须存在一对一的关系。
如果视图包含以下任何一项,则该视图不可更新:
1.聚合函数或窗口函数(SUM()、MIN()、MAX()、COUNT()等)
2. DISTINCT Aae
3. GROUP BY
4. HAVING
5.UNION或者UNION ALL
作用
触发器是与表有关的数据库对象,指在insert/update/delete之前或之后,触发并执行触发器中定义的SQL语句集合。触发器的这种特 性可以协助应用在数据库端确保数据的完整性,日志记录,数据校验等操作。
使用别名OLD和NEW来引用触发器中发生变化的记录内容,这与其他的数据库是相似的。现在触发器还只支持行级触发,不支持语句级触发。
CREATE TRIGGER trigger_name
BEFORE/AFTER INSERT/UPDATE/DELETE
ON tbl name FOR EACH ROW --行级触发器
BEGIN
trigger_stmt ;
END;
SHOW TRIGGERS ;
DROP TRIGGER [schema_name.]trigger_name;-如果没有指定schema_name,默认为当前数据库。
-- 准备工作:日志表
create table emoloyee_logs(
id int(11) not null auto_increment primary key ,
operate varchar(20) not null ,
operate_time datetime not null,
operate_id int(11) not null ,
operate_params varchar(500)
);
-- 插入数据触发器
create trigger tb_employee_insert_trigger
after insert on employee for each row
begin
insert into emoloyee_logs(id,operate,operate_time,operate_id,operate_params) values
(null,'insert',now(),new.eno,concat('插入的数为:id',new.eno));
end
-- 查看触发器
show triggers ;
-- 插入数据
insert into employee values (7,'小2','男','项目部',1500);
-- 修改数据的触发器
create trigger tb_employee_update_trigger
after update on employee for each row
begin
insert into emoloyee_logs(id,operate,operate_time,operate_id,operate_params) values
(null,'update',now(),new.eno,
concat('更新之前的数为:name:',old.ename,'| 更新之后的数:name:',new.ename));
end
-- 更新数据
update employee set ename='张1' where employee.eno<3;
-- 删除数据的触发器
create trigger tb_employee_delete_trigger
after delete on employee for each row
begin
insert into emoloyee_logs(id,operate,operate_time,operate_id,operate_params) values
(null,'delete',now(),old.eno,
concat('删除之前的数为:name:',old.ename));
end
-- 删除数据
delete from employee where eno=6;
案例1:
create trigger sc_update_trigger
before update on sc for each row
begin
if old.grade-new.grade>=10 then
insert into sc_G values(new.sno,new.cno,old.grade,now());
end if;
end;
-- ----
show triggers ;
-- 更新
update sc set grade=grade-30 where sno='10060101'&&cno='07294001';
update sc set grade=grade-5 where sno='10060102'&&cno='07294002';
update sc set grade=grade-10 where sno='10060103'&&cno='07294002';
-- ----------------------------------------2
create table avg_sno(
sno varchar(20) not null ,
avg_sno double comment '平均成绩'
);
-- 触发器
create trigger avg_sno_trigger
after update on sc for each row
begin
insert into avg_sno values(NEW.sno,(select avg(new.grade) from sc));
end;
-- ------
update sc set grade=grade-20 where sno='10060101'&&cno='07294001';
update sc set grade=grade-5 where sno='10060102'&&cno='07294002';
update sc set grade=grade-10 where sno='10060103'&&cno='07294002';