最近在学MySQL,这篇是第一篇,希望自己能够好好记笔记,方便以后的复习。
MYSQL逻辑分层
当我们执行一条命令时,比如
select * from student
数据库中的操作顺序如下:
连接层 -> 服务层 ->引擎层 ->存储层
- 连接层:只负责查询语句和数据库的连接
- 服务层:提供用户使用接口,例如select、delete...同时还可以对sql语句进行优化
- 引擎层:数据的存储方式(常用的有InnoDB(事务优先)、MyISAM(性能优先))
- 存储层:最终执行后的数据在存储层
查看当前使用了那些引擎
指定数据库对象的引擎:
当有时候想要性能优先的时候,可以改掉默认的引擎
//修改默认的存储引擎,可以在创建的时候指定
create table tb( id int(4) auto_increment, name varchar(5), dept varchar(5),primary key(id))ENGINE=MyISAM DEFAULT ChARSET=utf8;
SQL优化
为什么要优化:等待时间太长,执行时间太长,索引失效,服务器参数不合理(缓存区参数)
SQL:
编写过程:
select ... from ... join .... on where group by ... having ... order by limit
解析过程:
可能跟编写的过程不一样
from...on...join ... where ...group by... having...select ...
b.SQL优化
主要是优化索引,索引相当于书的目录,是高效查询数据的数据结构(树:B(默认)/Hash树...)
我们可以看到,右边是一个加了索引的树(当然这里是一个平衡二叉树,真实的环境是B树),加了索引树之后查询年龄只需要3次,不加就要5次,在千万级别的数据库中,这样可以节省大量的搜索时间。
- 弊端:
1 索引本身很大,可以存放在内存/硬盘
2 少量数据,不需要索引
3 频繁更新,每一次都要
4 很少使用的字段,不需要加
5 虽然可以增加检索效率,但是降低了增删改的效率 - 优势:
1 提高查询效率(降低IO使用率)
2 降低CPU使用率:比如DESC,索引本身就排好序,不需要再排序了
BTree原理
数据都在叶节点里面,非叶子节点的数据只是为了分割数据
索引
-分类
1 单值索引:单列的值,一个表可以有多个单值索引
2 唯一索引:不能重复,一般用id,值不能重复
3 复合索引:多个列构成,相当于二级目录(筛选两次,没有必要全部列都用)
创建索引
方式一
create 索引类型 索引名 on 表(字段)
//根据部门创建一个单值索引
create index dept_index on tb(dept);
//给name加上唯一索引,假设name是唯一的
create unique index name_index on tb(name);
//复合索引
create index dept_name_index on tb(dept, name);
方式二
alter table 表名 索引类型 索引名 (字段)
//根据部门创建一个单值索引
alter table tb add index dept_index(dept);
//给name加上唯一索引,假设name是唯一的
alter table tb add unique index name_index(dept);
//复合索引
alter table tb add index dept_name_index(dept,name);
DDL:create alter drop都是事务性语句,自动提交 不需要commit;
注意
- 主键索引不能为null,唯一索引可以是null
- primary就是默认的主键索引
删除索引
drop index name_index on tb;
查询索引
show index from table
SQL性能分析
- sql执行计划:(explain 可以模拟sql优化器执行sql语句,让开发人员知道自己的sql执行状况)
- 查询优化可能会干扰我们的优化
- 查询执行计划
id(编号) | select_type(查询类型) | table(表) | partitions | type(类型) | possible_keys(预测索引) | key | key_len | ref | rows | filtered | Extra
create table course
(
cid int(3),
cname varchar(20),
tid int(3)
);
create table teacher
(
tid int(3),
tname varchar(20),
tcid int(3)
);
create table tearcherCard
(
tcid int(3),
tcdesc varchar(200)
);
//查询课程编号为2或教师证编号为 3的老师信息
explain select t.* from teacher t, course c, tearcherCard tc where t.tid=c.tid and tc.tcid=t.tcid and (c.cid=2 or tc.tcid=3);
数据的顺序:t3-tc3-c4
数据的顺序:tc3-t6-c4
-为什么会有表的差异(笛卡尔积)
中间结果数据会变:数据小的表优先查询
id值不同的时候,越大越优先:查询sql课程的老师的描述
explain select tc.tcdesc from teacher t, course c, tearcherCard tc where t.tid=c.tid and tc.tcid=t.tcid and c.cname='sql';
//多表连接写成子查询形式(在嵌套子查询时先查最内存在查最外层)
explain select tc.tcdesc from tearcherCard tc where tc.tcid=(
select t.tcid from teacher t where t.tid=(select c.tid from course c where c.cname='sql')
);
- id(编号) :有相同和不同,越大越优先,id值相同从上往下顺序执行(explain语句中)
- select_type(查询类型):包含子查询sql中的子查询,PRIMARY、SUBQUERY、SIMPLE(最简单的,没有子查询,union),derived(衍生查询):from中只有一张表,在from子查询中(之前查询过来的)
- type(类型):索引类型system>const>eq_ref>ref>range>index>all
常用
ref
ref:不需要唯一性索引,数量是0或多
range
range:检索一定范围内的数据,where里面的范围(between in(有时失效) > <=)
index:查询数据,查询全部索引里面的数据全部索引
all:查询所有数据全部数据
- possible_keys(预测索引):预测用的索引
- key:实际的索引
- key_len:索引的长度,判断复合索引是否完全被使用
create table text(
name char(20) not null default ''
);
alter table text add column name1 char(20);
--加入复合索引,现根据name查,查不到,再根据另外一个name1查
alter table text add index index_name_name1(name,name1);
-
ref:指明当前表参照的字段
引用,一定要加上索引 rows:被索引优化查询的数据个数
Extra:
1 using filesort--当前sql语句需要额外的一次排序
复合索引,不能跨列,最佳左前缀
create table A(
a1 int,
a2 int,
a3 int,
index idx_a1_a2_a3(a1,a2,a3),
);
查找的时候只能是select a1 order by a2...
不能是a2...a3或者a1...a3之类的,因为都跨列的,这样会出现using filesort情况
2 using temporary性能损耗比较大,用到了临时表,常见于group by语句中
根据a1查找,但是根据a2分组。避免:查询那些列就根据那个group by,本来游标了,但是还需要另外一张表查找
3 using index
会对possiblekey和key有影响,如果没有where,索引只出现在key中,否则possiblekey和key里面都有。
出现了using index表示性能提升了,索引覆盖。
原因:不读取源文件,只从索引文件中获取数据
4 using where
需要回表查询
索引里面没有的,需要回到原表查询
select age ,name from .. where age=...
此语句必须要回到表格查询name,所以用where
5 possible where
永远不可能的
... where a1='x' and a2='y'