mysql note级别_note-mysql-senior

MySQL高级

索引Index

==排好序的快速查找数据结构==

查看表的索引

SHOW INDEX FROM `user`;

创建索引

方式一:

CREATE INDEX idx_user_age ON `user`(age);

idx_user_age : 索引名(idx_表名_索引字段名)

````user`(age):表名(索引字段名)```

方式二:

ALTER TABLE `user` ADD INDEX idx_user_gender(gender);

````user`(age):表名(索引字段名)```

idx_user_gender(gender) : 索引名(索引字段名)

删除索引

方式一:

ALTER TABLE `user` DROP INDEX idx_user_gender;

方式二:

DROP INDEX idx_user_age ON `user`;

哪些情况需要创建索引

主键自动建立唯一索引

频繁作为查询条件的字段应该创建索引

查询中与它表关联的字段,外键关系建立索引

查询中排序的字段,排序字段若通过索引去访问将大大提高排序速度

查询中统计|分组字段

单键|组合索引的选择问题,在高并发下倾向创建组合索引

哪些情况不要创建索引

频繁更新的字段不适合创建索引,因为每次更新不单单是更新了记录还会更新索引

Where条件里用不到的字段不适合创建索引

表记录太少不适合创建索引

经常增删改的表,提高了查询速度,同时却会降低更新表的速度,如对表进行INSERT,UPDATE和DELETE。因为更新表时,MySQL不仅要保存数据,还要保存一下索引文件

数据重复且分布平均的表字段,因此应该只为最经常查询和最经常排序的数据列建立索引。注意:如果某个数据列包含许多重复的内容,为它建立索引就没用太大的实际效果。

c12034e46a9ec9057162c7ee12da381c.png

性能分析

MySQL Query optimizer

679d81708c16f7e233d19c81e9995080.png

MySQL创建瓶颈

CPU:CPU在饱和的时候一般发送在数据装入内存或磁盘上读取时候

IO:磁盘I/O瓶颈发生在装入数据远大于内存容量的时候

服务器硬件的性能瓶颈:top,free,iostat和vmstat来查看系统的性能状态

Explain

是什么

查看执行计划

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

能干嘛

explain中的各字段的作用

表的读取顺序(id)

数据读取操作的操作类型(select_type)

哪些索引可以使用(prossible_keys)

哪些索引被实际使用(key)

表之间的引用(ref)

每张表有多少行被优化器查询(rows)

怎么用

Explain+SQL语句

EXPLAIN SELECT * FROM `user`;

执行计划包含的信息

39120e9925d6f63d38d625aec97d4e37.png

各字段解释

id

select查询的序列号,包含一组数字,标配是查询中执行select子句或操作表的顺序

三种情况

id相同,执行顺序由上至下

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

id相同不同,同时存在

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

select_type

常用值:

05363164c7bdf1d4b340eb30b863d86b.png

查询的类型,主要是用于区别

SIMPLE :简单的select查询,查询中不包含子查询或者UNION

PRIMARY :查询中若包含任何复杂的子部分,最外层查询则标记为

SUBQUERY :在SELECT或者WHERE列表中包含了子查询

DERIVED :在FROM列表中包含的子查询被标记为DERIVED(衍生),MySQL会递归执行这些子查询,把结果放在临时表里

UNION :若第二个SELECT出现在UNION之后,则被标记为UNION;

​ 若UNION包含在FROM子句的子查询中,外层SELECT将被标记为:DERIVED

UNION RESULT :从UNION表获取结果的SELECT

table

显示这一行的数据是关于哪张表的

partitions

该列显示的为分区表命中的分区情况。非分区表该字段为空(null)

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用于比较peimary key或者unique索引。因为只匹配一行数据,所以很快。如将主键置于where列表中,MySQL就能将该查询转换为一个常量

eq_ref : 唯一性索引扫描,对于每个索引键,表中只有一条记录与之匹配。常见于主键或唯一索引扫描

ref :非唯一性索引扫描,返回匹配某个单独值的所有行。本质上也是一种索引访问,它返回所有匹配某个单独值的行,然而,它可能会找到多个符合条件的行,所以他应该属于查找和扫描的混合体

range :只检索给定范围的行,使用一个索引来选择行。key列显示使用了哪个索引,一般就是在你的where语句中出现了between、、 in等的查询,这种范围扫描索引扫描比全表扫描要好,因为它只需要开始于索引的某一点,而结束于另一点,不用扫描全部索引。

index : FullIndexScan,index与ALL区别为index类型只遍历索引树。这通常比ALL快,因为索引文件通常比数据文件小。(也就是说虽然ALL和index都是读全表,但index是从索引中读取的,而ALL是从硬盘中读取的)

ALL :FullTableScan,将遍历全表以找到匹配的行

possible_keys

显示可能应用在这张表中的索引,一个或多个。

查询涉及到的字段上若存在索引,则该索引将被列出,但不一定被查询实际使用

key

实际使用的索引。如果为null,则没有使用索引。查询中若使用了覆盖索引,则该索引仅出现在key列表中

key_len

表示索引中使用的字节数,可通过该列计算查询中使用的索引的长度。在不损失精确性的情况下,长度越短越好。key_len显示的值为索引字段的最大可能长度,并非实际使用长度,即key_len是根据表定义计算而得,不是通过表内检索出的

ref

显示索引的哪一列被使用了,如果可能的话,是一个常数。哪些列或常量被用于查找索引列上的值。

rows

根据表统计信息及索引选用情况,大致估算出找到所需的记录所需要读取的行数

filtered

表示存储引擎返回的数据在server层过滤后,剩下多少满足查询的记录数量的比例,注意是百分比,不是具体记录数。

Extra

包含不适合在其他列中显示但十分重要的额外信息

Using filesort :说明MySQL会对数据使用一个外部的索引排序,而不是按照表内的索引进行读取。MySQL中无法利用索引完成的排序操作成为‘’文件排序‘’。

Using temporary :使用了临时表保存中间结果,MySQL在对查询结果排序时使用临时表。常见于排序order by和分组查询group by。

Using index :表示相应的select操作中使用了覆盖索引(Covering Index),避免访问了表的数据行,效率不错!

如果同时出现Using where,表明索引被用来执行索引键值的查询;

如果没有同时出现Using where,表明索引用来读取数据而非执行查询动作。

覆盖索引(Covering Index):select的数据列只用从索引中就能够读取,不必读取数据行,MySQL可以利用索引返回select列表中的字段,而不必根据索引再次读取数据文件,换句话说==查询列要被索引覆盖==。注意:如果使用覆盖索引,一定要注意select列表中只取出需要的列,不可select *,因为如果将所有字段一起做所有会导致索引文件过大,查询性能下降。

Using where :表明使用了where过滤

Using join buffer :使用了连接缓存,可根据情况适当提高配置文件中的buffer缓冲区大小。

impossible where :where子句的值总是false(不满足条件),不能用来获取任何元组。

select tables optimized away :在没有group by子句的情况下,基于索引优化MIN/MAX操作或者对于 MyISAM存储引擎优化count(*)操作,不必等到执行阶段再进行计算,查询执行计划生成的阶段即完成优化。

distinct :优化distinct操作,在找到第一匹配的元组后即停止找同样值的动作

索引优化

索引失效

应该避免

全值匹配

建立了复合索引(a,b,c)

根据最佳左前缀法则,查询不带a将不能使用索引

查询

a,b,c(覆盖索引,最好)

a,b(部分使用索引,a和b皆使用到了索引)

a(部分使用索引,a使用到了索引)

b,c(违背最佳左前缀法则,索引最左列不能丢,索引失效)

a,c(违背最佳左前缀法则,不能跳过索引的列,a使用索引,c索引失效)

==最佳左前缀法则==

如果索引了多列,要遵守最左前缀法则。指的是查询从索引的最左前列开始并且不跳过索引中的列

不在索引列上做任何操作(计算、函数、(自动|手动)类型转换),会导致索引失效而转向全表扫描

存储引擎不能使用索引中范围条件右边的列

尽量使用覆盖索引(只访问索引的查询(索引列和查询列一致)),减少select *

MySQL在使用不等于(!=|<>)的时候无法使用索引会导致全表扫描

is null,is not null也无法使用索引

like以通配符开头(如%abc),MySQL索引失效会编程全表扫描的操作

**解决like %字符串%**时索引不被使用的方法

使用==覆盖索引==

字符串不加单引号索引失效

少用or,用它来连接时会索引失效

建议

对于单键索引,尽量选择针对当前query过滤性更好的索引

在选择组合索引的时候,当前query中过滤性最好的字段在索引字段顺序中,位置越靠前越好

在选择组合索引的时候,尽量选择可以能够包含当前query中where字句中更多字段的索引

尽可能通过分析统计信息和调整query的写法来达到选择合适索引的目的

677a5ef366a5ff1daf5c0a22cd4bce8c.png

查询截取

查询优化

==永远小表驱动大表==:即小的数据集驱动大的数据集

0dff0367ccce50274f6f2997fa898978.png

-- EXISTS:将著擦好像的数据,放到子查询中做条件验证,根据验证结果(TRUE|FALSE)来决定主查询的数据结果是否得以保留

SELECT * FROM 表 WHERE EXISTS (子查询)

order by关键字优化

order by子句,尽量使用Index方式排序,避免使用FileSort方式排序

order by满足两种情况,会使用Index方式排序

order by语句使用索引最左前列

使用where子句与order by子句条件列组合满足索引最左前列

尽可能在索引列上完成排序操作,遵照索引建的最佳左前缀

如果不在索引列上,FileSort有两种算法:

mysql就要启动双路排序和单路排序

双路排序:

mysql4.1之前是使用双路排序,字面意思就是两次扫描磁盘,最终得到数据,读取行指针和order by列,对他们进行排序,然后扫描已经排序好的列表,按照列表中的值重新从列表中读取对应的数据输出。

从磁盘取排序字段,在buffer进行排序,再从磁盘取其他字段。

取一批数据,要对磁盘进行了两次扫描,众所周知,I/O是很耗时的,所以在mysql4.1之后,出现了第二种改进的算法,单路排序。

==单路排序:==

从磁盘读取查询需要的所有列,按照order by列再buffer对它们进行排序,然后扫描排序后的列表进行输出,它的效率更快一些,避免了第二次读取数据。并且把随机I/O变成了顺序I/O,但是它会使用更多的空间,因为它把每一行都保存在内存中了。

由于单路是后出的,总体而言好过双路,但是==用单路有问题==

d860d66f1524d2537c929462f471e56e.png

优化策略

增大sort_buffer_size参数的设置

增大max_length_for_sort_data参数的设置

7e63f3680de17a0868a447ff47961245.png

总结

5f887174d1f615fc0d4555b27c79b2c6.png

group by关键字优化

group by实质是先排序后进行分组,遵照索引建的最佳左前缀

当无法使用索引列时,增大max_length_for_sort_data参数的设置 + 增大sort_buffer_size参数的设置

where高于having,能写在where限定的条件就不要取having限定了

慢查询日志

是什么

Mysql的慢查询日志是Mysql提供的一种日志记录,它用来记录在Mysql中响应时间超过阙值的语句,具体指运行时间超过long_query_time值的SQL,则会被记录到慢查询日志中。

具体指运行时间超过long_query_time值的SQL,则会被记录到慢查询日志中。long_query_time的默认值为10,意思就是运行10秒以上的语句。

由它来查看哪些SQL超过了我们的最大忍耐时间值,比如一条SQL执行超过5秒钟,我们就算慢SQL,希望能收集超过5秒的SQL,结合之前的explain进行全面分析。

怎么用

默认情况下,MySQL数据库没有开启慢查询日子,需要我们手动来设置这个参数。

当然,如果不是调优需要,一般不建议启动该参数,因为开启慢查询日志会或多或少带来一定的性能影响。慢查询日志支持将日志记录写入文件。

查看是否开启及如何开启

默认:SHOW VARIABLES LIKE '%slow_query_log%';

开启:set global slow_query_log = 1; ==此处的1为true(ON),0为false(OFF);==

使用set global slow_query_log = 1;开启慢查询日志只对当前数据库生效,如果Mysql重启后则会失效。

afac072e5534876687ea381ae7066056.png

什么样的SQL为慢SQL?

这个是由参数long_query_time控制的,默认情况下long_query_time的值为10秒,10是大于,并非大于等于,因此等于10秒的SQL不会被记录下来

通过SHOW VARIABLES LIKE 'long_query_time%'查看;

设置慢的阙值时间:set global long_query_time = 3;,设置完成后需要重写开启一个mysql会话才能通过SHOW GLOBAL VARIABLES LIKE 'long_query_time%'查看更改

查看当前系统中有多少条慢查询记录:SHOW GLOBAL STATUS LIKE '%Slow_queries%'

使用配置文件

6a4eca952dfdc82b2e43fd04668b3623.png

==日志分析工具mysqldumpslow==

在生产环境中,如果要手工分析日志,查找、分析SQL,显然是个体力活,Mysql提供了日志分析工具mysqldumpslow

mysqldumpslow --help

s:是表示按照何种方式排序

c:访问次数

l:锁定时间

r:返回时间

t:查询时间

al:平均锁定时间

ar:平均返回记录数

at:平均查询时间

t:即为返回前面多少条的数据

g:后边搭配一个正则匹配模式,大小写不敏感的

工作常用参考

fc7a966a14fb9a90150914637767b470.png

Show Profile

是什么

是mysql提供可以用来分析当前会话中语句执行的资源消耗情况。可以用于SQL的调优的测量

分析步骤

是否支持,看看当前的mysql版本是否支持

Show variables like 'profiling;'默认是关闭的,使用前需要开启

或者:Show variables like 'profiling%;'

开启功能,默认是关闭,使用前需要开启

set profiling = on;

运行SQL

默认情况下,参数处于关闭状态,并保存最近15次运行结果

查看结果,show profiles

诊断SQL,show profile cpu,block io for query 查询id(查询id通过show profiles获取)

Type:

all--显示所有的开销信息

block io --显示块IO相关开销

context switches --上下文切换相关开销

cpu --显示cpu相关开销信息

ipc --显示发送和接收相关开销信息

memory --显示内存相关开销信息

page faults --显示页面错误相关开销信息

source --显示和Source_function,Source_file,Source_line相关的开销相信

swaps --显示交换次数相关开销信息

日常开发需要注意的结论

show profile cpu,block io for query 查询id查看Status出现以下一种需要优化

converting HEAP to MyISAM:查询结果太大,内存都不够用了往磁盘上搬了

Creating tmp table:创建临时表(拷贝数据到临时表,用完再删除)

Copying to tmp table on disk:把内存中临时表复制到磁盘,==危==

locked:锁表

全局查询日志

仅允许再测试环境中使用,==永远不要再生产环境开启这个功能==

编码启用

set global general_log = 1;

set global log_output = 'TABLE';

此后,你所编写的sql语句,都将会记录到mysql库里面的general_log表,

可以用select * from mysql.general_log查看

MySQL锁机制

锁的分类

对数据的操作类型分:

读锁(共享锁)

针对同一份数据,多个读操作可以同时进行而不会相互影响。

写锁(排他锁)

当前写操作没有完成前,它会阻断其他写锁和读锁。

对数据的操作粒度分:表锁,行锁

三锁

开销,加锁速度,死锁,粒度,并发性能

只能就具体应用的特点来说哪种锁更合适

表锁(偏读)

偏向于MyISAM存储引擎,开销小,加锁快;无死锁;锁定粒度大,发送锁冲突的概率最高,并发度最低。

手动增加表锁

lock table 表名字 read(|write),表名字2 read(|write),其他;

查看表上加过的锁

show open tables;

释放表锁

unlock tables;

总结

加了读锁的的session,不能执行对该表的写操作,不能读其他表,不能写其他表,仅允许读被锁的表

其他session,可以读被加读锁的表,不允许写该表(会被阻塞),其他表可读可写

加了写锁的session,仅能对自己锁定的表进行读写

其他session不允许读(阻塞)写(阻塞)加了写锁的session,其他表可读可写

3bc4391ecbbbb1143351643e3c838118.png

表锁分析

6dd5ba88de2010f244423e9189524964.png

行锁(偏写)

偏向InnoDB存储引擎,开销大,加锁慢;会出现死锁;锁定粒度最小,发送锁冲突的概率最低,并发度也最高。

==InnoDB和MyISAM最大的不同有两点==

一:支持事务(Transaction)

二:采用行级锁

事务(Transaction)及其ACID属性:

8f53636432b24c868f0bea838afc2e2b.png

并发事务处理带来的问题

更新丢失(Lost Update)

a7a43c98a3a64cee53ed82ebaa57b521.png

脏读(Dirty Reads)

0f0090804095c222dde9e54c1c3b057e.png

不可重复读(Non-Repeatable Reads)

f1873cc55d8411d825295dcb8a1cf392.png

幻读(Phantom Reads)

0f5090142a187ea8caf4f630efea2c95.png

事务的隔离级别

7c41d16ac8977c12d35c06e4afa5ed9b.png

==行锁变表锁==

==当 Where 查询条件中的字段没有索引时,更新操作会锁住全表!索引失效也会导致行锁变表锁。==

间隙锁

当我们用范围条件而不是相等条件检索数据,并请求共享或排他锁时,InnoDB会给符合条件的已有数据记录的索引项加锁;对于键值在条件范围内但并不存在的记录,叫做“间隙(GAP)”,InnoDB也会对这个“间隙”加锁,这种锁机制就是所谓的间隙锁(Next-Key锁)。

危害:因为Query执行过程中通过范围查找的话,他会锁定整个范围内所有的索引键值,即使这个键值并不存在。

间隙锁有一个比较致命的弱点,就是当锁定一个范围键值之后,即使某些不存在的键值也会被无辜的锁定,而造成在锁定的时候无法插入锁定键值范围内的任何数据。在某些场景下这可能会对性能造成很大的危害。

如何锁定一行

5c31096e0b33fd53b3839661c3fe348c.png

总结

c6e9d706a4c5bb8b4442e53797bf582a.png

行锁分析

8e53d5bf05923943ccf408515aad4fda.png

优化建议

尽可能让所有数据检索都通过索引来完成,避免无索引行锁升级为表锁。

合理设计索引,尽量缩小锁的范围

尽可能较少检索条件,避免间隙锁

尽量控制事务大小,减少锁定资源量和时间长度

尽可能低级别事务隔离

页锁

开销和加锁时间界于表锁和行锁之间;会出现死锁;锁定粒度界于表锁和行锁之间,并发度一般。

MySQL主从复制

复制的基本原理

slave会从master读取binlog来进行数据同步

Mysql复制过程分为三步:

master将改变记录到二进制日志(binary log)。这些记录过程叫做二进制日志事件,binary log events;

slave将master的binary log events拷贝到它的中继日志(relay log);

slave重做中继日志中的事件,将改变应用到自己的数据库中。MySQL复制是异步的且串行化的

b171509618544577ffd7a259f608eb26.png

复制的基本原则

每一个slave只有一个master

每个slave只能由一个唯一的服务器ID

每个master可以由多个salve

复制的最大问题

延时

一主(windows)一从(linux)常见配置

mysql版本一致且后台以服务运行

主从斗鱼配置在==[mysqld]==节点下,都是小写

主机修改my.ini(windows)配置文件

[必须]主服务器唯一IDserver-id=1

[必须]启用二进制日志log-bin=自己本地的路径/mysqlbin

[可选]启用错误日志log-err=自己本地的路径/mysqlerr

[可选]根目录basedir="自己本地路径"

[可选]临时目录tmpdir="自己本地路径"

[可选]数据目录datadir="自己本地路径/Data"

read-only=0主机,读写都可以

[可选]设置不要复制的数据库binlog-ignore-db=不要复制的数据库名字

[可选]设置需要复制的数据库binlog-do-db=需要复制的主数据库名字

aa662a54153593afd68f65f2fdea6462.png

从机修改my.cnf(linux)配置文件

[必须]从服务器唯一ID

[可选]启用二进制日志

因修改过配置文件,主机和从机都要重启后台mysql服务

主机从机关闭防火墙(相互ip ping得通)

在windows主机上建立账户并授权slave

c3562c2fe5d9a571427984e3a0db2493.png

在linux从机上配置需要复制的主机

ffe75fd6f352e7b5c75129f35554234e.png

主机新建库,表,insert记录,从机复制

如何停止从服务复制功能

stop slave;

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值