一、MySQL体系架构
由图,可以看出MySQL最上层是连接组件。下面服务器是由连接池、管理服务和工具组件、SQL接口、查询解析器、查询优化器、缓存、存储引擎、文件系统组成。
1、连接池管理、缓冲用户的连接,线程处理等需要缓存的需求。连接池的作用就是将这些连接缓存下来,下次可以直接用已经建立好的连接,提升服务器性能。
2、管理服务和工具组件系统管理和控制工具,例如备份恢复、Mysql复制、集群等 。
3、SQL接口接受用户的SQL命令,并且返回用户需要查询的结果。
4、查询解析器SQL命令传递到解析器的时候会被解析器验证和解析(权限、语法结构)。解析器是由Lex和YACC实现的,是一个很长的脚本, 主要功能:将SQL语句分解成数据结构,并将这个结构传递到后续步骤,以后SQL语句的传递和处理就是基于这个结构的
如果在分解构成中遇到错误,那么就说明这个sql语句是不合理的
5、查询优化器SQL语句在查询之前会使用查询优化器对查询进行优化 他使用的是“选取-投影-联接”策略进行查询。
用一个例子就可以理解: select uid,name from user where gender = 1;这个select 查询先根据where 语句进行选取,而不是先将表全部查询出来以后再进行age过滤
这个select查询先根据id和name进行属性投影,而不是将属性全部取出以后再进行过滤
将这两个查询条件联接起来生成最终查询结果
6、缓存如果查询缓存有命中的查询结果,查询语句就可以直接去查询缓存中取数据
7、插入式存储引擎存储引擎说白了就是如何管理操作数据(存储数据、如何更新、查询数据等)的一种方法。因为在关系数据库中数据的存储是以表的形式存储的,所以存储引擎也可以称为表类型(即存储和操作此表的类型)
二、MySQL存储引擎
对于MySQL 5.5及更高版本,默认的存储引擎是InnoDB。在5.5版本之前,MySQL的默认存储引擎是MyISAM。
1、什么是MySQL存储引擎?MySQL属于关系型数据库,而关系型数据库的存储是以表的形式进行的,对于表的创建,数据的存储,检索,更新等都是由MySQL存储引擎完成的,这也是MySQL存储引擎在MySQL中扮演的重要角色。存储引擎可以概括为数据文件在磁盘上的不同组织形式. SQL Server和Oracle的读者可能很清楚,这两种数据库的存储引擎只有一个,而MySQL的存储引擎种类比较多,如MyISAM,InnoDB和Memory.多种存储引擎是因为MySQL的开源性.
2、MySQL存储引擎的作用是什么?
MySQL存储引擎在MySQL中扮演重要角色,其作比较重要作用,大致归结为如下两方面:管理表创建,数据检索,索引创建等
满足自定义存储引擎开发。
3、MySQL存储引擎种类
常用的三种存储引擎:
(1)InnoDB
MySQL 5.5 及以后版本中的默认存储引擎,他的优点如下:灾难恢复性好
支持事务
使用行级锁
支持外键关联
支持热备份
对于InnoDB引擎中的表,其数据的物理组织形式是簇表(Cluster Table),主键索引和数据是在一起的,数据按主键的顺序物理分布实现了缓冲管理,不仅能缓冲索引也能缓冲数据,并且会自动创建散列索引以加快数据的获取
(2)MyISAM
该存储引擎管理非事务性表;使用表级锁;提供高速存储和检索;可以配合锁,实现操作系统下的复制备份、迁移;支持全文搜索;数据紧凑存储,因此可获得更小的索引和更快的全表扫描性能。
(3)MEMORY
提供内存中的表,以前称为堆,不支持事务和外键。它在RAM中处理所有数据,以便比在磁盘上存储数据更快地访问。用于快速查找引用和其他相同的数据。
不常用的几种存储引擎:
(4)MERGE
将多个类似的MyISAM表分组为一个表,可以处理非事务性表,默认情况下包括这些表。
(5)PERFORMANCE_SCHEMA
该引擎主要用于收集数据库服务器性能参数。这种引擎提供以下功能:提供进程等待的详细信息,包括锁、互斥变量、文件信息;保存历史的事件汇总信息,为提供MySQL服务器性能做出详细的判断;对于新增和删除监控事件点都非常容易,并可以随意改变mysql服务器的监控周期,例如(CYCLE、MICROSECOND)。 MySQL用户是不能创建存储引擎为PERFORMANCE_SCHEMA的表。
(6)ARCHIVE
Archive是归档的意思,在归档之后很多的高级功能就不再支持了,仅仅支持最基本的插入和查询两种功能。在MySQL 5.5版以前,Archive是不支持索引,但是在MySQL 5.5以后的版本中就开始支持索引了。Archive拥有很好的压缩机制,它使用zlib压缩库,在记录被请求时会实时压缩,所以它经常被用来当做仓库使用。
(7)CSV
该种类型的存储引擎不支持索引,即使用该种类型的表没有主键列;另外也不允许表中的字段为null。csv的编码转换需要格外注意。
(8)BLACKHOLE
该存储引擎支持事务,而且支持mvcc的行级锁,写入这种引擎表中的任何数据都会消失,主要用于做日志记录或同步归档的中继存储,这个存储引擎除非有特别目的,否则不适合使用。
(9)FEDERATED
该存储引擎可以不同的Mysql服务器联合起来,逻辑上组成一个完整的数据库。这种存储引擎非常适合数据库分布式应用。将数据存储在远程数据库中,本地是不存储任何数据的。
4、MySQL存储引擎的选择
三、数据库的范式设计
1、关系数据库有六种范式:第一范式(1NF)、第二范式(2NF)、第三范式(3NF)、巴德斯科范式(BCNF)、第四范式(4NF)和第五范式(5NF)。满足最低要求的范式是第一范式(1NF)。在第一范式的基础上进一步满足更多要求的称为第二范式(2NF),其余范式以此类推。一般说来,数据库只需满足第三范式(3NF)就行了。
(1) 第一范式
1NF是对属性的原子性,要求属性具有原子性,不可再分解;
第一范式是最基本的范式。如果数据库表中的所有字段值都是不可分解的原子值,就说明该数据库表满足了第一范式。数据库表的每一列都是不可分割的原子数据项,而不能是集合,数组,记录等非原子数据项。简而言之,第一范式就是无重复的域。
(2)第二范式
2NF是对记录的惟一性,要求记录有惟一标识,即实体的惟一性,即不存在部分依赖;
满足第二范式必须先满足第一范式。第二范式需要确保数据库表中的每一列都和主键相关,而不能只与主键的某一部分相关(主要针对联合主键而言)。也就是说在一个数据库表中,一个表中只能保存一种数据,不可以把多种数据保存在同一张数据库表中。
(3)第三范式
3NF是对字段的冗余性,要求任何字段不能由其他字段派生出来,它要求字段没有冗余,即不存在传递依赖;
首先是 2NF,另外非主键列必须直接依赖于主键,不能存在传递依赖。即不能存在:非主键列 A 依赖于非主键列 B,非主键列 B 依赖于主键的情况。简而言之,第三范式(3NF)要求一个关系中不包含已在其它关系已包含的非主关键字信息。
2、 范式的利弊
优点:范式可以避免数据冗余,减少数据库的空间,减轻维护数据完整性的麻烦。
缺点:按照范式的规范设计出来的表,等级越高的范式设计出来的表越多。例如第一范式可能设计出来的表可能只有一张表而已,再按照第二范式去设计这张表时就可能出来两张或更多张表,如果再按第三范式或更高的范式去设计这张表会出现更多比第二范式多 的表。表的数量越多,当我们去查询一些数据,必然要去多表中去查询数据,这样查询的时间要比在一张表中查询中所用的时间要高很多。也就是说我们所用的范式越高,对数据操作的性能越低。所以我们在利用范式设计表的时候,要根据具体的需求再去权衡是否使用更高范式去设计表。
3、反范式
故名思义,跟范式所要求的正好相反,在反范式的设计模式,我们可以允许适当的数据的冗余,用这个冗余去取操作数据时间的缩短。也就是用空间来换取时间,把数据冗余在多个表中,当查询时可以减少或者是避免表之间的关联。
4、反范式的利弊
优点:查询时可以减少表的关联;可以更好的进行索引优化;
缺点:存在数据冗余以及数据维护异常;对数据的修改需要更多的成本
四、MySQL索引
1、数据库索引的原理
该原理就是对收集到的大量数据进行筛选,从中搜索出自己需要获得的重要信息。如针对数据库中的一行或是多行,筛选出满足你设定条件的人数等。建立数据库索引的便利之处在于能迅速定位到信息,为搜索提供帮助。
2、MySQL中索引的优点和缺点
优点:所有的MySql列类型(字段类型)都可以被索引,也就是可以给任意字段设置索引
大大加快数据的查询速度
缺点:创建索引和维护索引要耗费时间,并且随着数据量的增加所耗费的时间也会增加
索引也需要占空间,我们知道数据表中的数据也会有最大上线设置的,如果我们有大量的索引,索引文件可能会比数据文件更快达到上线值
当对表中的数据进行增加、删除、修改时,索引也需要动态的维护,降低了数据的维护速度。
3、MySQL中索引的使用原则
通过上面说的优点和缺点,我们应该可以知道,并不是每个字段度设置索引就好,也不是索引越多越好,而是需要自己合理的使用。对经常更新的表就避免对其进行过多的索引,对经常用于查询的字段应该创建索引。
数据量小的表最好不要使用索引,因为由于数据较少,可能查询全部数据花费的时间比遍历索引的时间还要短,索引就可能不会产生优化效果。
在一同值少的列上(字段上)不要建立索引,比如在学生表的"性别"字段上只有男,女两个不同值。相反的,在一个字段上不同值较多可以建立索引。
上面说的只是很片面的一些东西,索引肯定还有很多别的优点或者缺点,还有使用原则,先基本上理解索引,然后等以后真正用到了,就会慢慢知道别的作用。
4、MySQL数据库的索引类型
索引我们分为四类来讲 单列索引(普通索引,唯一索引,主键索引)、组合索引、全文索引、空间索引单列索引:一个索引只包含单个列,但一个表中可以有多个单列索引。
(1)普通索引
MySQL中基本索引类型,没有什么限制,允许在定义索引的列中插入重复值和空值,用于加速查询。
创建方法:
a. 建表的时候一起创建
CREATE TABLE mytable ( name VARCHAR(32) , INDEX index_mytable_name (name) );
b. 建表后,直接创建索引
CREATE INDEX index_mytable_name ON mytable(name);
c. 修改表结构
ALTER TABLE mytable ADD INDEX index_mytable_name (name);注:如果是字符串字段,还可以指定索引的长度,在列命令后面加上索引长度就可以了(例如:name(11))
(2)唯一索引
索引列中的值必须是唯一的,但是允许为空值。如果是组合索引,则列值的组合必须唯一。
创建方法:
a.建表的时候一起创建
CREATE TABLE mytable ( `name` VARCHAR(32) , UNIQUE index_unique_mytable_name (`name`) );
b. 建表后,直接创建索引
CREATE UNIQUE INDEX index_mytable_name ON mytable(name);
c. 修改表结构
ALTER TABLE mytable ADD UNIQUE INDEX index_mytable_name (name);注:如果是字符串字段,还可以指定索引的长度,在列命令后面加上索引长度就可以了(例如:name(11))
(3)主键索引
是一种特殊的唯一索引,一个表只能有一个主键,不允许有空值。一般是在建表的时候同时创建主键索引。
创建方法:
a.建表的时候一起创建
CREATE TABLE mytable ( `id` int(11) NOT NULL AUTO_INCREMENT , `name` VARCHAR(32) , PRIMARY KEY (`id`) );
b. 修改表结构
ALTER TABLE test.t1 ADD CONSTRAINT t1_pk PRIMARY KEY (id);注:如果是字符串字段,还可以指定索引的长度,在列命令后面加上索引长度就可以了(例如:name(11))
(4)组合索引
在表中的多个字段组合上创建的索引,只有在查询条件中使用了这些字段的左边字段时,索引才会被使用,使用组合索引时遵循最左前缀集合。
创建方法:
a.建表的时候一起创建
CREATE TABLE mytable ( `id` int(11) , `name` VARCHAR(32) , INDEX index_mytable_id_name (`id`,`name`) );
b. 建表后,直接创建索引
CREATE INDEX index_mytable_id_name ON mytable(id,name);
c. 修改表结构
ALTER TABLE mytable ADD INDEX index_mytable_id_name (id,name);
(5)全文索引
全文索引,只有在MyISAM引擎上才能使用,只能在CHAR,VARCHAR,TEXT类型字段上使用全文索引,介绍了要求,说说什么是全文索引,就是在一堆文字中,通过其中的某个关键字等,就能找到该字段所属的记录行,比如有"你是个靓仔,靓女 ..." 通过靓仔,可能就可以找到该条记录。这里说的是可能,因为全文索引的使用涉及了很多细节,我们只需要知道这个大概意思。
创建方法:
a. 建表的时候一起创建
CREATE TABLE `article` ( `id` int(11) NOT NULL AUTO_INCREMENT , `title` char(250) NOT NULL , `contents` text NULL , `create_at` int(10) NULL DEFAULT NULL , PRIMARY KEY (`id`), FULLTEXT (contents) );
b. 建表后,直接创建索引
CREATE FULLTEXT INDEX index_article_contents ON article(contents);
c. 修改表结构
ALTER TABLE article ADD FULLTEXT INDEX index_article_contents (contents);
(6)空间索引
空间索引是对空间数据类型的字段建立的索引,MySQL中的空间数据类型有四种,GEOMETRY、POINT、LINESTRING、POLYGON。在创建空间索引时,使用SPATIAL关键字。要求,引擎为MyISAM,创建空间索引的列,必须将其声明为NOT NULL。
如果任何问题或者建议,欢迎留言交流。
以上内容希望帮助到大家,很多PHPer在进阶的时候总会遇到一些问题和瓶颈,业务代码写多了没有方向感,不知道该从那里入手去提升,对此我整理了一些资料,包括但不限于:分布式架构、高可扩展、高性能、高并发、服务器性能调优、TP6,laravel,YII2,Redis,Swoole、Swoft、Kafka、Mysql优化、shell脚本、Docker、微服务、Nginx等多个知识点高级进阶干货需要的可以免费分享给大家,需要的可以加入我的PHP技术交流群点击此处。