MySQL高级
2018-11-07 14:42:24 1 举报
AI智能生成
MySQL高级
作者其他创作
大纲/内容
mysql的架构介绍
Mysql简介
概述
Mysql高手是怎样炼成的
数据库内部结构和原理
数据库建模优化
数据库索引建立
SQL语句优化
SQL编程
mysql服务器的安装配置
数据库的性能监控分析与系统优化
各种参数常量设定
主从复制
分布式架构搭建、垂直切割和水平切割
数据迁移
容灾备份和恢复
shell或python等脚本语言开发
对开源数据库进行二次开发
MysqlLinux版的安装
mysql5.5
下载地址
拷贝&解压缩
检查工作
检查当前系统是否安装过mysql
检查/tmp文件夹权限
安装
查看MySQL安装版本
mysql服务的启+停
首次登录
MySQL的安装位置
在linux下查看安装目录 ps -ef|grep mysql
自启动mysql服务
修改字符集问题
Mysql配置文件
主要文件
二进制日志log-bin
主从复制及备份恢复(了解)
错误日志log-error
默认是关闭的,记录严重的警告和错误信息,每次启动和关闭的详细信息等。
慢查询日志log
默认关闭,记录查询的sql语句,如果开启会减低mysql的整体性能,因为记录日志也是需要消耗系统资源的
数据文件
两系统
windows
....\MySQLServer5.5\data目录下很多数据库文件
linux
默认路径:/var/lib/mysql
每个目录代表一个同名的库
Myisam存放方式
frm文件(framework)
存放表结构
myd文件(data)
存放表数据
myi文件(index)
存放表索引
innodb存放方式
ibdata1
frm文件
存放表结构
单独存放
如何配置
windows
my.ini文件(配置文件)
Linux
/etc/my.cnf文件(配置文件)
Mysql 的用户与权限管理
MySQL的用户管理
创建用户
了解user表
设置密码
修改用户
删除用户
权限管理
授予权限
收回权限
查看权限
通过工具远程访问
Mysql的一些杂项配置
大小写问题
(生产环境)sql_mode
Mysql逻辑架构介绍
总体概览
查询说明
Mysql存储引擎
查看命令
各个引擎简介
MyISAM和InnoDB
阿里巴巴、淘宝用哪个
索引优化分析
性能下降SQL慢
执行时间长
等待时间长
查询数据过多
关联了太多的表,太多join
没有利用到索引
单值
复合
服务器调优及各个参数设置(缓冲、线程数等)(不重要DBA的工作)
常见通用的Join查询
SQL执行顺序
手写
机读
总结
Join图
共有与独有(理解)
建表SQL
7种JOIN
增加掌门字段
join 的理解例题
索引简介
是什么
MySQL官方对索引的定义为:索引(Index)是帮助MySQL高效获取数据的数据结构。
可以得到索引的本质:索引是数据结构。
你可以简单理解为“排好序的快速查找数据结构”。
详解(重要)
结论
一般来说索引本身也很大,不可能全部存储在内存中,因此索引往往以索引文件的形式存储的磁盘上
我们平常所说的索引,如果没有特别指明,都是指B树(多路搜索树,并不一定是二叉的)结构组织的索引。其中聚集索引,次要索引,覆盖索引,
复合索引,前缀索引,唯一索引默认都是使用B+树索引,统称索引。当然,除了B+树这种类型的索引之外,还有哈稀索引(hash index)等。
优势
类似大学图书馆建书目索引,提高数据检索的效率,降低数据库的IO成本
通过索引列对数据进行排序,降低数据排序的成本,降低了CPU的消耗
劣势
实际上索引也是一张表,该表保存了主键与索引字段,并指向实体表的记录,所以索引列也是要占用空间的
虽然索引大大提高了查询速度,同时却会降低更新表的速度,如对表进行INSERT、UPDATE和DELETE。
因为更新表时,MySQL不仅要保存数据,还要保存一下索引文件每次更新添加了索引列的字段,
都会调整因为更新所带来的键值变化后的索引信息
索引只是提高效率的一个因素,如果你的MySQL有大数据量的表,就需要花时间研究建立最优秀的索引,或优化查询语句
mysql索引结构
BTree索引
原理图
Myisam普通索引
关于时间复杂度
B+Tree索引
原理图
innodb的普通索引
B树和B+树的区别
聚簇索引与非聚簇索引
full-text全文索引
Hash索引
R-Tree索引
mysql索引分类
主键索引
设定为主键后数据库会自动建立索引,innodb为聚簇索引
语法
单值索引
即一个索引只包含单个列,一个表可以有多个单列索引
语法
唯一索引
索引列的值必须唯一,但允许有空值
语法
复合索引
即一个索引包含多个列
语法
基本语法
创建
ALTER mytable ADD [UNIQUE ] INDEX [indexName] ON (columnname(length))
删除
DROP INDEX [indexName] ON mytable;
查看
SHOW INDEX FROM table_name\G
使用ALTER命令
哪些情况需要创建索引
主键自动建立唯一索引
频繁作为查询条件的字段应该创建索引(where 后面的语句)
查询中与其它表关联的字段,外键关系建立索引
单键/组合索引的选择问题,who?(在高并发下倾向创建组合索引)
查询中排序的字段,排序字段若通过索引去访问将大大提高排序速度
查询中统计或者分组字段
哪些情况不要创建索引
表记录太少
经常增删改的表
Why:提高了查询速度,同时却会降低更新表的速度,如对表进行INSERT、UPDATE和DELETE。
因为更新表时,MySQL不仅要保存数据,还要保存一下索引文件
Where条件里用不到的字段不创建索引
数据重复且分布平均的表字段,因此应该只为最经常查询和最经常排序的数据列建立索引。
注意,如果某个数据列包含许多重复的内容,为它建立索引就没有太大的实际效果。
性能分析
MySQL常见瓶颈
CPU
SQL中对大量数据进行比较、关联、排序、分组
IO:
实例内存满足不了缓存数据或排序等需要,导致产生大量 物理 IO。
查询执行效率低,扫描过多数据行。
锁
不适宜的锁的设置,导致线程阻塞,性能下降。
死锁,线程之间交叉调用资源,导致死锁,程序卡住。
服务器硬件的性能瓶颈:top,free, iostat和vmstat来查看系统的性能状态
Explain
是什么(查看执行计划)
使用EXPLAIN关键字可以模拟优化器执行SQL查询语句,从而知道MySQL是
如何处理你的SQL语句的。分析你的查询语句或是表结构的性能瓶颈
官网介绍
能干嘛
表的读取顺序
哪些索引可以使用
数据读取操作的操作类型
哪些索引被实际使用
表之间的引用
每张表有多少行被优化器查询
怎么玩
Explain + SQL语句
执行计划包含的信息
分支主题
建表脚本
各字段解释
id
select查询的序列号,包含一组数字,表示查询中执行select子句或操作表的顺序
三种情况
id相同,执行顺序由上至下
id不同,如果是子查询,id的序号会递增,id值越大优先级越高,越先被执行
id相同不同,同时存在
select_type
有哪些
查询的类型,主要是用于区别
普通查询、联合查询、子查询等的复杂查询
SIMPLE
简单的 select 查询,查询中不包含子查询或者UNION
PRIMARY
查询中若包含任何复杂的子部分,最外层查询则被标记为Primary
DERIVED
在FROM列表中包含的子查询被标记为DERIVED(衍生)
MySQL会递归执行这些子查询, 把结果放在临时表里。
SUBQUERY
在SELECT或WHERE列表中包含了子查询
DEPENDENT SUBQUERY
在SELECT或WHERE列表中包含了子查询,子查询基于外层
UNCACHEABLE SUBQUREY
无法被缓存的子查询
UNION
若第二个SELECT出现在UNION之后,则被标记为UNION;
若UNION包含在FROM子句的子查询中,外层SELECT将被标记为:DERIVED
UNION RESULT
从UNION表获取结果的SELECT
table
显示这一行的数据是关于哪张表的
type
分支主题
访问类型排列
显示查询使用了何种类型,
从最好到最差依次是:
system>const>eq_ref>ref>range>index>ALL
system
表只有一行记录(等于系统表),这是const类型的特列,平时不会出现,这个也可以忽略不计
const
表示通过索引一次就找到了,const用于比较primary key或者unique索引。因为只匹配一行数据,所以很快
如将主键置于where列表中,MySQL就能将该查询转换为一个常量
eq_ref
唯一性索引扫描,对于每个索引键,表中只有一条记录与之匹配。常见于主键或唯一索引扫描
ref
非唯一性索引扫描,返回匹配某个单独值的所有行.
本质上也是一种索引访问,它返回所有匹配某个单独值的行,然而,
它可能会找到多个符合条件的行,所以他应该属于查找和扫描的混合体
range
只检索给定范围的行,使用一个索引来选择行。key 列显示使用了哪个索引
一般就是在你的where语句中出现了between、<、>、in等的查询
这种范围扫描索引扫描比全表扫描要好,因为它只需要开始于索引的某一点,而结束语另一点,不用扫描全部索引。
index
Full Index Scan,index与ALL区别为index类型只遍历索引树。这通常比ALL快,因为索引文件通常比数据文件小。
(也就是说虽然all和Index都是读全表,但index是从索引中读取的,而all是从硬盘中读的)
all
Full Table Scan,将遍历全表以找到匹配的行
index_merge
在查询过程中需要多个索引组合使用,通常出现在有 or 的关键字的sql中
ref_or_null
对于某个字段既需要关联条件,也需要null值得情况下。查询优化器会选择用ref_or_null连接查询。
index_subquery
利用索引来关联子查询,不再全表扫描。
unique_subquery
该联接类型类似于index_subquery。 子查询中的唯一索引
备注:一般来说,得保证查询至少达到range级别,最好能达到ref。
possible_keys
显示可能应用在这张表中的索引,一个或多个。
查询涉及到的字段上若存在索引,则该索引将被列出,但不一定被查询实际使用
key
实际使用的索引。如果为NULL,则没有使用索引
查询中若使用了覆盖索引,则该索引和查询的select字段重叠
key_len
表示索引中使用的字节数,可通过该列计算查询中使用的索引的长度。
key_len字段能够帮你检查是否充分的利用上了索引
ref
显示索引的哪一列被使用了,如果可能的话,是一个常数。哪些列或常量被用于查找索引列上的值
rows
rows列显示MySQL认为它执行查询时必须检查的行数。
越少越好
Extra
包含不适合在其他列中显示但十分重要的额外信息
Using filesort
说明mysql会对数据使用一个外部的索引排序,而不是按照表内的索引顺序进行读取。
MySQL中无法利用索引完成的排序操作称为“文件排序”
Using temporary
使了用临时表保存中间结果,MySQL在对查询结果排序时使用临时表。常见于排序 order by 和分组查询 group by。
USING index
表示相应的select操作中使用了覆盖索引(Covering Index),避免访问了表的数据行,效率不错!
如果同时出现using where,表明索引被用来执行索引键值的查找;
如果没有同时出现using where,表明索引只是用来读取数据而非利用索引执行查找。
覆盖索引(Covering Index)
Using where
表明使用了where过滤
using join buffer
使用了连接缓存:
impossible where
where子句的值总是false,不能用来获取任何元组
select tables optimized away
在没有GROUPBY子句的情况下,基于索引优化MIN/MAX操作或者
对于MyISAM存储引擎优化COUNT(*)操作,不必等到执行阶段再进行计算,
查询执行计划生成的阶段即完成优化。
查询优化
使用索引
建表SQL
案例(索引失效)
全值匹配我最爱
最佳左前缀法则
如果索引了多列,要遵守最左前缀法则。指的是查询从索引的最左前列开始并且不跳过索引中的列。
不在索引列上做任何操作(计算、函数、(自动or手动)类型转换),会导致索引失效而转向全表扫描
存储引擎不能使用索引中范围条件右边的列
尽量使用覆盖索引(只访问索引的查询(索引列和查询列一致)),减少select *
mysql 在使用不等于(!= 或者<>)的时候无法使用索引会导致全表扫描
is not null 也无法使用索引,但是is null是可以使用索引的
like以通配符开头('%abc...')mysql索引失效会变成全表扫描的操作
问题:解决like '%字符串%'时索引不被使用的方法??
字符串不加单引号索引失效
少用or,用它来连接时会索引失效
小总结
热身case
题目SQL
一般性建议
对于单键索引,尽量选择针对当前query过滤性更好的索引
在选择组合索引的时候,当前Query中过滤性最好的字段在索引字段顺序中,位置越靠前越好。(避免索引过滤性好的索引失效)
在选择组合索引的时候,尽量选择可以能够包含当前query中的where字句中更多字段的索引
尽可能通过分析统计信息和调整query的写法来达到选择合适索引的目的
单表查询优化
建表SQL
案例
关联查询优化
建表SQL
案例
建议
1、保证被驱动表的join字段已经被索引
2、left join 时,选择小表作为驱动表,大表作为被驱动表。
3、inner join 时,mysql会自己帮你把小结果集的表选为驱动表。
4、子查询尽量不要放在被驱动表,有可能使用不到索引。
子查询优化
用in 还是 exists
实验
结论
order by关键字优化
ORDER BY子句,尽量使用Index方式排序,避免使用FileSort方式排序
建表SQL
Case
1
2
MySQL支持二种方式的排序,FileSort和Index,Index效率高.
它指MySQL扫描索引本身完成排序。FileSort方式效率较低。
ORDER BY满足两情况,会使用Index方式排序:
ORDER BY 语句使用索引最左前列
使用Where子句与Order BY子句条件列组合满足索引最左前列
where子句中如果出现索引的范围查询(即explain中出现range)会导致order by 索引失效。
尽可能在索引列上完成排序操作,遵照索引建的最佳左前缀
小总结
如果不在索引列上,filesort有两种算法:
mysql就要启动双路排序和单路排序
双路排序
MySQL 4.1之前是使用双路排序,字面意思就是两次扫描磁盘,最终得到数据,
读取行指针和orderby列,对他们进行排序,然后扫描已经排序好的列表,按照列表中的值重新从列表中读取对应的数据输出
从磁盘取排序字段,在buffer进行排序,再从磁盘取其他字段。
取一批数据,要对磁盘进行了两次扫描,众所周知,I\O是很耗时的,所以在mysql4.1之后,出现了第二种改进的算法,就是单路排序。
单路排序
从磁盘读取查询需要的所有列,按照order by列在buffer对它们进行排序,然后扫描排序后的列表进行输出,
它的效率更快一些,避免了第二次读取数据。并且把随机IO变成了顺序IO,但是它会使用更多的空间,
因为它把每一行都保存在内存中了。
结论及引申出的问题
由于单路是后出的,总体而言好过双路
但是用单路有问题
优化策略
增大sort_buffer_size参数的设置
增大max_length_for_sort_data参数的设置
去掉select 后面不需要的字段
Why
分页查询的优化---limit
GROUP BY关键字优化
group by实质是先排序后进行分组,遵照索引建的最佳左前缀
当无法使用索引列,增大max_length_for_sort_data参数的设置+增大sort_buffer_size参数的设置
where高于having,能写在where限定的条件就不要去having限定了。
去重优化
尽量不要使用 distinct 关键字去重:优化
查询截取分析
慢查询日志
是什么
怎么玩
说明
查看是否开启及如何开启
默认
SHOW VARIABLES LIKE '%slow_query_log%';
开启
set global slow_query_log=1;
那么开启了慢查询日志后,什么样的SQL才会记录到慢查询日志里面呢?
Case
查看当前多少秒算慢
SHOW VARIABLES LIKE 'long_query_time%';
设置慢的阙值时间
为什么设置后看不出变化?
需要重新连接或新开一个会话才能看到修改值。 SHOW VARIABLES LIKE 'long_query_time%';
或者通过set session long_query_time=1来改变当前session变量;
记录慢SQL并后续分析
查询当前系统中有多少条慢查询记录
配置版
日志分析工具mysqldumpslow
查看mysqldumpslow的帮助信息
s: 是表示按照何种方式排序;
c: 访问次数
l: 锁定时间
r: 返回记录
t: 查询行数
al:平均锁定时间
ar:平均返回记录数
at:平均查询时间
t:即为返回前面多少条的数据;
g:后边搭配一个正则匹配模式,大小写不敏感的;
工作常用参考
批量数据脚本
往表里插入1000W数据
建表
设置参数log_bin_trust_function_creators
创建函数,保证每条数据都不同
随机产生字符串
随机产生部门编号
创建存储过程
创建往emp表中插入数据的存储过程
创建往dept表中插入数据的存储过程
调用存储过程
dept
emp
大量数据案例
Show Profile
是什么:是mysql提供可以用来分析当前会话中语句执行的资源消耗情况。可以用于SQL的调优的测量
官网:http://dev.mysql.com/doc/refman/5.5/en/show-profile.html
默认情况下,参数处于关闭状态,并保存最近15次的运行结果
分析步骤
是否支持,看看当前的mysql版本是否支持
开启功能,默认是关闭,使用前需要开启
运行SQL
select * from emp group by id%10 limit 150000;
select * from emp group by id%20 order by 5
查看结果,show profiles;
诊断SQL,show profile cpu,block io for query n (n为上一步前面的问题SQL数字号码);
参数备注
日常开发需要注意的结论
converting HEAP to MyISAM 查询结果太大,内存都不够用了往磁盘上搬了。
Creating tmp table 创建临时表
拷贝数据到临时表
用完再删除
Copying to tmp table on disk 把内存中临时表复制到磁盘,危险!!!
locked
全局查询日志
配置启用
编码启用
尽量不要在生产环境开启这个功能。
MySql锁机制
概述
定义
生活购物
锁的分类
从对数据操作的类型(读\写)分
读锁(共享锁):针对同一份数据,多个读操作可以同时进行而不会互相影响。
写锁(排它锁):当前写操作没有完成前,它会阻断其他写锁和读锁。
从对数据操作的粒度分
表锁
行锁
三锁
表锁(偏读)
特点
偏向MyISAM存储引擎,开销小,加锁快;无死锁;锁定粒度大,发生锁冲突的概率最高,并发度最低。
案例分析
建表SQL
加读锁
加写锁
结论
行锁(偏写)
特点
偏向InnoDB存储引擎,开销大,加锁慢;会出现死锁;锁定粒度最小,发生锁冲突的概率最低,并发度也最高。
InnoDB与MyISAM的最大不同有两点:一是支持事务(TRANSACTION);二是采用了行级锁
由于行锁支持事务,复习老知识
事务(Transaction)及其ACID属性
并发事务处理带来的问题
更新丢失(Lost Update)
脏读(Dirty Reads)
不可重复读(Non-Repeatable Reads)
幻读(Phantom Reads)
事务隔离级别
案例分析
建表SQL
行锁定基本演示
无索引行锁升级为表锁
Select也可以加锁
读锁
select ..lock in share mode
写锁
select... for update
间隙锁危害
案列结论
行锁分析
优化建议
尽可能让所有数据检索都通过索引来完成,避免无索引行锁升级为表锁。
尽可能较少检索条件,避免间隙锁
尽量控制事务大小,减少锁定资源量和时间长度
锁住某行后,尽量不要去调别的行或表,赶紧处理被锁住的行然后释放掉锁。
涉及相同表的事务,对于调用表的顺序尽量保持一致。
在业务环境允许的情况下,尽可能低级别事务隔离
页锁
开销和加锁时间界于表锁和行锁之间;会出现死锁;锁定粒度界于表锁和行锁之间,并发度一般。
了解一下即可
主从复制
复制的基本原理
slave会从master读取binlog来进行数据同步
三步骤+原理图
master将改变记录到二进制日志(binary log)。这些记录过程叫做二进制日志事件,binary log events
slave将master的binary log events拷贝到它的中继日志(relay log)
slave重做中继日志中的事件,将改变应用到自己的数据库中。 MySQL复制是异步的且串行化的
复制的基本原则
每个slave只有一个master
每个slave只能有一个唯一的服务器ID
每个master可以有多个salve
复制的最大问题
延时
一主一从常见配置
mysql版本一致且后台以服务运行
主从都配置在[mysqld]结点下,都是小写
主机修改my.ini配置文件
[必须]主服务器唯一ID
server-id=1
[必须]启用二进制日志
log-bin=自己本地的路径/data/mysqlbin
log-bin=D:/devSoft/MySQLServer5.5/data/mysqlbin
[可选]启用错误日志
log-err=自己本地的路径/data/mysqlerr
log-err=D:/devSoft/MySQLServer5.5/data/mysqlerr
[可选]根目录
basedir="自己本地路径"
basedir="D:/devSoft/MySQLServer5.5/"
[可选]临时目录
tmpdir="自己本地路径"
tmpdir="D:/devSoft/MySQLServer5.5/"
[可选]数据目录
datadir="自己本地路径/Data/"
datadir="D:/devSoft/MySQLServer5.5/Data/"
read-only=0
主机,读写都可以
[可选]设置不要复制的数据库
binlog-ignore-db=mysql
[可选]设置需要复制的数据库
binlog-do-db=需要复制的主数据库名字
从机修改my.cnf配置文件
[必须]从服务器唯一ID
[可选]启用二进制日志
因修改过配置文件,请主机+从机都重启后台mysql服务
主机从机都关闭防火墙
windows手动关闭
关闭虚拟机linux防火墙 service iptables stop
在Windows主机上建立帐户并授权slave
GRANT REPLICATION SLAVE ON *.* TO 'zhangsan'@'从机器数据库IP' IDENTIFIED BY '123456';
分支主题
flush privileges;
查询master的状态
show master status;
记录下File和Position的值
执行完此步骤后不要再操作主服务器MYSQL,防止主服务器状态值变化
在Linux从机上配置需要复制的主机
CHANGE MASTER TO MASTER_HOST='主机IP',MASTER_USER='zhangsan',MASTER_PASSWORD='123456',MASTER_LOG_FILE='File名字',MASTER_LOG_POS=Position数字;
启动从服务器复制功能
start slave;
show slave status\G
下面两个参数都是Yes,则说明主从配置成功!
Slave_IO_Running: Yes
Slave_SQL_Running: Yes
主机新建库、新建表、insert记录,从机复制
如何停止从服务复制功能
stop slave;
0 条评论
下一页