2.1原因:性能低、执行时间长,等待时间长,sql语句欠佳(连接查询),索引失效、服务器参数设置不合理(缓冲、线程数) 2.2sql优化:主要就是优化索引
索引相当于书的目录index是帮助mysql高效获取数据的数据结构。索引是数据结构(树:b树、二叉树。。)索引的弊端: 索引本身很大,可以放到内存/硬盘中索引不是所有的情况都适用:a.少量数据 b.频繁的更新的字段 c.很少使用的字段索引会降低增删改的效率(因为更改以后还需要去更改索引) 优势 提高查询效率(降低了io的使用率)降低cpu的使用率(因为已经做好了排序等)单值索引:单列,一个表可以有多个单值索引 唯一索引:不能重复 id(和主键索引的区别 主键不能为null) 复合索引:多个列构成的索引(相当于 一级目录二级目录。。。)
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)
drop index 索引名 on 表名
show index from 表名;
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_key和key是NULL,则说明没用索引
在utf8:一个字符站三个字节 gbk:一个字符两个字节 latin:一个字符一个字节 如果索引字段可以为NULL,则会使用1个字节用于标识
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引擎使用了连接缓存
优化:加索引
根据SQL实际解析的顺序,调整索引的顺序索引一旦进行升级优化,需要将之间废弃的索引删掉,防止干扰优化:将数据小的表 放在外面 (小表在左)
索引建立在经常使用的字段上(左外连接给左表加索引,右外连接给右表加索引)小表驱动大表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 *复合索引 不要跨列使用尽量保证排序字段的 排序一致性(都是升序 或 都是降序)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
分析海量数据: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
解决因资源共享而造成的并发问题 分类: 操作:
读锁(共享锁)写锁(独占锁) 范围:表索:MyISAM存储引擎使用:开销小、加锁快、无死锁,容易发送锁冲突、并发度低行锁 : innoDB存储引擎使用:开销大、加锁慢、容易死锁,不容易锁冲突、并发度高页锁