sql语句:select distinct … from … where … group by …having… order by… limit…
执行顺序:from…on…where…order by…having…select distinct…order by…limit…
SQL性能问题:
a.分析SQL执行计划(explain + SQL语句),可以模拟SQL优化器执行SQL语句,从而知道编写的SQL状况
b.MySQL查询优化会干扰我们的优化
select识别符,是select查询序列号,序号为sql执行顺序;
id值越大先执行
id相同:从上往下顺序执行,数据个数越少越先执行(原因:笛卡尔积),数据量小的表优先执行
simple:简单的select,没有union和子查询
subquery:包含子查询SQL的子查询(非最外层)
primary:最外面的select,在有子查询的语句中,最外面的select查询就是primary
derived:衍生查询(在查询时候用到了临时表)
在from 子查询中,只有一张表;
在from 子查询中,如果有table1 union table2,则table1就是derived
union:union语句的第二个或者说是后面那一个
dependent union: union中的第二个或后面的select语句,取决于外面的查询
union result:union的结果,哪些表存在union
输出的行所用表
system:表仅有一行,是const的特例
const: 表最多有一个匹配行,const用于比较primary或者unique索引;必须用到primary key或者unique索引
eq_ref: 用在一个索引的所有部分被联接使用并且索引是primary key或者unique索引;可以用于使用=比较带索引的列
ref: 如果联接只使用键的最左边的前缀,或者键不是primary key或者unique索引,则使用ref
ref_or_null: 与ref相比,添加了MYSQL能专门搜索包含null值的行,经常使用在子查询中
index_merge: 使用索引合并优化方法
unique_subquery:
index_subquery:
range: 给定范围内的检索,where后面事范围(between或者in、>、<),使用一个索引来检查行;in有时会失效,转为无索引
index: 查询全部索引中的数据,与ALL基本相同,除了只有索引树被扫描
ALL: 查询全部表中的数据,对每个行组合,都进行完整行扫描
type小结:system/const:结果只有一条数据
ef-ref:结果多条;但每条数据是唯一的
ref:结果多条;但是每条数据是0或者多条
可能用到的索引,是一种索引,不准
如果是null,则说明没有索引
实际使用到的索引
索引的长度,用于判断复合索引是否被完全使用
在utf-8中:1哥字符占3个字节(所有索引长度会乘以3)
如果索引字段可以为null,则会使用1个字节用于标识
指明当前表所参照的字段,表之间的引用
(1)const:常量
(2)用到的字段
被索引优化查询的数据个数(实际通过索引查询到的数据个数)
数值越小越好
using filesort:性能消耗大;需要额外的一次排序,经常出现在order by中
对于单索引,如果排序和查找收同一个字段,不会出现using filesort;
如果不是同一个字段,则会出现using filesort
Where那些字段,就order by那些字段
复合索引:不能跨列(最佳左前缀)
避免where和order by按照复合索引的顺序使用 不要跨列或无序使用
using temporary:性能损耗大,用到了临时表,已经有表了,但不适用,必须再来一张表,一般出现在group by中
避免:查询哪些列就跟
using index:性能提升;索引覆盖,不读取原文件,只从索引中查询数据
只要使用到的列都在索引中,则称为索引覆盖
如果用到了索引覆盖Using index时,会对possible_keys和keys产生影响
如果没有where,则索引只出现在key中;
如果有where,则索引出现在key和possible_keys中
using where:需要回表查询
impossible where:where子句永远为false
左连接:
索引往哪里加:(1)小表驱动大表;(2)索引建立在经常使用的字段上
(3)左外连接给左表加索引,右外连接给右表加索引
where 小表.x = 大表.y;
编写 …on t.cid=c.cid时,将数据量小的表放左边
Using join buffer: extra中的一个选项,作用:mysql引擎使用了连接缓存
1.复合索引:
(1)不要跨列或无序使用(最佳左前缀)
(a,b,c)
(2)尽量使用全索引匹配
2.不要再索引上进行任何操作(计算、函数、类型转换),否则做索引失效
3.复合索引不能使用不等于(!= <>)或者 is not null,否则自身以及右侧索引全部失效;
复合索引中如果有 > ,则自身和右侧索引全部失效
Sql优化,是一种概率层面的优化,至于是否实
际使用我们的优化,要用explain进行推测(服务器中有sql优化器优化影响我们的优化)
4.补救:尽量使用索引覆盖(using index)
5.like尽量以常量开头,不要以%开头
如果一定要使用%x%,则使用索引覆盖 using index
6.尽量不要使用显示或者隐式转换,否则索引失效
7.尽量不要使用or,否则索引失效
select …from table where exist (子查询)
select tname from teacher where exist (select * from teacher);
select…from table where 字段 in (子查询)
如果主查询的数据集大,则使用In
如果子查询的数据集大,则使用exist;
exist语法:将主查询的结果,放到子查询结果中进行条件校验,如果检验成功(看子查询是否有数据),则保留数据
using filesort 有两种算法:双路排序、单路排序(根据IO的次数)
MYSQL4.1之前,默认使用 双路排序(扫描2 次磁盘IO)
MYSQL4.1之后,默认使用 单路排序
选择使用单路、双路;调整buffer的容量大小
避免select*…
复合索引 不要跨列使用,避免使用using filesort
保证全部的排序字段 排序的一致性(都是升序或者降序)
1.MYSQL提供的一种日志记录,用于记录mysql中响应时间超过阈值的sql语句(long_querytime默认10s)
2.慢查询日志默认是关闭的,可以开发调优时打开,最后部署时关闭
3.检查是否开启了慢查询日志:
show variables like ‘%slow_query_log%’
4.开启慢查询日志:
(1)临时开启:
Set global slow_query_log=1;在内存中开启
Exit
Service mysql restart
(2)永久开启:
/etc/my.conf中(mysqld中)追加配置:
[mysqld]
slow_query_log=1
slow_query_log_file=/var/lib/mysql/localhost-slow.log
5.慢查询阀值:
show variables like ‘%long_query_time%’
临时设置阀值:
Set global long_query_time=5;需要重新登陆后生效
永久设置阀值:
在/etc/my.conf中(mysqld中)追加配置:
[mysqld]
long_query_time =5
6.查看超过阀值的SQL(看到慢查询的条数):
show global status like ‘%slow_queries%’ ;
7.慢查询的sql被记录在了日志中:
(1)可以通过日志查看具体慢sql(即存放的位置:/var/lib/mysql/localhost-slow.log)
cat /var/lib/mysql/localhost-slow.log;
(2)通过mysqldumpslow工具查看慢sql
默认关闭
show variables like ‘%profiling%’;
set profiling = on;
show profiles: 会记录所有profling打开之后的全部SQL查询语句
缺点:不够精确,只能看到总共消费的时间,不能看到各个硬件消费的时间
sql诊断
Show profile all for query +需要查询的Query_Id
记录开启之后的全部sql语句(在开发调优时开启,部署后关闭)
show variables like ‘%general_log%’;
(1)执行的所有记录sql记录在表中:
set global general_log=1; 开启全局日志
set global log_output=’table’; 设置将全部的sql记录在表中
(2)执行的所有sql记录在文件中:
set global general_log=on;
set global log_output=’file’;
set global general_log_file = ‘/tmp/general.log’;
可以通过 select * from mysql.general_log; 查看日志
a.读锁(共享锁):
对同一数据,多个操作可以同时进行,互不干扰
b.写锁(互斥锁):
如果当前写操作没有完毕,则无法进行其他的读操作和写操作
a.表锁:
一次性对一张表整体加锁,如MyISAM储存引擎,开销小,加锁块,无死锁;但锁范围大,容易发送锁冲突,并发度低
b.行锁:
一次性对一条数据加锁,如InnoDB存储引擎;开销大,加锁慢,容易出现死锁,锁范围小,不易发生锁冲突,并发度高(小概率发生高并发问题)
c.页锁:
加锁语法:lock table 表1 read/write,表2 read/write… ;
查看加锁的表:show open tables;
释放锁:unlock tables;
a) 在会话0中加读锁:
lock table tablelock read;
select * from tablelock; 查可以
delete from tablelock where id=1; 增删改不行
select * from teacher2; 查其他表,不可以
delete from tablelock where id=1;其他表增删改不可以
如果一个会话对A表加了read锁,则该会话可以对A进行读操作不能进行写操作;而且当前会话不能对其他表进行读和写操作
总结:如果给A表加了read锁,则当前会话只能对A进行读操作
b) 在会话1中:
select * from tablelock; 查可以
delete from tablelock where id=1; 增删改不行,会等待会话0释放锁
select * from teacher2; 查其他表,可以
delete from tablelock where id=1;其他表增删改也可以
总结:会话0给A表加了读锁;其他会话可以对A表以外的其他表进行读写操作;
对A表可以读,写需要等待释放锁
会话0:
lock table tablelock write;
当前会话可以对加了写锁的表进行任何操作,不能操作其他表
会话1:
对会话0中加写锁的表可以进行增删改查的前提是会话0释放锁;
MyISAM在执行查询语句select前,会自动给涉及的所有表加读锁;
在执行增删改(DML)时,会自动给涉及的表加写锁;
因此在对MyISAM表进行读操作时,不会阻塞其他进程对同一表的读请求,会阻塞对同一表的写请求,只有当读锁释放后才能进行写操作;
在对MyISAM表的写操作时,会阻塞其他进程对同一表的读和写操作,只有当写锁释放后,才能执行其他进程的读写操作
查看哪些表加了锁:show open tables; 1代表被加了锁
分析表锁定的严重程度:show status like ‘table%’;有下面两个参数
Table_locks_immediate:即可能获取到的锁数
Table_locks_waited: 需要等待的表锁数(值越大,存在更大的锁竞争)
一般建议:
Table_locks_immediate/ Table_locks_waited >5000,建议采用InnoDB,否则使用MyISAM引擎
Mysql默认自动commit;oracle默认不会自动commit
研究行锁,将自动commit关闭:
set autocommit = 0;
start transaction;
begin;三种方式均可
以后需要通过commit
会话0:写操作
insert into linelock values(‘a6’);
会话1:写操作 同样的数据
Update linelock set name=’ax’ where id=6;
对行锁情况(关闭自动commit):
a.如果会话x对某条数据a进行DML操作,则其他会话必须等待会话x结束事务(commit或者roolback)后,才能对数据进行操作;
b.表锁是通过unlock tables,也可以通过事务解锁;行锁是通过事务解锁(commit或者roolback)
行锁如果操作不同数据,不同会话则互不干扰
a.如果没有索引,则行锁会转为表锁;
b.行锁的一种特殊情况:间隙锁;值在范围内,但却不存在
mysql间隙会自动给间隙加锁-间隙锁
行锁:如果有where,则实际加锁的范围就是where后面的范围
InnoDB默认采用行锁;高并发使用InnoDB,否则使用MyISAM
缺点:比表锁性能损耗大;
优点:并发能力强,效率高
行锁分析:
Show status like ‘%innodb_row_lock%’;
参数值:
Innodb_row_lock_current_waits:当前正在等待锁的数量
Innodb_row_lock_time:等待总时长,从系统启动到现在一共等待的时间
Innodb_row_lock_time_avg:平均等待时长
Innodb_row_lock_time_max:最大等待时长
Innodb_row_lock_waits:等待次数
仅仅查询数据,可以使用for update加锁
select * from linelock where id =2 for update;
(1)负载均衡
(2)失败迁移
(mysql图形化客户端:SQLyog,Navicat)
如果要远程连接数据库,则需要授权远程访问
授权远程访问:(A->B,则在B计算机的Mysql中执行以下命令)
GRANT ALL PRIVILEGES ON . TO ‘root’ @’%’ IDENTIFIED BY ‘root’ WITH GRANT OPTION;
FLUSH PRIVILEGES;
如果仍然报错,可能是防火墙没关闭,在B关闭防火墙 service iptables stop;
(1) master将改变的数记录在本地的二进制日志中(binary log);该过程称之为二进制日志事件
(2) slave将master的binary log拷贝到自己的relay log(中继日志文件)
(3) 中继日志事件,将数据读取到自己的数据库中
Mysql主从复制是异步的,串行化的,有延迟
Master:slaver=1:n
连接层、服务层、引擎层、存储层
InnoDB(默认):事务优先(适合高并发操作;行锁)
MyISAM:性能优先(表锁)
查看当前使用引擎:show variables like ‘%storage_engine%’;
指定数据库对象的引擎:
ENGINE=MyISAM
索引是帮助mysql高效获取数据的数据结构(树:B树、二叉树、Hash树)
Mysql索引使用的是B树
索引本身很大,可以存放内存/硬盘(通常为硬盘)
索引不是所有情况都适用:
少量数据
频繁更新的字段
很少使用的列
提高查询效率(降低IO使用率)
降低CPU使用率(B树索引本身已经排好序,可以直接使用)
一般指B+树,数据放在叶子节点中
B+树中查询任意的数据次数等于B+树的高度
(1)分类:
主键索引:不能重复,不能是null
单值索引:单列,一个表可以有多个单值索引
唯一索引:不能重复,可以为null
复合索引:多个列构成的索引(相当于书的二级目录)
(2)创建索引:
第一种:create 索引类型 索引名 on 表(字段)
单值索引:create index dept_index on table(name);
唯一索引:create unique index dept_index on table(name);
复合索引:create index dept_name_index on tb(dept,name);
第二种:
alter table 表名 add 索引类型 索引名(索引字段)
如果一个字段事primary key,则该字段默认是 主键索引
(3)删除索引:
Drop index 索引名 on 表名;
(4)查询索引:show index from 表名;