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