目录

查询缓存

查询优化处理的三个阶段

InnoDB的锁

MVCC

Mysql服务器参数类型

主键顺序插入和随机插入对性能的影响

MySQL的SQL书写和优化技巧


查询缓存

工作原理:
缓存SELECT操作的结果集和SQL语句;
新的SELECT语句, 先去查询缓存, 判断是否存在可用的记录集;
判断标准:
与缓存的SQL语句, 是否完全一样, 区分大小写
(简单认为存储了一个key-value结构, key为sql, value为sql查询结果集)

query_cache_type
值: 0 -– 不启用查询缓存, 默认值;
值: 1 -– 启用查询缓存, 只要符合查询缓存的要求, 客户端的查询语句和记录集
都可以缓存起来, 供其他客户端使用, 加上 SQL_NO_CACHE将不缓存
值: 2 -– 启用查询缓存, 只要查询语句中添加了参数: SQL_CACHE, 且符合查询
缓存的要求, 客户端的查询语句和记录集, 则可以缓存起来, 供其他客户端使用(按需开启)
query_cache_size
允许设置query_cache_size的值最小为40K, 默认1M, 推荐设置 为: 64M/128M;
query_cache_limit
限制查询缓存区最大能缓存的查询记录集, 默认设置为1M
show status like 'Qcache%' 命令可查看缓存情况

查询不会缓存的情况:

1.当查询语句中有一些不确定的数据时, 则不会被缓存。 如包含函数NOW(),
CURRENT_DATE()等类似的函数, 或者用户自定义的函数, 存储函数, 用户变
量等都不会被缓存
2.当查询的结果大于query_cache_limit设置的值时, 结果不会被缓存
3.对于InnoDB引擎来说, 当一个语句在事务中修改了某个表, 那么在这个事务
提交之前, 所有与这个表相关的查询都无法被缓存。 因此长时间执行事务,
会大大降低缓存命中率
4, 查询的表是系统表
5, 查询语句不涉及到表

为什么mysql默认关闭了缓存开启?

1.在查询之前必须先检查是否命中缓存,浪费计算资源
2.如果这个查询可以被缓存, 那么执行完成后, MySQL发现查询缓存中没有这
个查询, 则会将结果存入查询缓存, 这会带来额外的系统消耗
3.针对表进行写入或更新数据时, 将对应表的所有缓存都设置失效。
4.如果查询缓存很大或者碎片很多时, 这个操作可能带来很大的系统消耗

适用场景:

以读为主的业务, 数据生成之后就不常改变的业务
比如门户类、 新闻类、 报表类、 论坛类等

查询优化处理的三个阶段

• 解析sql
通过lex词法分析,yacc语法分析将sql语句解析成解析树
https://www.ibm.com/developerworks/cn/linux/sdk/lex/
• 预处理阶段
根据mysql的语法的规则进一步检查解析树的合法性, 如: 检查数据的表
和列是否存在, 解析名字和别名的设置。 还会进行权限的验证
• 查询优化器
优化器的主要作用就是找到最优的执行计划

查询骑如何找到最优执行计划
1.使用等价变化规则     5 = 5 and a > 5 改写成 a > 5   a < b and a = 5 改写成 b > 5 and a = 5
2.外连接自动转为内连接 
3.基于联合索引, 调整条件位置等
4. 优化count 、 min、 max等函数.   min函数只需找索引最左边,max函数只需找索引最右边,myisam引擎count(*)
5. 覆盖索引扫描
6.子查询优化
7.提前终止查询 用了limit关键字或者使用不存在的条件
8.IN的优化         先进行排序, 再采用二分查找的方式

Mysql的查询优化器是基于成本计算的原则。 他会尝试各种执行计划。
数据抽样的方式进行试验( 随机的读取一个4K的数据块进行分析)

explian各个字段的含义 

type

访问类型, sql查询优化中一个很重要的指标, 结果值从好到坏依次是:
system > const > eq_ref > ref > range > index > ALL
system: 表只有一行记录( 等于系统表) , const类型的特例, 基本不会出现, 可以忽略不计
const: 表示通过索引一次就找到了, const用于比较primary key 或者 unique索引
eq_ref: 唯一索引扫描, 对于每个索引键, 表中只有一条记录与之匹配。 常见于主键 或 唯一索引扫描
ref: 非唯一性索引扫描, 返回匹配某个单独值的所有行, 本质是也是一种索引访问
range: 只检索给定范围的行, 使用一个索引来选择行
index: Full Index Scan, 索引全表扫描, 把索引从头到尾扫一遍
ALL: Full Table Scan, 遍历全表以找到匹配的行

possible_keys
查询过程中有可能用到的索引

key
实际使用的索引, 如果为NULL, 则没有使用索引

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

filtered
它指返回结果的行占需要读到的行(rows列的值)的百分比
表示返回结果的行数占需读取行数的百分比, filtered的值越大越好

Extra 
1、 Using filesort :
mysql对数据使用一个外部的文件内容进行了排序, 而不是按照表内的索引进行排序读取
2、 Using temporary:
使用临时表保存中间结果, 也就是说mysql在对查询结果排序时使用了临时表, 常见于order by 或 group by
3、 Using index:
表示相应的select操作中使用了覆盖索引( Covering Index) , 避免了访问表的数据行, 效率高
4、 Using where :
使用了where过滤条件
5、 select tables optimized away:
基于索引优化MIN/MAX操作或者MyISAM存储引擎优化COUNT(*)操作, 不必等到执行阶段在进行计算, 查询执行计划生成的阶段即可完成优化

慢查询日志的使用

配置

show variables like 'slow_query_log'
set global slow_query_log = on
set global slow_query_log_file = '/var/lib/mysql/gupaoedu-slow.log'
set global log_queries_not_using_indexes = on
set global long_query_time = 0.1 (秒)

日志分析

Time : 日志记录的时间
User@Host: 执行的用户及主机
Query_time: 查询耗费时间 Lock_time 锁表时间 Rows_sent 发送给请求方的记录
条数 Rows_examined 语句扫描的记录条数
SET timestamp 语句执行的时间点
select .... 执行的具体语句

分析工具

mysqldumpslow -t 10 -s at /var/lib/mysql/gupaoedu-slow.log

InnoDB的锁

一.锁的类型

共享锁:
又称为读锁, 简称S锁, 顾名思义, 共享锁就是多个事务对于同一数据可以共享一把锁,
都能访问到数据, 但是只能读不能修改;
加锁释锁方式:
select * from users WHERE id=1 LOCK IN SHARE MODE;
commit/rollback

排他锁:
又称为写锁, 简称X锁, 排他锁不能与其他锁并存, 如一个事务获取了一个数据行的排他
锁, 其他事务就不能再获取该行的锁( 共享锁、 排他锁) , 只有该获取了排他锁的事务是可以对
数据行进行读取和修改, ( 其他事务要读取数据可来自于快照)
加锁释锁方式:
delete / update / insert 默认加上X锁
SELECT * FROM table_name WHERE ... FOR UPDATE
commit/rollback

意向共享锁(IS):
表示事务准备给数据行加入共享锁, 即一个数据行加共享锁前必须先取得该表的IS锁,
意向共享锁之间是可以相互兼容的

意向排它锁(IX):
表示事务准备给数据行加入排他锁, 即一个数据行加排他锁前必须先取得该表的IX锁,
意向排它锁之间是可以相互兼容的

意向锁(IS、 IX)是InnoDB数据操作之前自动加的, 不需要用户干预
意义:当事务想去进行锁表时, 可以先判断意向锁是否存在, 存在时则可快速返回该表不能
启用表锁

理解:意向锁相当于一个判断锁是否被锁定过的flag

自增锁(AUTO-INC Locks)
针对自增列自增长的一个特殊的表级别锁
show variables like 'innodb_autoinc_lock_mode';
默认取值1, 代表连续, 事务未提交ID永久丢失

临间锁(Next-key locks):
锁住记录+区间(左开右闭)
当sql执行按照索引进行数据的检索时,查询条件为范围查找( between and、 <、 >等) 并有数
据命中则此时SQL语句加上的锁为Next-key locks, 锁住索引的记录+区间( 左开右闭)

防止幻读

间隙锁(Gap Locks)

当sql执行按照索引进行数据的检索时, 查询条件的数据不存在, 这时SQL语句加上的锁即为
Gap locks, 锁住索引不存在的区间( 左开右开)

Record locks:
锁住具体的索引项
当sql执行按照唯一性( Primary key、 Unique key) 索引进行数据的检索时, 查询条件等值匹配且查询的数据是存在, 这时SQL语句加上的锁即为记录锁Record locks, 锁住具体的索引项

二、利用锁类解决脏读、不可重复读、幻读

三、InnoDB行锁到底锁了什么

InnoDB的行锁是通过给索引上的索引项加锁来实现的。
只有通过索引条件进行数据检索,InnoDB才使用行级锁,否则,InnoDB将使用表锁(锁住索引的所有记录)
表锁:lock tables xx read/write

四、死锁

1)类似的业务逻辑以固定的顺序访问表和行。
2)大事务拆小。大事务更倾向于死锁,如果业务允许,将大事务拆小。
3)在同一个事务中,尽可能做到一次锁定所需要的所有资源,减少死锁概
率。
4)降低隔离级别,如果业务允许,将隔离级别调低也是较好的选择
5)为表添加合理的索引。可以看到如果不走索引将会为表的每一行记录添
加上锁(或者说是表锁)

MVCC

Multiversion concurrency control (多版本并发控制)

并发访问(读或写)数据库时,对正在事务内处理的数据做 多版本的管理。以达到用来避免写操作的堵塞,从而引发读操 作的并发问题。

备注:查询的条件1和条件2是&&关系

备注:先执行3,4没有commit。解决不可重复读或脏读采用的方案不是MVCC,而是快照读

Mysql服务器参数类型

一.基于参数的作用域:
全局参数
set global autocommit = ON/OFF;
会话参数(会话参数不单独设置则会采用全局参数)
set session autocommit = ON/OFF;
注意:
全局参数的设定对于已经存在的会话无法生效
会话参数的设定随着会话的销毁而失效
全局类的统一配置建议配置在默认配置文件中, 否则重启服务会导致配置失效

二.如何寻找配置文件

mysql --help 寻找配置文件的位置和加载顺序
Default options are read from the following files in the given order:
/etc/my.cnf /etc/mysql/my.cnf /usr/etc/my.cnf ~/.my.cnf
mysql --help | grep -A 1 'Default options are read from the following
files in the given order'

三、Mysql内存参数配置

每一个connection内存参数配置:
sort_buffer_size connection排序缓冲区大小
建议256K(默认值)-> 2M之内
当查询语句中有需要文件排序功能时, 马上为connection分配配置的内
存大小
join_buffer_size connection关联查询缓冲区大小
建议256K(默认值)-> 1M之内
当查询语句中有关联查询时, 马上分配配置大小的内存用这个关联查
询, 所以有可能在一个查询语句中会分配很多个关联查询缓冲区
上述配置4000连接占用内存:
4000*(0.256M+0.256M) = 2G

Innodb_buffer_pool_size
innodb buffer/cache的大小( 默认128M)
Innodb_buffer_pool
数据缓存
索引缓存
缓冲数据
内部结构
大的缓冲池可以减小多次磁盘I/O访问相同的表数据以提高性能
参考计算公式:
Innodb_buffer_pool_size = ( 总物理内存 - 系统运行所用 - connection 所用) * 90%

四、常见的全局配置文件

port = 3306
socket = /tmp/mysql.sock
basedir = /usr/local/mysql
datadir = /data/mysql
pid-file = /data/mysql/mysql.pid
user = mysql
bind-address = 0.0.0.0
max_connections=2000
lower_case_table_names = 0 #表名区分大小写
server-id = 1
tmp_table_size=16M
transaction_isolation = REPEATABLE-READ
ready_only=1

五、Mysql其他配置参数

wait_timeout
服务器关闭非交互连接之前等待活动的秒数
innodb_open_files
限制Innodb能打开的表的个数
innodb_write_io_threads
innodb_read_io_threads
innodb使用后台线程处理innodb缓冲区数据页上的读写 I/O(输入输出)请求
innodb_lock_wait_timeout
InnoDB事务在被回滚之前可以等待一个锁定的超时秒数
https://www.cnblogs.com/wyy123/p/6092976.html 常见配置的帖子

主键顺序插入和随机插入对性能的影响

首先来看顺序插入的情况。如果主键是顺序的,所以InnoDB会把每插入的记录存储在上一条记录的后面。当达到页的最大填充因子时(InnoDB默认的最大填充因子是15/16,流出不封空间用于以后可能产生的修改),下一条记录就会写入新的页中。一旦数据按照这种顺序的的方式插入,主键就会近似于被顺序的记录填满。

再来看随机插入的情况,比如使用了uuid聚簇索引的表插入数据。因为新插入的值是随机,可能比上一个插入的主键值大,也可能小,所以InnoDB无法简单的总是把新的记录插入到索引的最后,也就是说插入的位置很有可能是在现有数据的中间。这往往会导致性能恶化。

这种随机插入方式可能会有以下缺点:

  1. 写入的目标页可能不在内存缓存区,那么插入记录的时候需要先从磁盘读取目标页到内存中。这会导致大量的随机IO.如果是顺序插入,由于是插入到上一个记录的后面,则大多数情况下(不需要开辟新页的情况)磁盘页是已经加载到内存了的。
  2. 因为写入是乱序的,InnoDB可能需要不断的的做页分裂操作,以便为新的行分配空间。而页分裂会导致移动大量的数据,而且一次分裂至少要修改三个页而不是一个页。
  3. 由于频繁的分页,页面会变得稀疏并被不规则的填充,最后会导致数据碎片。

所以,当把随机值载入到聚簇索引后,最好做一次optimize table来重建表并优化页的填充。

当然顺序的主键在一些情况下也有可能有一些缺点。比如对于高并发的场景,如果按主键顺序插入可能会造成明显的争用。因为所有的插入都是上一次记录的后面,所以主键的上边界就会成为热点,这可能会导致间隙锁竞争。如果是随机插入的话,因为插入的地方可能都不一样,所以竞争就是少一点。

MySQL的SQL书写和优化技巧

一、MySQL正则表达式

使用REGEXP和NOT REGEXP操作符(或RLIKE和NOT RLIKE,它们是同义词)

“.”匹配任何单个的字符。(单字节字符)

“ * ”匹配零个或多个在它前面的东西

“^”在模式开始处

“$”在模式的结尾

SELECT * FROM user WHERE u_name REGEXP ‘^三’;SELECT * FROM user WHERE u_name REGEXP ‘三$’;

二、需求:随机从表中取N条数据

SELECT * FROM t_share ORDER BY rand() LIMIT 10;

百万大表随机取N条数据的优化

SELECT*
FROMt_table
WHEREid >= ((SELECT max(id) FROM t_table) - (SELECT min(id) FROM t_table)) * RAND() + (SELECT min(id) FROM t_table)
LIMIT 10

三、分组统计

MySQL提供了 group by with rollup 函数进行group by 字段的汇总

SELECT IFNULL(b.城市,"总计") AS 城市,SUM(IF(b.年月=201607,b.金额,NULL)) AS 7月金额,SUM(IF(b.年月=201608,b.金额,NULL)) AS 8月金额,SUM(IF(b.年月=201609,b.金额,NULL)) AS 9月金额
FROM (SELECT IFNULL(city,'空城市') AS 城市,DATE_FORMAT(order_time,"%Y%m") AS 年月,SUM(pay_money) AS 金额FROM test_a03order AS aGROUP BY city,DATE_FORMAT(order_time,"%Y%m")
) AS b
GROUP BY b.城市 WITH ROLLUP

四、MySQL中,追踪SQL。在线设置Trace,执行的sql保存在log文本中。

-- 查看MySQL的版本号
select version();

-- 查询关于log的设置 (若版本号为 ‘5.1.29’以上版本 like 'general_log%')
SHOW VARIABLES LIKE 'general_log%';

-- 开启日志
SET GLOBAL general_log ='ON';

-- 设置日志的文件路径:本例在Windows下
SET GLOBAL general_log_file='D:/MySql/Sql.log';

-- 设置结束,执行的sql语句会保存在‘D:/MySql/Sql.log’,可通过notepad++查看wu

五、MySQL中ORDER BY与LIMIT一起使用(有坑)

1、如果你只需要结果集中的某几行,那么建议使用limit。这样这样的话可以避免抓取全部结果集,然后再丢弃那些你不要的行。

2、对于order by查询,带或者不带limit可能返回行的顺序是不一样的。

3、如果limit row_count 与 order by 一起使用,那么在找到第一个row_count就停止排序,直接返回。

4、如果order by列有相同的值,那么MySQL可以自由地以任何顺序返回这些行。换言之,只要order by列的值不重复,就可以保证返回的顺序。

5、可以在order by子句中包含附加列,以使顺序具有确定性。

详细分析见:MySQL中ORDER BY与LIMIT一起使用(有坑) - 废物大师兄 - 博客园

MySQL的性能优化理论相关推荐

  1. MySQL的性能优化及自动化运维实践与Mysql高并发优化

    首先,我们来看看DBA的具体工作,我觉得 DBA 真的很忙:备份和恢复.监控状态.集群搭建与扩容.数据迁移和高可用,这是我们 DBA 的功能. 了解这些功能以后要对体系结构有更加深入的了解,你不知道怎 ...

  2. DBA很忙—MySQL的性能优化及自动化运维实践

    作者:王辰 来自:高效运维(ID:greatops) DBA的日常工作 首先,我们来看看DBA的具体工作,我觉得 DBA 真的很忙:备份和恢复.监控状态.集群搭建与扩容.数据迁移和高可用,这是我们 D ...

  3. MySQL数据库性能优化之一

    MySQL数据库性能优化需要考虑的几个方面: 1.sql语句及索引优化 2.数据库结构优化 3.系统配置优化 4.硬件优化 转载于:https://blog.51cto.com/davidlinux/ ...

  4. mysql 改表面_MySQL_解析MySQL数据库性能优化的六大技巧,数据库表表面上存在索引和防 - phpStudy...

    解析MySQL数据库性能优化的六大技巧 数据库表表面上存在索引和防错机制,然而一个简单的查询就会耗费很长时间.Web应用程序或许在开发环境中运行良好,但在产品环境中表现同样糟糕.如果你是个数据库管理员 ...

  5. 淘宝内部分享:MySQL MariaDB性能优化

     淘宝内部分享:MySQL & MariaDB性能优化 摘要:MySQL是目前使用最多的开源数据库,但是MySQL数据库的默认设置性能非常的差,必须进行不断的优化,而优化是一个复杂的任务, ...

  6. MySQL主从复制性能优化

    MySQL主从复制性能优化 MySQL的主从复制的基本原理是从库连接到主库,主库生成一个主库DUMP线程,该DUMP线程的主要任务是 一直挖掘binlog日志,然后发送到从库的IO线程,IO线程接收到 ...

  7. #周末课堂# 【Linux + JVM + Mysql高级性能优化班】(火热报名中~~~)

    Linux + JVM + Mysql高级性能优化课程 课程名称:      Linux + JVM + Mysql高级性能优化 QQ群:      243242580(小白.菜鸟勿进)跟Java.M ...

  8. MySQL 数据库性能优化之SQL优化

    2019独角兽企业重金招聘Python工程师标准>>> MySQL 数据库性能优化之SQL优化 发布时间: 2012 年 3 月 21 日  发布者: OurMySQL 来源:简朝阳 ...

  9. MySQL数据库性能优化的关键参数(转)

    我们在进行数据库管理和开发中经常会遇到性能问题,这就涉及到MySQL的性能优化.通过在网络上查找资料和笔者自己的尝试,我认为以下系统参数是比较关键的: 关键参数一:back_log 要求 MySQL ...

最新文章

  1. 基于K-gram的winnowing特征提取剽窃查重检测技术(概念篇)
  2. Android之assets资源
  3. Docker知识1:Docker-hub简介
  4. Animate与transform的使用
  5. update 没有索引导致业务崩了,老板骂了一个小时
  6. linux配置apache服务器项目文档,Apache(Linux)服务器配置文档.doc
  7. MTK 驱动(20)--- camera 相机启动时间优化
  8. 水泵怎么做_燃气壁挂炉初次调试,要怎么做才好?
  9. 关于C语言的指针、链表的原理和各类操作
  10. java连接远程服务器之manyged-ssh2 (windows和linux)
  11. 艾永亮:这家酒店如何让你毫不犹豫点上五星好评?
  12. ShineDisk M667固态修复记录 慧荣SM2258XT开卡量产工具
  13. sqlServer取余数
  14. 链接脚本之SECTIONS
  15. 将 s1 和 r1 上的启动配置文件上传到服务器进行备份,packettracer综合技能练习261...
  16. iOS 免审核更换图标
  17. map和multimap的用法详解
  18. 字符串指针和指向字符串的指针变量
  19. 实际上Ubuntu在你最起初配置完系统以后,是无法访问root类型的操作的(下面详解),ubuntu系统网络设置方法(图文)
  20. 059 感情的维系在于什么?

热门文章

  1. 矩估计和最大似然估计关系
  2. oracle xe连接数,解决Oracle XE允许连接的用户数不足问题
  3. Silverlight游戏特效开发(一) : 制作人物光环效果
  4. 数据结构--环形队列
  5. 算法导论------递归算法的时间复杂度求解
  6. 带你了解递归算法的时间复杂度
  7. Qt QImage scaled方法缩放中的问题
  8. Tensorflow Test1
  9. 读Java核心技术36讲有感——谈谈对Java的理解,谈谈Exception和Error
  10. 手机电池电量剩余通知