MySQL是一个开源的关系型数据库,由MySQL AB公司开发,目前已被Oracle收购。其遵循GPL协议,用户可根据需求定制化开发资金的MySQL。MySQL可移植性高,支持多种语言,例如:Java、PHP、C++、Python、Perl、Eiffel、Rubby等。其使用标准的SQL数据语言形式,可通过如下数据语言进行使用:
DQL:数据查询语言,select、from、where;
DML:数据操作语言,insert、delete、update;
DDL:数据定义语言,create、alter、drop、truncate;
DCL:数据控制语言,grant、rollback、commit
MySQL常用的SQL说明:
SQL | 描述 | 备注 |
---|---|---|
show databases | 列出所有数据库 | |
create database test01 | 创建数据库test01 | |
create database test01 character set utf8 | 创建数据库,并设置字符集为utf-8 | |
show create database test01 | 查看数据库字符集 | |
show variables like ’%char%‘ | 查询参数 | |
set [字符集属性]=utf8 | 设置字符集属性为utf8 | 仅临时更改,如需彻底修改需改配置文件 |
alter database test01 character set ‘utf8’ | 修改数据库字符集 | |
alter table table01 convert to character set ’utf8‘ | 修改数据表字符集 |
MySQL支持大型数据库,支持5000万条记录的数据仓库,32位系统表文件最大支持4GB,64位系统表文件最大支持8TB。在200万条记录下不加索引性能依旧较好。
注意:
字符集需要安装之后立即修改,如果插入数据之后再进行修改则之前数据库、表格及数据依然为原编码格式!
以5.7.28为例:参考博文MySQL 5.7.28安装最稳教程
CentOS 7 使用docker安装mysql
yum install mysql
rpm -qa|grep mysql
rpm -ivh MySQL-client-xxx.linu.xxx.rpm
rpm -ivh MySQL-server-xxx.linu.xxx.rpm
tips:
sql_mode定义了对MySQL中的语法校验规则,其默认值是空值,这种情况下是可以进行一些非法操作的,生产环境下必须将该值设置为严格模式,以下为sql_mode常用的值。
参数 | 说明 |
---|---|
ONLY_FULL_GROUP_BY | 若select未选中group by的字段,则SQL不合法 |
NO_AUTO_VALUE_ON_ZERO | 自增长列可插入0或者null |
STRICT_TRANS_TABLES | 若一个值不能插入到事务表中,则中断,对非事务表不做限制 |
NO_ZERO_IN_DATE | 严格模式下不允许日期和月份为零 |
NO_ZERO_DATE | 日期不允许插入零 |
ERROR_FOR_DIVISION_BY_ZERO | insert或update中,若数据被零除,则报错,如果未给出该模式,则返回null |
NO_AUTO_CREATE_USER | 禁止grant创建密码为空的用户 |
NO_ENGINE_SUBSTITUTION | 存储引擎被禁用则报错,若未设置则使用默认的存储引擎代替 |
查看:select @@sql_mode
修改:set @@sql_mode=’’;
命令 | 说明 | 备注 |
---|---|---|
create user z3 identified by ’123456‘ | 创建名称为z3,密码为12346的用户 | |
select host,user,password,select_priv,insert_priv,drop_priv from mysql.user | 查看用户和权限信息 | |
set password = password(‘123456’) | 修改当前用户密码 | |
update mysql.user set password=password(‘123456’) where user = ‘z3’ | 修改其他用户密码 | 通过user表的修改需要flush privileges才能生效 |
update mysql.user set user = ‘li4’ where user =‘z3’ | 修改用户名 | 通过user表的修改需要flush privileges才能生效 |
drop user li4 | 删除用户 | 不要通过user表删除,系统会有残留 |
host:表示连接类型
命令 | 说明 |
---|---|
grant select,insert,delete,drop on mydb.* to z3@localhost | 给本地的z3用户的mydb数据库所有表授予增删改查权限 |
grant all privileges on *.* to z3@’%’ identified by ‘123’ | 授予通过网络登录的z3用户对所有库的权限,密码为123 |
show grants | 查看权限 |
revoke all privileges on mysql.* from z3@localhost | 收回z3全库全表所有权限 |
一般使用SQL操作数据库时,当遇到SQL执行时间太长怎么办呢?一般我们都是从下面四个方面进行查摆问题一一优化:
在优化开始之前,我们需要了解MySQL的逻辑架构是怎样的,也就是MySQL是如何处理我们的SQL语句的呢?
上图为MySQL逻辑架构图,其主要分为连接层、服务层、引擎层及存储层。
连接层,MySQL最上层,它是一些客户端和连接服务,包含本地socket通信和基于客户端连接的类似tcp/ip通信,主要完成连接处理、授权认证及相关安全方案,该层引入了线程池的概念为安全认证客户端提供线程,例如驱动连接。
服务层:
Management Services & Utilities | 系统管理和控制工具 |
---|---|
SQL Interface | SQL接口:接收SQL返回查询结果 |
Parser | 解析器:验证和解析SQL语句 |
Optimizer | 查询优化器:MySQL对SQL会根据优化器结果进行优化 |
Cache&Buffer | 查询缓存:提高查询效率 |
引擎层
可插拔式引擎的选择,负责MySQL中数据的存储和查询,目前MySQL最常用的两种数据库存储引擎为InnoDB与MyISAM,下表为二者的区别。
特性 | InnoDB | MyISAM |
---|---|---|
是否支持事务 | 支持 | 不支持事务 |
是否支持外键 | 支持 | 不支持 |
索引类型 | 聚簇索引 | 非聚簇索引 |
是否保存表的行数 | 否 | 是(通过变量保存,避免select count(*) 时进行全表扫描) |
全文索引 | 5.7以后支持 | 支持 |
是否可压缩后查询 | 否 | 是 |
锁的粒度 | 行锁 | 表锁 |
主键是否必须 | 是(聚簇索引特性) | 否 |
存储文件 | frm(表结构),ibd(数据文件) | frm(表结构),myd(数据文件),myi(索引文件) |
tips:
1、聚簇索引与非聚簇索引
聚簇索引:数据与索引是在同一B+Tree上的,非叶子节点存放的是索引(数据的指针),叶子节点存放的是数据,该索引类型必须有主键,数据可通过主键进行查询,之后建立的索引为辅助索引,辅助索引需要两次查询,先查询到主键,然后通过主键查询数据,所以主键最好设置为自增,否则主键过大会带来额外开销;
非聚簇索引:B+Tree的非叶子节点和叶子节点存放的都是数据的引用地址,数据文件与索引文件是分开保存的。
2、InnoDB的行锁是实现在索引上的,而不是锁在物理上,如果索引失效则行锁会退化为表锁。
通过对MySQL逻辑结构的分析,我们可以知道SQL查询的流程大致为:
SQL手写为:
优化器优化之后的顺序:
tips:
- show engines可查看所有数据库引擎
- show variables like ‘%storage_engine%’ 可查看当前默认数据库引擎
通过show profile可以查看SQL的详细执行周期,可以作为优化SQL最强有力的工具。
show profiles可以提供SQL执行的详细信息,但是实际中我们更多使用explain对SQL进行解释优化,查看SQL是否使用索引等等,下文更多是针对explain的使用进行介绍。
如何提高SQL执行速度?许多人第一反应就是增加索引,什么是索引呢?如何增加索引且增加的索引不会因为SQL问题导致失效呢?
我们知道MySQL底层使用B+树实现,索引作为数据的另一种表现形式同样也会耗费存储空间的。
如果单纯的为了提升某个字段的查询效率而在全表字段上都增加索引,那么无疑给存储空间带来了巨大负担。而且索引增加之后虽然给查询带来了便利,但是在增加和删除方面,为了维护索引而带来的工作量也是极为繁重的,这说明了不经研究而随意建立索引的方法是不可取的。
索引是帮助MySQL高效获取数据的数据结构,所以索引可以简单理解为排好序的快速查找数据结构。
优点:
劣势:
在日常工作中,使用最为频繁的就是通过explain+SQL模拟优化器执行SQL语句,从而知道MySQL是如何处理SQL语句的,并根据情况分析SQL的性能瓶颈以优化SQL。
那么,通过explain我们可以获得什么信息呢?
我们通过explain+SQL的方式可以获得如下所示的列表:
可以看出主要参数即:id,select_type,table,partitions,type,possible_keys,key,key_len,ref,rows,filtered,Extra。
以下针对第一行参数进行详细分析:
id:select查询的序列号,包含一组数字,表示查询中select子句或操作表的顺序,主要分以下三种情况:
select_type:查询的类型,主要用于区别普通查询、联合查询、子查询等的复杂查询,具体参数如下:
table:显示改行的数据来源于哪张表
partitions:是否分区
type:优化器定义的访问类型,从最好到最差依次是scerria(system>const>ref_eq>ref>range>index>all),具体含义如下:
一般来说,保证查询达到range或者ref效果为佳。
possible_keys:显示可能应用在这张表中的索引,一个或多个。查询所涉及字段若存在索引,则索引将被列出,但不一定被使用
key:查询中实际使用的索引,如果没有则为null,查询中如果使用了覆盖索引,则索引和查询的字段一一吻合
key_len:表示索引使用到的字节数,可通过该值计算查询中使用的索引长度。在不损失精度的情况下,该值越小越好。该值为索引最大可能长度,并非实际使用长度。
ref:显示索引哪一列被使用了,哪些列或者常数被用于索引进行查询(最好是常数)。也就是说key 列是实际使用的 index , 但 index 可能建立在数据表的若干列上。ref 列列出具体哪些列或常数被使用了。
rows:根据表统计信息及索引使用情况大致估算除所需要读取的行数
filtered:返回结果的行占需要读到的行(rows列的值)的百分比,因为对于join操作,前一个表的结果集大小直接影响了循环的次数
Extra:包含不适合在其他列中显示但十分重要的额外信息,其主要会有以下几个常数:
参数 | 说明 |
---|---|
Using filesort | MySQL会对数据使用外部的文件索引排序,而不是按照表内索引顺序读取,文件的建立删除会耗费大量资源,出现该项一定要优化 |
Using temporary | 使用临时表保存中间结果,常见于order by、group by,临时表的创建与删除会耗费大量资源,出现该项一定要优化 |
Using index | 相应的select中使用了覆盖索引,避免访问冗余数据,效果不错,同时出现Using where则表明索引被用来执行索引键的查找,若没有出现Using where 则表明索引用于读取数据而非执行查找 |
Using where | 表明使用了where过滤 |
Using join buffer | 使用了连接缓存,可在my.cnf中增加缓存大小 |
impossible where | where的值总是false,不能获取任何值 |
select tables optimized away | 在没有GROUPBY子句的情况下,基于索引优化MIN/MAX操作或者对于MyISAM存储引擎优化COUNT(*)操作,不必等到执行阶段再进行计算,查询执行计划生成的阶段即完成优化。 |
distinct | 优化distinct,找到第一匹配值即停止 |
以上就是对explain参数的分析,通过对这些参数的学习,将使得我们以后在SQL优化方面无论遇到什么问题都能对症下药,迎刃而解。
有时候我们明明在字段上建立了索引,但是explain之后发现优化器并没有使用到索引,那什么情况下会导致索引失效?写SQL语句时应该注意些什么才能避免索引失效呢?
以下是常见导致索引失效的几种情况:
以上就是会造成MySQL索引失效的一些情况,为了避免这些情况的出现而造成索引失效,建议:
完!如有不妥欢迎批评指正!