Mysql详解

一、Mysql简介

1.启动和停止MySQL服务

方式一:计算机-管理-服务-启动或停止Mysql
方式二: 启动 net start mysql服务名
停止 net stop mysql服务名

2.服务端的登陆和退出

mysql -h 主机名 -u用户名 -p 密码
exit

3.DQL、DML、DDL、DCL语言

DML(Data Mainipulation Language):数据操纵语句,用于增删查改数据库记录
INSERT\UPDATE\DELETE\SELECT
DDL(Data Definition Language):数据定义语言,用于库和表的创建、修改、删除
CREATE\ALTER\DROP\CREATE INDEX\DROP INDEX
DCL(Data Control Language):数据控制语言,用于定义用户的访问权限和安全级别
GRANT\REVOKE\COMMIT\ROLLBACK\SAVEPOINT\LOCK

4.数据库基本操作

查看mysql中有哪些数据库?show
使用一个数据库 use
新建一个数据库 create

查看制定数据库中有哪些表
创建表 create
查看表的结构 show
删除表 alter
查看表 select
向表中插入记录 insert
修改记录 update
删除记录 delete

查询表中所有列
查询特定列
对数据进行过滤
运算符

二、DQL

1.SELECT和FROM

SELECT 列名或*(列名用逗号隔开) FROM 表名;

2.别名

AS 加别名 全字母大写
“别名” 指定别名;

3.字符串

字符串可以是 SELECT 列表中的一个字符,数字,日期。
日期和字符只能在单引号中出现。
每当返回一行时,字符串被输出一次。

4.DESCRIBE

DESCRIBE 表命;
显示表的结构

5.distinct

distinct去重,但是大表一般用distinct效率不高,大数据量的时候都禁止用distinct,建议用group by解决重复问题。

6.Where

用于过滤,紧跟FROM
可以用 = 、<、>、 BETWEEN … AND … 、IN(值、值、值) 、 LIKE 、 IS NULL

在这里插入图片描述

LIKE中%代表0个或多个字符、_代表一个字符,可以同时使用

AND、OR、NOT 逻辑运算

ORDER BY 写在SELECT之后, -ASC升序(不写默认) -DESC降序
ORDER BY 列名/别名,列名/别名 ASC
可以使用不在SELECT列表中的列排序

7.分组函数

分组函数作用于一组数据,并对一组数据返回一个值
AVG() 平均数,
COUNT() 总数,
MAX() 最大值,
MIN() 最小值,
SUM() 总和
可用在SELECT WHERE中

8.GROUP BY

可以使用GROUP BY 将表中的数据分成若干组,与SELCET中分组函数配合使用
在SELECT列表中所有未包含在组函数中的列都应该包含在GROUP BY子句中

在这里插入图片描述

GROUP BY中可以包含多个列,

9.HAVING

使用HAVING过滤分组,
1.行已经被分组
2.使用了分组函数
3.满足HAVING子句中的条件的分组将被显示出来
在这里插入图片描述

10.多表查询

等值连接
非等值连接 (内连接)
外连接
交叉连接

select 列名,… from 表1
【inner|left outer|right outer|cross】join 表2 on 连接条件
【inner|left outer|right outer|cross】join 表3 on 连接条件
【where 筛选条件】
【group by 分组字段】
【having 分组后的筛选条件】
【order by 排序的字段或表达式】

INNER JOIN 两边表同时有对应的数据,即任何一边缺失数据就不显示。
LEFT JOIN 会读取左边数据表的全部数据,即便右边表无对应数据。
RIGHT JOIN 会读取右边数据表的全部数据,即便左边表无对应数据。

使用表名前缀在多个表中区分相同的列

可以使用表的别名在FROM中,使用后SELECT中需要使用别名.列名

在这里插入图片描述

连接n各表,至少需要n-1个连接条件,

11.ON

自然连接中是以具有相同名字的列为连接条件的。

可以使用ON子句指定额外的连接条件,这个连接条件是与其它条件分开的
ON子句使语句更具有易读性
内连接: [inner] join on

外连接:
左外连接 left[ out] join on
右外连接 right [out] join on

12.表连接总结

在这里插入图片描述
在这里插入图片描述

13.UNION

联合 拼接 去重
在这里插入图片描述
UNION ALL 不去重
在这里插入图片描述

14.常见函数

1、字符函数

upper转换成大写
lower转换成小写
在这里插入图片描述
concat拼接
substr截取子串
length 获取字节个数
instr返回子串第一次出现的索引
lpad左填充
rpad右填充
trim去掉前后指定的空格和字符
ltrim去掉左边空格
rtrim去掉右边空格
replace替换
在这里插入图片描述

2、数学函数
round 四舍五入

在这里插入图片描述
rand 随机数
floor向下取整
ceil向上取整
mod取余
truncate截断

3、日期函数

now当前系统日期+时间
curdate当前系统日期
curtime当前系统时间
str_to_date 将字符转换成日期
在这里插入图片描述
date_format将日期转换成字符
在这里插入图片描述

4、流程控制函数
if 处理双分支
case语句 处理多分支
	情况1:处理等值判断
	情况2:处理条件判断	
5、其他函数
version版本
database当前库
user当前连接用户

三、DML

1.INSERT INTO

INSERT INTO 表名(列名) VALUES (值)
字符和日期型数据应包含在单引号中
在这里插入图片描述

插入空值
在这里插入图片描述
从其他表中拷贝数据
在这里插入图片描述

2.UPDATE

UPDATE 表名 SET 列名=值 WHERE 条件

如果没有WHERE表中相关列全部改变
若没有该列 则报错。

3.DELETE FROM

DELETE FROM 表名 WHERE 条件

四、子查询

1.基本概念:

出现在其他语句内部的select语句
select first_name
from employees
where
department_id in(
select department_id
from departments
where location_id=1700
)

子查询要包括在括号内。
将子查询放在比较条件的右侧

2.单行子查询

只返回一行
单行操作符对应单行子查询,多行操作符对应多行自查询

子查询 (内查询) 在主查询之前一次执行完成。
子查询的结果被主查询(外查询)使用 。

使用子查询解决:谁的工资比Abel高?(子查询为Abel的工资是多少?)

3.多行子查询

返回多行查询结果
使用多行比较操作符
IN/NOT IN 、等于列表中任意一个
ANY/SOME 、和子查询返回的某一个比较
ALL 和子查询返回的所有值比较
解决问题:
返回location_id是1400或1700的部门中的所有员工姓名 IN
返回其它部门中比job_id为‘IT_PROG’部门任一工资低的员工的员工号、姓名、job_id 以及salary ANY
返回其它部门中比job_id为‘IT_PROG’部门所有工资低的员工的员工号、姓名、job_id 以及salary ALL

五、DDL

1.CTEATE创建、SHOW查看、USE使用数据库

在这里插入图片描述

2.数据库命名规则

在这里插入图片描述

3.CTEATE创建表

必须指定表名、列名、数据类型、尺寸

CREATE TABLE 表名(
	列名 数据类型(长度),
	列名 数据类型(长度)
);

4.AS使用子查询创建表

复制现有的表

在这里插入图片描述
在这里插入图片描述

5.ALTER TABLE

实现对已有表中的列进行添加、修改、删除、重命名
ADD添加列:
在这里插入图片描述
MODIFY修改列:
DEFAULT
在这里插入图片描述

DROP COLUMN删除一个列
在这里插入图片描述

CHANGE重命名
在这里插入图片描述

6.DROP TABLE

DROP TABLE 表名

数据和结构都被删除
所有正在运行的相关事务倍提交
所有相关索引被删除
删除操作不能回滚

7.TRUNCATE TABLE

TRUNCATE TABLE 表名

清空表中的所有数据
删除操作不能回滚,使用delete删除表中的数据可以回滚

8.RENAME

改变表的视图名称
在这里插入图片描述

六、MySQL中的数据类型

1.数值类型

整数类型 字节 范围
tinyint 1 -128到127
无符号0到255
smallint 2
medimint 3
int Integer 4
Bigint 8
float 4
double 8
DEC(m,d)
DECIMAL(m,d) m+2
bit(M) 1~8

2.字符类型

字符类型 字节 范围
char(m) m m为0~255
varchar(m) m m为0~65535
binary
varbinary 存储二进制
Enum 1或2 1255或165535 指定值
Set 1到8 0~64 多个指定值

3.日期类型

日期类型 字节 最小值 最大值
date 4 1001-01-01 9999-12-31
datetime 8 1001-01-01 0:0:0 9999-12-31 23:59:59
timestamp 4
time 3
year 1 1901 2155

七、约束

1.NOT NULL

非空约束

表中增加约束:ALTER TABLE 表名 MODIFY 列名 数据类型 NOT NULL;

2.UNIQUE

唯一约束,允许出现多个空值
一个表可以有多个唯一约束,
多个列组合的唯一约束即列与列组合起来唯一。
mysql会给唯一约束的列上默认创建一个唯一索引。

表中增加唯一约束:
ALTER TABLE 表名 ADD UNIQUE(列名,列名);
ALTER TABLE 表名 ADD CONSTRAINT uk_name_pwd UNIQUE(列名,列名);
ALTER TABLE 表名 MODIFY 列名 数据类型 UNIQUE;

3.PRIMARY KEY

主键约束,唯一且非空
如果使多列组合的主键约束,那么这些列都不允许为空值,并且组合的值不允许重复。
每个表最多一个主键
在这里插入图片描述
在这里插入图片描述

4.FOREIGN KEY

外键约束

5.CHECK

Mysql不支持check约束,但可以使用check,没有效果

6.DEFAULT

八、分页

1.LIMIT

前10条记录:SELECT * FROM table LIMIT 0,10;
 第11至20条记录:SELECT * FROM table LIMIT 10,10;
 第21至30条记录: SELECT * FROM table LIMIT 20,10;
kai’sh
LIMIT x,b
从x开始的的b条记录

SELECT * FROM table LIMIT(PageNo - 1)*PageSize,PageSize;

九、事务

1.事务的概述

事务由单独单元的一个或多个SQL语句组成,在这个单元中,每个MySQL语句是相互依赖的。而整个单独单 元作为一个不可分割的整体,如果单元中某条SQL语句一 旦执行失败或产生错误,整个单元将会回滚。所有受到影 响的数据将返回到事物开始以前的状态;如果单元中的所有SQL语句均执行成功,则事物被顺利执行。

2.存储引擎

在mysql中的数据用各种不同的存储技术存储在文件或内存中。
通过show engines;来查看mysql支持的存储引擎。
在mysql中用的最多的存储引擎有:
innodb,myisam ,memory 等。
其中innodb支持事务,而 myisam、memory等不支持事务

3.事务的特点

原子性:要么都执行,要么都回滚
一致性:保证数据的状态操作前和操作后保持一致
隔离性:多个事务同时操作相同数据库的同一个数据时,一个事务的执行不受另外一个事务的干扰
持久性:一个事务一旦提交,则数据将持久化到本地,除非其他事务对其进行修改

4.事务的使用?

1、开启事务(以第一个DML语句的执行作为开始)
2、编写事务的一组逻辑操作单元(多条sql语句)
3、提交事务或回滚事务

set autocommit=0;
start transaction;//开启事务
commit;//事务提交
rollback;//回滚

savepoint 断点
commit to 断点
rollback to 断点

5.事务并发问题如何发生?

脏读:一个事务读取到了另外一个事务未提交的数据

不可重复读:同一个事务中,多次读取到的数据不一致

幻读:一个事务读取数据时,另外一个事务进行更新,导致第一个事务读取到了没有更新的数据

6.如何避免事务的并发问题?

当多个事务同时操作同一个数据库的相同数据时

通过设置事务的隔离级别
1、READ UNCOMMITTED 未提交读
2、READ COMMITTED 已提交 读可以避免脏读
3、REPEATABLE READ 重复读 可以避免脏读、不可重复读和一部分幻读
4、SERIALIZABLE 串行读 可以避免脏读、不可重复读和幻读

set session|global transaction isolation level 隔离级别名;

select @@tx_isolation;//查看隔离级别

十、视图

1.VIEM

MySQL从5.0.1版本开始提供视图功能。
一种虚拟存在的表,行和列的数据来自定义视图的查询中使用的表,并且是在使用视图时动态生成的,只保存了sql逻辑,不保存查询结果

应用场景
多个地方用到同样的查询结果
该查询结果使用的sql语句较复杂

2.视图和表的区别

使用方式 占用物理空间

视图 完全相同 不占用,仅仅保存的是sql逻辑

表 完全相同 占用

视图的优势
1、sql语句提高重用性,效率高
2、和表实现了分离,提高了安全性

3.视图的创建、修改、删除查看

视图的创建 语法: CREATE VIEW 视图名 AS 查询语句;
视图的删除 DROP VIEW test_v1,test_v2,test_v3;
视图结构的查看 DESC test_v7; SHOW CREATE VIEW test_v7;
视图逻辑的更新:
CREATE OR REPLACE VIEW test_v7
AS SELECT last_name
FROM employees
WHERE employee_id>100;

ALTER VIEW test_v7ASSELECT employee_id
FROM employees;
SELECT * FROM test_v7;

(1)查看视图的数据
SELECT * FROM my_v4;
SELECT * FROM my_v1 WHERE last_name=‘Partners’;

(2)插入视图的数据
INSERT INTO my_v4(last_name,department_id) VALUES(‘虚竹’,90);

(3)修改视图的数据
UPDATE my_v4 SET last_name =‘梦姑’ WHERE last_name=‘虚竹’;

(4)删除视图的数据
DELETE FROM my_v4;

4.视图不能更新的情况

包含以下关键字的sql语句:
分组函数、distinct、group by、having、union或者union all 常量视图
Select中包含子查询 join
from一个不能更新的视图
where子句的子查询引用了from子句中的表

十一、存储过程以及函数

1.procedure

事先经过编译并存储在数据库中的一段sql语句的集合。

2.存储过程的分类

1、无返回无参
2、仅仅带in类型,无返回有参
3、仅仅带out类型,有返回无参
4、既带in又带out,有返回有参
5、带inout,有返回有参
注意:in、out、inout都可以在一个存储过程中带多个

3.创建

create procedure 存储过程名(in|out|inout 参数名 参数类型,…)
begin
存储过程体
end

4.注意事项

1、需要设置新的结束标记
delimiter 新的结束标记
示例:
delimiter $
CREATE PROCEDURE 存储过程名(IN|OUT|INOUT 参数名 参数类型,…)
BEGIN
sql语句1;
sql语句2;
END $

2、存储过程体中可以有多条sql语句,如果仅仅一条sql语句,则可以省略begin end

3、参数前面的符号的意思
in:该参数只能作为输入 (该参数不能做返回值)
out:该参数只能作为输出(该参数只能做返回值)
inout:既能做输入又能做输出

5.调用存储过程

call 存储过程名(实参列表)

6.FUNCTION

创建:
CREATE FUNCTION 函数名(参数名 参数类型,…)
RETURNS 返回类型
BEGIN
函数体
END

7.调用函数

调用函数 SELECT 函数名(实参列表)

8.函数与存储过程的区别

关键字 调用语法 返回值 应用场景
函数 FUNCTION SELECT 函数() 只能是一个 一般用于查询结果为一个值并 返回时,当有返回值而且仅仅一个
存储过程 PROCEDURE CALL 存储过程() 可以有0个或多个 一般用于更新

9.存储过程以及函数的修改、删除、查看

• 修改存储过程:
alter procedure 存储过程名 [charactristic…]
• 修改函数:
alter function 函数名 [charactristic…]
characteristic:
{contains sql|no sql|reads sql data|modifies sql data}
|sql security{definer|invoker}
|comment ‘string’

说明:一次只能删除一个存储过程或者函数,并且要求有该 过程或函数的alter routine 权限
删除存储过程:
drop procedure [if exists] 存储过程名
删除函数:
drop function [if exists] 函数名

1.查看存储过程或函数的状态:
show {procedure|function} status like 存储过程或函数名
2.查看存储过程或函数的定义:
show create {procedure|function} 存储过程或函数名
3.通过查看information_schema.routines了解存储过程和函数的信息(了解)
select * from rountines where rounine_name =存储过程名|函数名

十二、流程控制结构

1.变量

系统变量:全局变量和会话变量
自定义变量:用户变量,局部变量

2.全局变量

作用域:针对于所有会话(连接)有效,但不能跨重启
查看所有全局变量SHOW GLOBAL VARIABLES;
查看满足条件的部分系统变量SHOW GLOBAL VARIABLES LIKE ‘%char%’;
查看指定的系统变量的值SELECT @@global.autocommit;
为某个系统变量赋值SET @@global.autocommit=0;SET GLOBAL autocommit=0;

3.会话变量

作用域:针对于当前会话(连接)有效
查看所有会话变量SHOW SESSION VARIABLES;
查看满足条件的部分会话变量SHOW SESSION VARIABLES LIKE ‘%char%’;
查看指定的会话变量的值SELECT @@autocommit;SELECT @@session.tx_isolation;
为某个会话变量赋值SET @@session.tx_isolation=‘read-uncommitted’;
SET SESSION tx_isolation=‘read-committed’;

4.用户变量

声明并初始化:
SET @变量名=值;
SET @变量名:=值;
SELECT @变量名:=值;
赋值:
方式一:一般用于赋简单的值
SET 变量名=值;
SET 变量名:=值;
SELECT 变量名:=值;

方式二:一般用于赋表 中的字段值
SELECT 字段名或表达式INTO变量
FROM 表;
使用:
select @变量名;

5.局部变量

声明:
declare 变量名 类型 【default 值】;
赋值:
方式一:一般用于赋简单的值
SET 变量名=值;
SET 变量名:=值;
SELECT 变量名:=值;

方式二:一般用于赋表 中的字段值
SELECT 字段名或表达式 INTO 变量
FROM 表;
使用:
select 变量名

6.用户变量和局部变量的区别

作用域	定义位置	语法

用户变量 当前会话 会话的任何地方 加@符号 不用指定类型
局部变量 定义它的BEGIN END中 BEGIN END的第一句话 一般不用加@ 需要指定类型

7.if函数

语法:if(条件,值1,值2)
特点:可以用在任何位置

8.case语句

语法:
情况一:类似于switch
case表达式
when 值1 then 结果1或语句1(如果是语句,需要加分号)
when 值2 then 结果2或语句2(如果是语句,需要加分号)

else 结果n或语句n(如果是语句,需要加分号)
end 【case】(如果是放在begin end中需要加上case,如果放在select后面不需要)

情况二:类似于多重if
case
when 条件1 then 结果1或语句1(如果是语句,需要加分号)
when 条件2 then 结果2或语句2(如果是语句,需要加分号)

else 结果n或语句n(如果是语句,需要加分号)
end 【case】(如果是放在begin end中需要加上case,如果放在select后面不需要)

9.if elseif语句

语法:
if 情况1 then 语句1;
elseif 情况2 then 语句2;
…else 语句n;
end if;
特点: 只能用在begin end中!!!!!!!!!!!!!!!

10.if语句比较

应用场合
if函数 简单双分支
case结构 等值判断 的多分支
if结构 区间判断 的多分支

11.循环

语法:
【标签:】WHILE 循环条件 DO
循环体END WHILE 【标签】;
特点:
只能放在BEGIN END里面
如果要搭配leave跳转语句,需要使用标签,否则可以不用标签
leave类似于java中的break语句,跳出所在循环!!!

十三、索引

1.索引的定义

MySQL官方对索引的定义为:
索引(Index)是帮助MySQL高效获取数据的数据结构.可以得出索引的本质就是数据结构
  你可以简单理解为"排序好的快速查找数据结构"
  在数据之外,数据库还维护着满足特定查找算法的数据结构,这些数据结构以某种方式引用(指向)数据,这样就可以在这些数据结构的基础上实现高级查找算法,这种数据结构就是索引
  一般来说索引本身很大,不适合全部存储在内存中,因此索引往往以索引文件的形式存储在磁盘上
  我们平常所说的索引,如果没有特别指明,都是指B树(多路搜索树,并不一定是二叉的)结构组织的索引,其中聚集索引,次要索引,覆盖索引,复合索引,前缀索引,唯一索引默认都是使用B+树索引,统称索引.当然,除了B+树这种类型的索引之外,还有哈稀索引(hash index)等

2.索引的优缺点

优势
  类似大学图书馆建书目录索引,提高数据检索的效率,降低数据库的IO成本
  通过索引列对数据进行排序,降低数据排序成本,降低了CPU的消耗
  可以加速表和表之间的连接
劣势
  实际上索引也是一张表,该表保存了主键与索引字段,并指向实体表的记录,所以索引也是要占内存空间的
  虽然索引大大提高了查询速度,同时都会降低更新表的速度,如对表进行insert,update和delete
  因为更新表时,MySQL不仅要保存数据,还要保存一下索引文件每次更新添加了索引的字段,都会调整因为更新所带来的键值变化后的索引信息
  索引只是高效的一个因素,如果你的MySQL有大数据量的表,就需要花时间研究建立最优秀的索引,或优化查询方法

3.索引的分类

单值索引:即一个索引只包含单个列,一个表不\可以有多个单列索引

唯一索引:索引列的值必须唯一,但允许有控制,例如手机号,银行卡号等值必须是唯一

复合索引:即一个索引包含多个列,例如手机号和银行卡号一起,如果一个表中的数据在查询时有多个字段总是同时出现则这些字段就可以作为复合索引

4.索引的基本语法

创建:create [unique] index indexName on tbname(columnname(lenght))

更改:alter table tbname add [unique] index [indexName] on (columnname(lenght))
更改:alter table tbname add [unique] fulltext [indexName] on (columnname(lenght))#指定索引为fulltext,用于全文索引
删除:drop index [indexName] on tbname;
查看:show index from tbname\G;

5.索引结构

BTree索引
  Hash索引
  full-text全文索引
  R-Tree索引

6.创建索引的应用场景

哪种情况需要创建索引
  1.主键自动建立唯一索引
  2.频繁作为查询条件的字段应该创建索引
  3.查询中与其他表关联的字段,外键关系建立索引
  4.频繁更新的字段不适合创建索引,因为每次更新不单单是更新数据还会更新索引
  5.Where条件里用得到的字段适合创建索引
  6.单键/组合索引的选择问题,在高并发下倾向创建组合索引
  7.查询中排序的字段,排序字段若通过索引去访问将大大提高排序速度
  8.查询中统计或者分组字段
  
哪种情况不需要建索引
  1.表记录太少(一般生产环境下,三百万条记录性能就可能开始下降,官方说的是五百万到八百万)
  2.经常增删改的表
  3.某个数据列的值包含许多重复的内容

7.性能分析

1.MySQL Query Optimizer(查询优化器)

1.1MySQL中有专门负责优化select语句的优化器模块,主要功能:通过计算分析系统中收集到的统计信息,为客户端请求的query提供它认为最有的执行计划(它认为最优的数据检索方式,但不见得是DBA认为是最优的,这部分是最耗时间的)
  1.2当客户端向MySQL请求一条query,命令解析其模块完成请求分类,区别是select并转发给MySQL Query Optimizer时,MySQL Query Optimizer首先会对整条Query进行优化,处理掉一些常量表达式的预算,直接转换成常量值,并对query中的查询条件进行简化和转换,如去掉一些无用或显而易见的条件,结构调整等,然后分析query中的Hint信息(如果有),看显示Hint信息是否可以完全确定该query的执行计划,如果没有Hint或Hint信息不足以完全确定执行计划,则会读取所涉及对象的统计信息,根据query进行写相应的计算分析,然后再得出最后的执行计划。

2.MySQL常见瓶颈

CPU:CPU在饱和的时候一般发生在数据装入内存或从磁盘读取数据时候
  IO:磁盘IO瓶颈发生在装入数据远大于内存容量的时候
  服务器硬件的性能瓶颈,top,free,iostat和vmstat来查看系统的性能状态

3.Explain

3.1explain+SQL语句顺序解释
  表的读取顺序(数字大的先读,相同的则由上而下读取)
  数据读取操作的操作类型
  哪些索引可以使用
  哪些索引被实际使用
  索引总长度
  表之间的引用
  每张表有多少行被优化器查询
  额外的信息(出现using index较好,出现using filesort较差)
3.2怎么用
  explain+SQL语句
  执行计划包含以下的信息
id select_type table type possible_keys key key_len ref rows extra

8.导致索引失败的案例

1.建什么索引用什么索引,顺序也最好保持一致
  2.最佳左前缀索引名称命名(如字段name,age,city,则索引命名应该是nameAgeCity或者xxx_nameAgeCity,顺序很重要)
  3.不在索引列上做任何操作(计算,函数,or,类型转换),会导致索引失效而转向全表扫描
  4.存储引擎不能使用索引中范围条件右边的列(如name=‘lin’ and age>25 and city=‘qingdao’,则age后面的索引会实效)
  5.尽量使用覆盖索引(只访问索引的查询(索引列和要查询的列一致)),减少select *
  6.MySQL在使用不等于(!=或者<>)的时候无法使用索引会导致全表扫描
  7.is null,is not null 也无法使用索引
  8.like以通配符在这(’%abc’,’%abc%’)两种情况会索引实效变成全表扫描,‘abc%‘则不会,若要’%abc’,’%abc%'不失效,建议使用覆盖索引,且查询的字段要少于索引或者与索引一致,不使用select *。如为name,age,city建了索引,请这么使用:select name或者select age,或者select city或者select name,age,city。如果select name,age,city,email则会全表扫描
  9.字符串不加引号索引失效,
  10.少用or,用他来连接时索引会失效
  11.select * from A where exists (select 1 from where b.id=A.id)#当A表的数据系小于B表时,用exists优于in
  12.使用join代替子查询

9.数据类型的选择

1.数字类型
    Float和double选择(尽量选择float)
    区分开TINYINT / INT / BIGINT,能确定不会使用负数的字段,建议添加 unsigned定义
    能够用数字类型的字段尽量选择数字类型而不用字符串类型的
  2.字符类型
    char,varchar,TEXT的选择:非万不得已不要使用 TEXT 数据类型,定长字段,建议使用 CHAR 类型(填空格),不定长字段尽量使用 VARCHAR(自动适应长度,超过阶段),且仅仅设定适当的最大长度
  3.时间类型
    按选择优先级排序DATE(精确到天)、TIMESTAMP、DATETIME(精确到时间)
  4.ENUM
    对于状态字段,可以尝试使用 ENUM 来存放
  5.避免使用NULL字段
    很难查询优化且占用额外索引空间

10.字符编码

同样的内容使用不同字符集表示所占用的空间大小会有较大的差异,所以通过使用合适的字符集,可以帮助我们尽可能减少数据量,进而减少IO操作次数。
  1.纯拉丁字符能表示的内容,选择 latin1 字符编码
  2.中文可选用utf-8
  3.MySQL的数据类型可以精确到字段,所以当我们需要大型数据库中存放多字节数据的时候,可以通过对不同表不同字段使用不同的数据类型来较大程度减小数据存储量,进而降低 IO 操作次数并提高缓存命中率

11.order by优化和group by 优化

order by优化
  重点:使用order by就需要看会不会产生filesort
  mysql支持两种方式排序,index和filesort,index效率高
  尽量使用Index方式排序,避免使用FileSort方式排序
  尽可能在索引列上完成排序操作,遵照索引列的最佳左前缀
  如果不在索引列上,filesort有两种算法:双路排序和单路排序
  双路排序:取一堆数据,要对磁盘进行两次扫描(mysql4.1之前,后来的版本增加了单路排序)
  单路排序:从磁盘读取查询需要的所有列,按照order by列在buffer对他们进行排序,然后扫描排序后的列表进行输出,效率快,但会使用更多的内存空间,因此注意调整sort_buffer_size和max_lenght_for_sort_data参数值(增大值),避免创建tmp文件从而进行多次I/O

group by优化
  和order by差不多
  先排序后分组,遵照索引列的最佳左前缀
  当无法使用索引列时,增大max_lenght_for_sort_data和sort_buffer_size的值
  where高于having,能在where限定的条件就不要去having限定了

12.优化总结

	1.开启慢查询日志
 	2.expain+慢SQL分析
  3.show profile查询sql在mysql服务器里面的执行细节和生命周期情况
  4.sql数据库服务器的参数调优 

十四、Mysql高级简介

1.Mysql 高手是怎样练成的

数据库内部结构和原理
 数据库建模优化
 数据库索引建立
 SQL 语句优化
 SQL 编程(自定义函数、存储过程、触发器、定时任务)
 mysql 服务器的安装配置
 数据库的性能监控分析与系统优化
各种参数常量设定
主从复制
分布式架构搭建、垂直切割和水平切割
数据迁移
容灾备份和恢复
shell 或 python 等脚本语言开发
对开源数据库进行二次开发

2.检查当前系统是否安装过 Mysql

(1)CentOS6 环境下
命令:rpm -qa|grep mysql

默认 Linux 在安装的时候,自带了 mysql 相关的组件。
先卸载系统自带的 mysql,
执行卸载命令 rpm -e --nodeps mysql-libs
(1)CentOS7 环境下
命令:rpm -qa|grep mariadb

默认 Linux(CentOS7)在安装的时候,自带了 mariadb(mysql 完全开源版本)相关的组件。
先卸载系统自带的 mariadb,执行卸载命令 rpm -e --nodeps mariadb-libs

3.检查/tmp 文件夹权限

查看/tmp 文件夹权限:
赋予其最大权限:chomd -R 777 /tmp

4.安装mysql

安装的版本是 mysql 5.5,官网下载地址:http://dev.mysql.com/downloads/mysql/
①将 rpm 安装包拷贝到 opt 目录下
命令ll查看当前文件夹中文件列表
②在安装目录下执行 rpm 安装
rpm -ivh MySQL-client-5.5.54-1.linux2.6.x86_64.rpm
rpm -ivh MySQL-server-5.5.54-1.linux2.6.x86_64.rpm
-ivm含义:
安装完成后,出现如下警告,需要为软件设置 root 用户的密码。
在这里插入图片描述
③查看是否安装成功:mysqladmin --version
或者也可以通过 rpm 命令来查看:
④设置用户和密码: mysqladmin –u root password xxxxxx

5.Mysql 服务

Mysql 服务的启动和停止
查看状态:service mysql status
启动服务:service mysql start
停止服务:service mysql stop
重启服务:service mysql restart
启动之后,查看进程:ps -ef|grep mysql

6.mysql的安装位置

在这里插入图片描述

7.设置Mysql 服务的自启动

Mysql 服务是开机自动启动的!
查看:chkconfig --list|grep mysql
如果要取消开机自启动,则输入命令 ntsysv
出现以下界面:
使用空格取消选中,然后按 TAB 确定!

8.Mysql重复启动问题

启动两个,登陆时报错
杀死所有和mysql有关的操作:killall mysqld
d代表demon,守护进程

再重启服务:service mysql start

9.修改字符集

字符集乱码原因
如果在建库建表的时候,没有明确指定字符集,则采用默认的字符集 latin1,其中是不包含中文字符的。查看默认的编码字符集:
show variabels like ‘%char%’;

永久修改

(1)修改配置文件
在/usr/share/mysql/ 中找到 my.cnf 的配置文件,拷贝其中的 my-huge.cnf 到 /etc/ 并命名为 my.cnf 。添加以
下内容后再重启服务。
注意:必须将文件拷贝到指定路径,且名称为 my.cnf
[client]
default-character-set=utf8
[mysqld]
character_set_server=utf8
character_set_client=utf8
collation-server=utf8_general_ci
[mysql]
default-character-set=utf8
再次查看:
show variabels like ‘%char%’;
注意:已经创建的数据库的设定不会发生变化,参数修改只对新建的数据库有效!

(2)修改已创建库、表字符集
修改数据库的字符集
mysql> alter database mydb character set ‘utf8’;
修改数据表的字符集
mysql> alter table mytbl convert to character set ‘utf8’;

(3)修改已经乱码数据
无论是修改 mysql 配置文件或是修改库、表字符集,都无法改变已经变成乱码的数据。
只能删除数据重新插入或更新数据才可以完全解决

10.设置大小写不敏感

①查看大小写是否敏感:show variables like ‘%lower_case_table_names%’ windows
系统默认大小写不敏感,但是 linux 系统是大小写敏感的

②设置大小写不敏感:在 my.cnf 这个配置文件 [mysqld] 中加入 lower_case_table_names = 1 ,然后重启服务器

注意:如果要设置属性为大小写不敏感,要在重启数据库实例之前就需要将原来的数据库和表转换为小写,否则将找不到数据库名。
在进行数据库参数设置之前,需要掌握这个参数带来的影响,切不可盲目设置。

11.sql_mode

sql_mode 定义了对 Mysql 中 sql 语句语法的校验规则!
sql_mode 是个很容易被忽视的变量,默认值是空值,在这种设置下是可以允许一些非法操作的,比如允许一些 非法数据的插入。在生产环境必须将这个值设置为严格模式,所以开发、测试环境的数据库也必须要设置,这样在 开发测试阶段就可以发现问题。

sql_mode 常用的值
ONLY_FULL_GROUP_BY 对于 GROUP BY 聚合操作,如果在 SELECT 中的列,没有在 GROUP BY 中出现,那么这个 SQL 是不合法的,因为列不在 GROUP BY 从句中
NO_AUTO_VALUE_ON_ZERO 该值影响自增长列的插入。默认设置下,插入 0 或 NULL 代表生成下一个自增 长值。如果用户 希望插入的值为 0,而该列又是自增长的,那么这个选项就有用了
STRICT_TRANS_TABLES 在该模式下,如果一个值不能插入到一个事务表中,则中断当前的操作,对非事务表不做限制
NO_ZERO_IN_DATE 在严格模式下,不允许日期和月份为零
NO_ZERO_DATE 设置该值,mysql 数据库不允许插入零日期,插入零日期会抛出错误而不是警告
ERROR_FOR_DIVISION_BY_ZERO 在 INSERT 或 UPDATE 过程中,如果数据被零除,则产生错误而非警告。如果未给出该模式,那么数据被零除时 MySQL 返回 NULL
NO_AUTO_CREATE_USER 禁止 GRANT 创建密码为空的用户
NO_ENGINE_SUBSTITUTION 如果需要的存储引擎被禁用或未编译,那么抛出错误。不设置此值时,用默认的存储引擎替代,并抛出一个异常
PIPES_AS_CONCAT 将"||"视为字符串的连接操作符而非或运算符,这和 Oracle 数据库是一样的,也和字符串的拼接函数 Concat 相类似
ANSI_QUOTES 启用 ANSI_QUOTES 后,不能用双引号来引用字符串,因为它被解释为识别符
ORACLE 设置等同于PIPES_AS_CONCAT, ANSI_QUOTES, IGNORE_SPACE, NO_KEY_OPTIONS, NO_TABLE_OPTIONS, NO_FIELD_OPTIONS, NO_AUTO_CREATE_USER

2.6.2 查看和修改
①查看当前的 sql_mode:
select @@sql_mode;
②sql_mode 的影响案例:group by 查询语法错误!
CREATE TABLE mytbl2 (id INT,NAME VARCHAR(200),age INT,dept INT);
INSERT INTO mytbl2 VALUES(1,‘zhang3’,33,101);
INSERT INTO mytbl2 VALUES(2,‘li4’,34,101);
INSERT INTO mytbl2 VALUES(3,‘wang5’,34,102);
INSERT INTO mytbl2 VALUES(4,‘zhao6’,34,102);
INSERT INTO mytbl2 VALUES(5,‘tian7’,36,102);
查询每个 dept 中年龄最大的人:SELECT NAME,dept,MAX(age) FROM mytbl2 GROUP BY dept;
正 确 写 法 :
SELECT id,name,ab.dept,ab.maxage FROM mytbl2 m INNER JOIN(SELECT dept,MAX(age)maxage FROM mytbl2 GROUP BY dept)ab ON ab.dept=m.dept AND m.age=ab.maxage;
③临时修改 sql_mode: set @@sql_mode=’’;
④永久修改,需要在配置文件 my.cnf 中修改:
[mysqld] 下添加 sql_mode=’’ 然后重启 mysql 即可

十五、Mysql用户和管理权限

1.相关命令

create user zhang3
identified by ‘123123’;
创建名称为 zhang3 的用户,密码设为 123123;

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=‘li4’;
修改其他用户的密码
所有通过user 表的修改,必须用 flush privileges;命令才能生效

update mysql.user set user=‘li4’ where user=‘wang5’;
修改用户名
所有通过 user 表的修改,必须用 flush privileges;命令才能生效

drop user li4
删除用户
不要通过 delete from user u where user=‘li4’ 进行删除,系统会有残留信息保留。

2.实例说明

select host,user,password,select_priv,insert_priv,drop_priv
from mysql.user;

host :表示连接类型
% 表示所有远程通过 TCP 方式的连接
IP 地址 如 (192.168.1.2,127.0.0.1) 通过制定 ip 地址进行的 TCP 方式的连接机器名 通过制定 i 网络中的机器名进行的 TCP 方式的连接
::1 IPv6 的本地 ip 地址 等同于 IPv4 的 127.0.0.1
localhost 本地方式通过命令行方式的连接 ,比如 mysql -u xxx -p 123xxx 方式的连接。
user:表示用户名
同一用户通过不同方式链接的权限是不一样的。
password:密码
所有密码串通过 password(明文字符串) 生成的密文字符串。加密算法为 MYSQLSHA1 ,不可逆 。
mysql 5.7 的密码保存到 authentication_string 字段中不再使用 password 字段。
select_priv , insert_priv 等
为该用户所拥有的权限。

3.授予权限

grant 权限 1,权限 2,…权限 n
on 数据库名称. 表名称
to 用户名@用户地址
identified by ‘连接口令’
该权限如果发现没有该用户,则会直接新建一个用户。
示例:
grant select,insert,delete,drop
on atguigudb.*
to li4@localhost ;
给 li4 用户用本地命令行方式下,授予 atguigudb 这个库下的所有
表的插删改查的权限。

grant all privileges on .
to joe@’%’
identified by ‘123’;
授予通过网络方式登录的的 joe 用户 ,对所有库所有表的全部权限,密码设为 123.

4.收回权限

show grants 查看当前用户权限

revoke [权限 1,权限 2,…权限 n]
on 库名.表名
from 用户名@用户地址 ;
收回权限命令

REVOKE ALL PRIVILEGES
ON mysql.*
FROM joe@localhost;
收回全库全表的所有权限
REVOKE select,insert,update,delete
ON mysql.*
FROM joe@localhost;
收回 mysql 库下的所有表的插删改查权限

权限收回后,必须用户重新登录后,才能生效。

5.查看权限

show grants; 查看当前用户权限
select * from user ;

十六、逻辑框架简介

1.mysql整体框架

和其它数据库相比,MySQL 有点与众不同,它的架构可以在多种不同场景中应用并发挥良好作用。主要体现在存储引擎的架构上,插件式的存储引擎架构将查询处理和其它的系统任务以及数据的存储提取相分离。这种架构可以根据业务的需求和实际需要选择合适的存储引擎。
连接层、服务层、引擎层、存储层

1.1连接层

最上层是一些客户端和连接服务,包含本地 sock 通信和大多数基于客户端/服务端工具实现的类似于 tcp/ip 的通信。
主要完成一些类似于连接处理、授权认证、及相关的安全方案。
在该层上引入了线程池的概念,为通过认证安全接入的客户端提供线程。同样在该层上可以实现基于 SSL 的安全链接。服务器也会为安全接入的每个客户端验证它所具有的操作权限。

1.2 服务层

Management Serveices & Utilities 系统管理和控制工具
SQL Interface: SQL 接口。
接受用户的 SQL 命令,并且返回用户需要查询的结果。
比如 select from 就是调用 SQL Interface
Parser 解析器。
SQL 命令传递到解析器的时候会被解析器验证和解析
Optimizer 查询优化器。
SQL 语句在查询之前会使用查询优化器对查询进行优化,比如有 where 条件时,优化器来决定先投影还是先过滤。
Cache 和 Buffer 查询缓存。
如果查询缓存有命中的查询结果,查询语句就可以直接去查询缓存中取数据。这个缓存机制是由一系列小缓存组成的。比如表缓存,记录缓存,key 缓存,权限缓存等

1.3.引擎层

存储引擎层,存储引擎真正的负责了 MySQL 中数据的存储和提取,服务器通过 API 与存储引擎进行通信。不同的存储引擎具有的功能不同,这样我们可以根据自己的实际需要进行选取。

1.4.存储层

数据存储层,主要是将数据存储在运行于裸设备的文件系统之上,并完成与存储引擎的交互。

2.profile

show profile
查看sql执行周期

2.1 开启 profile

查看 profile 是否开启:show variables like ‘%profiling%’
如果没有开启,可以执行 set profiling=1 开启!

2.2 使用 profile

执行 show prifiles 命令,可以查看最近的几次查询。
根据 Query_ID,可以进一步执行 show profile cpu,block io for query Query_id 来查看 sql 的具体执行步骤。

3.大致的查询流程

mysql 客户端通过协议与 mysql 服务器建连接,发送查询语句,先检查查询缓存,如果命中,直接返回结果,
否则进行语句解析,也就是说,在解析查询之前,服务器会先访问查询缓存(query cache)——它存储 SELECT 语句以及相应的查询结果集。如果某个查询结果已经位于缓存中,服务器就不会再对查询进行解析、优化、以及执行。它仅仅将缓存中的结果返回给用户即可,这将大大提高系统的性能。

语法解析器和预处理:首先 mysql 通过关键字将 SQL 语句进行解析,并生成一颗对应的“解析树”。mysql 解析器将使用 mysql 语法规则验证和解析查询;预处理器则根据一些 mysql 规则进一步检查解析数是否合法。
查询优化器当解析树被认为是合法的了,并且由优化器将其转化成执行计划。一条查询可以有很多种执行方式,最后都返回相同的结果。优化器的作用就是找到这其中最好的执行计划。

然后,mysql 默认使用的 BTREE 索引,并且一个大致方向是:无论怎么折腾 sql,至少在目前来说,mysql 最多只用到表中的一个索引。

4.SQL 的执行顺序

手写的顺序:
在这里插入图片描述
真正执行的顺序:
随着 Mysql 版本的更新换代,其优化器也在不断的升级,优化器会分析不同执行顺序产生的性能消耗不同而动态调整执行顺序。

5.数据库引擎:myISAM和InnoDB

对比项 MyISAM InnoBD
外键 不支持 支持
事务 不支持 支持
行表锁 表锁,即使操作一条记录也会锁住整个表,不适合高并发的操作 行锁,操作时只锁某一行,不对其他行有影响,适合高并发的操作
缓存 只缓存索引,不缓存真实数据 不仅缓存索引还要缓存真实数据,对内存要求较高,而且内存大小对性能有决定性的影响
关注点 读性能 并发写、事务、资源
默认安装 y y
默认使用 n y
自带系统表使用 y n

show engines:查看所有的数据库引擎
show variables like ‘%storage_engine%’ 查看默认的数据库引擎

十七、SQL预热

1.常见的Join查询图

在这里插入图片描述

2.案例

十八、索引优化分析

1.什么是索引?

MySQL 官方对索引的定义为:索引(Index)是帮助 MySQL 高效获取数据的数据结构。可以得到索引的本质:
索引是数据结构。可以简单理解为排好序的快速查找数据结构。
在数据之外,数据库系统还维护着满足特定查找算法的数据结构,这些数据结构以某种方式引用(指向)数据,这样就可以在这些数据结构上实现高级查找算法。这种数据结构,就是索引。下图就是一种可能的索引方式示例:
在这里插入图片描述
左边是数据表,一共有两列七条记录,最左边的是数据记录的物理地址。为了加快 Col2 的查找,可以维护一个右边所示的二叉查找树,每个节点分别包含索引键值和一个指向对应数据记录物理地址的指针。
这样就可以运用二叉查找在一定的复杂度内获取到相应数据,从而快速的检索出符合条件的记录。
一般来说索引本身也很大,不可能全部存储在内存中,因此索引往往以索引文件的形式存储的磁盘上。

2.索引的优缺点

优势:
 提高数据检索的效率,降低数据库的IO成本。
 通过索引列对数据进行排序,降低数据排序的成本,降低了CPU的消耗。
劣势:
 虽然索引大大提高了查询速度,同时却会降低更新表的速度,如对表进行INSERT、UPDATE和DELETE。因为更新表时,MySQL不仅要保存数据,还要保存一下索引文件每次更新添加了索引列的字段,都会调整因为更新所带来的键值变化后的索引信息。
 实际上索引也是一张表,该表保存了主键与索引字段,并指向实体表的记录,所以索引列也是要占用空间的。

3.Btree索引

MySQL 使用的是 Btree 索引。
在这里插入图片描述
【初始化介绍】
一颗 b 树,浅蓝色的块我们称之为一个磁盘块,可以看到每个磁盘块包含几个数据项(深蓝色所示)和指针(黄色所示),如磁盘块 1 包含数据项 17 和 35,包含指针 P1、P2、P3,
P1 表示小于 17 的磁盘块,P2 表示在 17 和 35 之间的磁盘块,P3 表示大于 35 的磁盘块。
真实的数据存在于叶子节点即 3、5、9、10、13、15、28、29、36、60、75、79、90、99。
非叶子节点不存储真实的数据,只存储指引搜索方向的数据项,如 17、35 并不真实存在于数据表中。
【查找过程】
如果要查找数据项 29,那么首先会把磁盘块 1 由磁盘加载到内存,此时发生一次 IO,在内存中用二分查找确定 29
在 17 和 35 之间,锁定磁盘块 1 的 P2 指针,内存时间因为非常短(相比磁盘的 IO)可以忽略不计,通过磁盘块 1
的 P2 指针的磁盘地址把磁盘块 3 由磁盘加载到内存,发生第二次 IO,29 在 26 和 30 之间,锁定磁盘块 3 的 P2 指
针,通过指针加载磁盘块 8 到内存,发生第三次 IO,同时内存中做二分查找找到 29,结束查询,总计三次 IO。
真实的情况是,3 层的 b+树可以表示上百万的数据,如果上百万的数据查找只需要三次 IO,性能提高将是巨大的,
如果没有索引,每个数据项都要发生一次 IO,那么总共需要百万次的 IO,显然成本非常非常高。

4.B+tree索引

在这里插入图片描述
B+Tree 与 B-Tree 的区别
1)B-树的关键字和记录是放在一起的,叶子节点可以看作外部节点,不包含任何信息;
B+树的非叶子节点中只有关键字和指向下一个节点的索引,记录只放在叶子节点中。
2)在 B-树中,越靠近根节点的记录查找时间越快,只要找到关键字即可确定记录的存在;而 B+树中每个记录的查找时间基本是一样的,都需要从根节点走到叶子节点,而且在叶子节点中还要再比较关键字。

从这个角度看 B-树的性能好像要比 B+树好,而在实际应用中却是 B+树的性能要好些。因为 B+树的非叶子节点不存放实际的数据,这样每个节点可容纳的元素个数比 B-树多,树高比 B-树小,这样带来的好处是减少磁盘访问次数。尽管 B+树找到 一个记录所需的比较次数要比 B-树多,但是一次磁盘访问的时间相当于成百上千次内存比较的时间,因此实际中B+树的性能可能还会好些,而且 B+树的叶子节点使用指针连接在一起,方便顺序遍历(例如查看一个目录下的所有文件,一个表中的所有记录等),这也是很多数据库和文件系统使用 B+树的缘故。

思考:为什么说 B+树比 B-树更适合实际应用中操作系统的文件索引和数据库索引?

  1. B+树的磁盘读写代价更低
    B+树的内部结点并没有指向关键字具体信息的指针。因此其内部结点相对 B 树更小。如果把所有同一内部结点的关键字存放在同一盘块中,那么盘块所能容纳的关键字数量也越多。一次性读入内存中的需要查找的关键字也就越多。相对来说 IO 读写次数也就降低了。
  2. B+树的查询效率更加稳定
    由于非终结点并不是最终指向文件内容的结点,而只是叶子结点中关键字的索引。所以任何关键字的查找必须 走一条从根结点到叶子结点的路。所有关键字查询的路径长度相同,导致每一个数据的查询效率相当。

5.聚簇索引和非聚簇索引

聚簇索引并不是一种单独的索引类型,而是一种数据存储方式。
术语‘聚簇’表示数据行和相邻的键值聚簇的存储在一起。如下图,左侧的索引就是聚簇索引,因为数据行在磁盘的排列和索引排序保持一致。

聚簇索引的好处:

按照聚簇索引排列顺序,查询显示一定范围数据的时候,由于数据都是紧密相连,数据库不不用从多个数据块中提取数据,所以节省了大量的 io 操作。

聚簇索引的限制:

对于 mysql 数据库目前只有 innodb 数据引擎支持聚簇索引,而 Myisam 并不支持聚簇索引。
由于数据物理存储排序方式只能有一种,所以每个 Mysql 的表只能有一个聚簇索引。一般情况下就是该表的主键。

为了充分利用聚簇索引的聚簇的特性,所以 innodb 表的主键列尽量选用有序的顺序 id,而不建议用无序的 id,比如 uuid 这种。

6.时间复杂度(扩展)

同一问题可用不同算法解决,而一个算法的质量优劣将影响到算法乃至程序的效率。算法分析的
目的在于选择合适算法和改进算法。
时间复杂度是指执行算法所需要的计算工作量,用大 O 表示记为:O(…)

7.Mysql 索引分类

单值索引

概念:即一个索引只包含单个列,一个表可以有多个单列索引
语法:
所表一起创建:
CREATE TABLE customer (
id INT(10) UNSIGNED AUTO_INCREMENT ,
customer_no VARCHAR(200),
customer_name VARCHAR(200),
PRIMARY KEY(id),
KEY (customer_name)
);
单独建单值索引:
CREATE INDEX idx_customer_name ON customer(customer_name);

唯一索引

概念:索引列的值必须唯一,但允许有空值
随表一起创建:
CREATE TABLE customer (
id INT(10) UNSIGNED AUTO_INCREMENT ,
customer_no VARCHAR(200),
customer_name VARCHAR(200),
PRIMARY KEY(id),
KEY (customer_name),
UNIQUE (customer_no)
);
单独建唯一索引:
CREATE UNIQUE INDEX idx_customer_no ON customer(customer_no);

主键索引

概念:设定为主键后数据库会自动建立索引,innodb为聚簇索引
随表一起建索引
CREATE TABLE customer (
id INT(10) UNSIGNED AUTO_INCREMENT ,
customer_no VARCHAR(200),
customer_name VARCHAR(200),
PRIMARY KEY(id)
);
单独建主键索引:
ALTER TABLE customer add PRIMARY KEY customer(customer_no);
删除建主键索引:
ALTER TABLE customer drop PRIMARY KEY ;
修改建主键索引:
必须先删除掉(drop)原索引,再新建(add)索引

复合索引

概念:即一个索引包含多个列
随表一起建索引:
CREATE TABLE customer (
id INT(10) UNSIGNED AUTO_INCREMENT ,
customer_no VARCHAR(200),
customer_name VARCHAR(200),
PRIMARY KEY(id),
KEY (customer_name),
UNIQUE (customer_name),
KEY (customer_no,customer_name)
);
单独建索引:
CREATE INDEX idx_no_name ON customer(customer_no,customer_name);

8.索引的基本语法

创建 CREATE [UNIQUE ] INDEX [indexName] ON table_name(column))
删除 DROP INDEX [indexName] ON mytable;
查看 SHOW INDEX FROM table_name\G
使用 Alter 命令
ALTER TABLE tbl_name ADD PRIMARY KEY (column_list) : 该语句添加一个主键,这意味着索引值必须是唯一的,且不能为 NULL。
ALTER TABLE tbl_name ADD PRIMARY KEY (column_list)
ALTER TABLE tbl_name ADD INDEX index_name (column_list): 添加普通索引,索引值可出现多次。
ALTER TABLE tbl_name ADD FULLTEXT index_name (column_list):该语句指定了索引为 FULLTEXT ,用于全文索引。

9.索引的创建时机

适合创建索引的情况
 主键自动建立唯一索引;
 频繁作为查询条件的字段应该创建索引
 查询中与其它表关联的字段,外键关系建立索引
 单键/组合索引的选择问题, 组合索引性价比更高
 查询中排序的字段,排序字段若通过索引去访问将大大提高排序速度
 查询中统计或者分组字段

不适合创建索引的情况
 表记录太少
 经常增删改的表或者字段Where 条件里用不到的字段不创建索引
 过滤性不好的不适合建索引

十九、ExPlain性能分析

1.ExPlain关键字

使用 EXPLAIN 关键字可以模拟优化器执行 SQL 查询语句,从而知道 MySQL 是如何处理你的 SQL 语句的。分析你的查询语句或是表结构的性能瓶颈。
用法: Explain+SQL 语句。
Explain 执行后返回的信息:

2. Explain 准备工作

CREATE TABLE t1(id INT(10) AUTO_INCREMENT,content VARCHAR(100) NULL , PRIMARY KEY (id));
CREATE TABLE t2(id INT(10) AUTO_INCREMENT,content VARCHAR(100) NULL , PRIMARY KEY (id));
CREATE TABLE t3(id INT(10) AUTO_INCREMENT,content VARCHAR(100) NULL , PRIMARY KEY (id));
CREATE TABLE t4(id INT(10) AUTO_INCREMENT,content VARCHAR(100) NULL , PRIMARY KEY (id));
INSERT INTO t1(content) VALUES(CONCAT(‘t1_’,FLOOR(1+RAND()*1000)));
INSERT INTO t2(content) VALUES(CONCAT(‘t2_’,FLOOR(1+RAND()*1000)));
INSERT INTO t3(content) VALUES(CONCAT(‘t3_’,FLOOR(1+RAND()*1000)));
INSERT INTO t4(content) VALUES(CONCAT(‘t4_’,FLOOR(1+RAND()*1000)));

2.id

select 查询的序列号,包含一组数字,表示查询中执行 select 子句或操作表的顺序。
①id 相同,执行顺序由上至下

②id 不同,如果是子查询,id 的序号会递增,id 值越大优先级越高,越先被执行

③有相同也有不同

id 如果相同,可以认为是一组,从上往下顺序执行;
在所有组中,id 值越大,优先级越高,越先执行衍生 = DERIVED

关注点:id 号每个号码,表示一趟独立的查询。一个 sql 的查询趟数越少越好。

3.select_type

select_type 代表查询的类型,主要是用于区别普通查询、联合查询、子查询等的复杂查询。

select_type 属性
(1)SIMPLE 简单的 select 查询,查询中不包含子查询或者 UNION
SIMPLE 代表单表查询
(2)PRIMARY 查询中若包含任何复杂的子部分,最外层查询则被标记为 Primary
(3)DERIVED 在 FROM 列表中包含的子查询被标记为 DERIVED(衍生) MySQL 会递归执行这些子查询, 把结果放在临时表里。
(4)SUBQUERY 在SELECT或WHERE列表中包含了子查询
(5)DEPEDENT SUBQUERY 在SELECT或WHERE列表中包含了子查询,子查询基于外层
都是 where 后面的条件,subquery 是单个值,dependent subquery 是一组值
(6)UNCACHEABLE SUBQUERY 无法使用缓存的子查询
当使用了@@来引用系统变量的时候,不会使用缓存。
(7)UNION 若第二个SELECT出现在UNION之后,则被标记为UNION; 若UNION包含在FROM子句的子查询中,外层SELECT将被标记为:DERIVED
(8)UNION RESULT 从UNION表获取结果的SELECT

4.table

这个数据是基于哪张表的。

5.type

type 是查询的访问类型。是较为重要的一个指标,结果值从最好到最坏依次是:
system > const > eq_ref > ref > fulltext > ref_or_null > index_merge > unique_subquery > index_subquery > range > index > ALL
一般来说,得保证查询至少达到 range 级别,最好能达到 ref。
system :表只有一行记录(等于系统表),这是 const 类型的特列,平时不会出现,这个也可以忽略不计
const :表示通过索引一次就找到了,const 用于比较 primary key 或者 unique 索引。因为只匹配一行数据,所以很快
如将主键置于 where 列表中,MySQL 就能将该查询转换为一个常量。
eq_ref :唯一性索引扫描,对于每个索引键,表中只有一条记录与之匹配。常见于主键或唯一索引扫描。
ref :非唯一性索引扫描,返回匹配某个单独值的所有行.本质上也是一种索引访问,它返回所有匹配某个单独值的行,然而,它可能会找到多个符合条件的行,所以他应该属于查找和扫描的混合体。
没用索引前:
建立索引后:
range :只检索给定范围的行,使用一个索引来选择行。key 列显示使用了哪个索引一般就是在你的 where 语句中出现了 between、<、>、in 等的查询这种范围扫描索引扫描比全表扫描要好,因为它只需要开始于索引的某一点,而结束语另一点,不用扫描全部索引。
ind

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值