数据库进阶MYSQL分层及其优化

tech2024-10-10  20

1.mysql分层

连接层:提供与客户端连接的服务服务层:1.提供各种用户使用接口,2提供sql优化器(写的语句和执行可能不一致)引擎层:提供了各种存储数据的方式 InnoDB :事物优先,(适合高并发操作 使用行锁)MyISAM:性能优先(表锁) 存储层:存储数据 查询数据库支持哪些引擎:show engines;

2.SQL优化简述

2.1原因:性能低、执行时间长,等待时间长,sql语句欠佳(连接查询),索引失效、服务器参数设置不合理(缓冲、线程数) 2.2sql优化:主要就是优化索引

索引相当于书的目录index是帮助mysql高效获取数据的数据结构。索引是数据结构(树:b树、二叉树。。)索引的弊端: 索引本身很大,可以放到内存/硬盘中索引不是所有的情况都适用:a.少量数据 b.频繁的更新的字段 c.很少使用的字段索引会降低增删改的效率(因为更改以后还需要去更改索引) 优势 提高查询效率(降低了io的使用率)降低cpu的使用率(因为已经做好了排序等)

3.索引

3.1分类

单值索引:单列,一个表可以有多个单值索引 唯一索引:不能重复 id(和主键索引的区别 主键不能为null) 复合索引:多个列构成的索引(相当于 一级目录二级目录。。。)

3.2创建索引

方式一:

create 索引类型 索引名 on 表名(字段) 例: 单值:create index name_index on user(name); 唯一索引:create unique index id_index on user(id) 复合索引:create index name_id_index on user(name,id)

方式二:

**alter table 表名 add 索引类型 索引名(字段) ** 例: 单值:alter table user add index name_index(name); 唯一索引:alter table user add unique index id_index(id) 复合索引:alter table user add index name_id_index(name,id)

3.3删除索引

drop index 索引名 on 表名

3.4查询索引

show index from 表名;

4. SQL性能问题

分析SQL的执行计划 explain,可以模拟sql优化器执行SQL语句,从而让开发人员知道自己的编写语句的性能 mysql查询优化会干扰我们的优化查询执行计划:explain +SQL语句 idselect_typetabletypepossible_keyskeykey_lenrefrowsExtra编号查询类型表索引类型预测用到的索引实际索引实际使用索引的长度表之间的引用通过索引查到的数据量额外的信息

4.1 查询参数问题:

id:

id值相同,表记录小优先查询多表查询时会因为表数量记录的个数改变而改变:笛卡尔积(中间值越小越好)导致最小的表优先查询id值不同,id值大的优先查询

select_type :

Primary:包含子查询sql中的 主查询(最外层)subquery:包含子查询sql中的 子查询 (非最外层)simple: 简单查询derived:衍生查询(用到了临时表)在from查询中只有一张表 from下时union关系

type :索引类型

system>const>eq_ref>ref>range>index>all

性能system最大 all最小需要优化的前提:有索引system,const只是理想情况,实际能达到 ref>range system:只有一条数据的系统表:或衍生表只有一条数据的主查询 const:仅仅能查到一条数据的sql,用于primary key或unique索引 eq_ref:唯一性索引:对于每个索引键的查询,返回匹配唯一行数据(有且仅有1条):表中的个数和连接查询的数据个数一致,则有可能eq_ref级别 ref:非唯一索引,对于每个索引键的查询,返回匹配的所有行 range:检索指定范围的行,where后面是一个范围查询 index:查询全部索引的数据 explain select 索引列 from user all:将全部表查询一表 explain select 非索引列 from user 总结: system/const:结果只有一条数据 eq_ref:结果多条,但是每条数据是唯一的 ref:结果多条,但是每条数据是0或者多条

possible_keys:可能用到的索引,是一种预测,不准

key:实际使用到的索引

如果possible_key和key是NULL,则说明没用索引

key_len: 索引长度:作用:用于判断复合索引是否被完全使用

在utf8:一个字符站三个字节 gbk:一个字符两个字节 latin:一个字符一个字节 如果索引字段可以为NULL,则会使用1个字节用于标识

ref:指明当前表所 参照的 字段

rows: 被索引优化查询的 数据个数

Extra:duan

using filesort : 性能消耗大;需要"额外"的一次排序(查询)(查询一个字段 排序一个另一个字段) 小结:对于单索引,如果排序和查找是同一字段,则不会出现using filesort; 复合索引:不能跨列(最佳左前缀) 避免:where 那些字段 就order by那些字段 using temporary:性能损耗大,用到了临时表。一般出现在group by 语句中(已经查了一张表但是不适用 还得在查一张表) 避免:查询 那些列 就根据那些列order by **using index **:性能提升:索引覆盖(覆盖索引)。原因:不读取原文件。只从索引文件中获取数据 只要使用到的列:全部都在索引中,就是索引覆盖 如果用到了索引覆盖(using index时),会对possible_key和key造成影响 a.如果没有where,则索引只出现在key中; b.如果有索引,出现在key和possobler_keys中 using where:(需要回表查询) impossible where:where结果永远为false using join buffer:extra中的一个选项,作用:mysql引擎使用了连接缓存

5. 优化

5.1 单表优化

优化:加索引

根据SQL实际解析的顺序,调整索引的顺序索引一旦进行升级优化,需要将之间废弃的索引删掉,防止干扰

5.2 多表优化

优化:将数据小的表 放在外面 (小表在左)

索引建立在经常使用的字段上(左外连接给左表加索引,右外连接给右表加索引)小表驱动大表

5.3 避免索引失效的一些原则

复合索引:不要跨列或无序使用(最佳左前缀)复合索引:尽量使用全索引匹配复合索引:左边失效右边全部失效复合索引:不能使用不等于否则自身失效以及右侧全部失效复合索引:有大于号则自身失效独立索引:互不影响不要在索引上进行任何操作(计算、函数、类型转换),否则索引失效’SQL优化不会百分之百的优化,所以顺序要写对服务层的优化器可能影响我们的优化一般情况下范围查询之后的索引失效!!!尽量使用索引覆盖(百分百成功)like经量使用常量开头,不要以**%**开头,否则索引失效,如果必须使用,则用索引覆盖尽量不要使用类型装换(显示隐式)否则会失效尽量不要用or否则索引失效,or会将左右都失效

5.4 一些优化方法

如果主查询的数据集大,则使用in如果子查询的数据集大,则使用existorder by 优化 using filesort 有两种算法:双路排序、单路排序(根据IO的次数)

mysql4.1之前用的 双路排序:双路:扫描2次磁盘(1:从磁盘读取排序字段 (在buffer中进行排序)2:扫描其他字段) 改成单次 因为io比较消耗性能 mysql4.1之后用的 单路排序:只读取一次(全部字段),在buffer中进行排序 会有一定的隐患(不一定真的是”单路|1次IO“,有可能多次IO)。原因:如果数据量特别大,则无法将所有字段的数据一次性读取完毕,因此会进行‘分片读取、多次读取’; 注意: 单路排序会比双路排序占用更多的buffer 单路排序在使用时,如果数据大,考虑调大buffer的容量大小。 set max_length_for_sort_data =1024; 单位字节 如果max_length_for_sort_data值太低,则mysql会自动从单路->双路

提高order by查询的策略: 选择使用单路,双路:调整buffer的容量;避免使用 select *复合索引 不要跨列使用尽量保证排序字段的 排序一致性(都是升序 或 都是降序)

5.5 SQL排查-慢查询日志:

mysql提供的一种日志记录,用于记录MYSQL中响应时间超过阈值的sql语句(long_queryy_time,默认10秒) 慢查询日志默认是关闭的;建议:开发调优是 打开,而 最终部署时关闭; 慢查询日志是否开启:show variables like '%slow_query_log%'; 开启慢查询:

临时开启:set global slow_query_log=1; --在内存中开启永久开启:更改mysql配置文件 /etc/my.cnf 中追加配置,在mysqld中追加 slow_qurey_log=1 slow_query_log_file=/var/lib/mysql/localhost-slow.log

慢查询阈值:show variables like '%long_query_time%';

临时设置阈值: set global long_query_time = 5; --修改后,需要重新登录(不需要重启服务)永久设置阈值: /etc/my.cnf 中追加配置,在mysqld中追加 long_query_time=3

测试一下:

select sleep(4);show global status like ‘%slow_queries%’;慢查询的sql被记录在了日志里面,因此可以通过日志,查看具体的慢sql日志通过mysqldumpslow --help s:排序方式r:逆序l:锁定时间g:正则匹配模式

–获取返回记录最多的 mysqldumpslow -s r -t 3 /var/lib/mysql/localhost-slow.log –获取访问次数最多的3个SQLmysqldumpslow -s c -t 3 /var/lib/mysql/localhost-slow.log –按照时间排序,前十条包含left join查询语句的mysqldumpslow -s t -t 10 -g "left join" /var/lib/mysql/localhost-slow.log

6. 分析海量数据

分析海量数据:profiles show profiles; —默认关闭 set profiling = on; //开始记录 show profiles; 会记录所有profiling 打开之后的 全部sql查询语句所花费的时间 缺点:不够精确,只能看到总共消费的时间,不能看到各个硬件消费的时间 精确分析:sql诊断 show profile all for query id值 上一步查询的sqlid show profile cpu,blockio fo query id值 只查看和cpu io相关的 看全局查询日志:记录开启之后的,全部sql语句;(这次全局的记录操作,仅仅在调优、开发过程中打开即可,在最终部署时,一定关闭) show variables like '%general log%' set global general_log=1;打开全局日志:开启后会记录所有的sql set global log_output='table';记录到表中 会记录到mysql.general_log表中 select * from mysql.general_log

7. 锁机制

解决因资源共享而造成的并发问题 分类: 操作:

读锁(共享锁)写锁(独占锁) 范围:表索:MyISAM存储引擎使用:开销小、加锁快、无死锁,容易发送锁冲突、并发度低行锁 : innoDB存储引擎使用:开销大、加锁慢、容易死锁,不容易锁冲突、并发度高页锁
最新回复(0)