MySQL/MariaDB数据库的查询缓存优化
MySQL/MariaDB数据库的查询缓存优化
作者:尹正杰
版权声明:原创作品,谢绝转载!否则将追究法律责任。
一.MySQL架构
Connectors(MySQL对外提供的交互接口,API):
Connectors组件,是MySQL向外提供的交互组件,如Python,Golang,Java,C++,Php等语言可以通过该组件来操作SQL语句,实现与SQL的交互。 Connection Pool(连接池组件):
负责监听对客户端向MySQL Server端的各种请求,接收请求,转发请求到目标模块。每个成功连接MySQL Server的客户请求都会被创建或分配一个线程,该线程负责客户端与MySQL Server端的通信,接收客户端发送的命令,传递服务端的结果信息等。 SQL Interface(SQL接口组件):
接收用户SQL命令,检查SQL语法是否正确,如DML,DDL和存储过程等,并将最终结果返回给用户。 Parser(查询分析器组件):
首先分析SQL命令语法的合法性,并尝试将SQL命令分解成数据结构(将SQL指令转换成二进制格式来执行),若分解失败,则提示SQL语句不合理。 Optimlzer(优化器组件):
对SQL命令按照标准流程进行优化分析,选择最佳的查询路径。 Caches & Buffers(缓存主件):
缓存和缓冲组件 Pluggable Storage Engines(插件式存储引擎):
通过插件式存储引擎访问真正存储数据,常见的存储引擎有MyISAM,InnoDB等。 File system(文件系统):
存储引擎会帮我们和操作系统打交道,大家都直到数据持久化存储的依旧式在本地磁盘上。支持不同的文件系统,包括NTFS,EXT2/3/4,NFS,XFS等。 FIle & Logs:
各种各样的数据库相关文件,如数据文件,日志文件等,如Redo(重做),Undo(撤销)等。 Management Service & Utilities(管理服务组件和工具组件):
提供对MySQL的集成管理,如备份(Backup),恢复(Recovery),安全管理(Security)等
二.查询的执行路径
MySQL 整个查询执行过程,总的来说分为 5 个步骤 :
1.客户端向 MySQL 服务器发送一条查询请求
2.服务器首先检查查询缓存,如果命中缓存,则立刻返回存储在缓存中的结果,否则进入下一阶段
3.服务器进行 SQL解析、预处理、再由优化器生成对应的执行计划
4.MySQL 根据执行计划,调用存储引擎的 API来执行查询
5.将结果返回给客户端,同时缓存查询结果
三.查询缓存
1>.查询缓存( Query Cache )原理
缓存SELECT操作或预处理查询的结果集和SQL语句,当有新的SELECT语句或预处理查询语句请求,先去查询缓存,判断是否存在可用的记录集,判断标准:与缓存的SQL语句(进行HASH值对比),是否完全一样,区分大小写
2>.查询缓存( Query Cache )优缺点
不需要对SQL语句做任何解析和执行,当然语法解析必须通过在先,直接从Query Cache中获得查询结果,提高查询性能
查询缓存的判断规则,不够智能,也即提高了查询缓存的使用门槛,降低其效率;
查询缓存的使用,会增加检查和清理Query Cache中记录集的开销
3>.哪些查询可能不会被缓存
查询语句中加了SQL_NO_CACHE参数;
查询语句中含有获得值的函数,包含自定义函数,如:NOW(),CURDATE(),GET_LOCK(),RAND(),CONVERT_TZ()等;
对系统数据库的查询:mysql、information_schema 查询语句中使用SESSION级别变量或存储过程中的局部变量;
查询语句中使用了LOCK IN SHARE MODE、FOR UPDATE的语句,查询语句中类似SELECT …INTO 导出数据的语句;
对临时表的查询操作;存在警告信息的查询语句;不涉及任何表或视图的查询语句;某用户只有列级别权限的查询语句;
事务隔离级别为Serializable时,所有查询语句都不能缓存。
4>.查询缓存相关的服务器变量
query_cache_min_res_unit:
查询缓存中内存块的最小分配单位,默认4k,较小值会减少浪费,但会导致更频繁的内存分配操作,较大值会带来浪费,会导致碎片过多,内存不足
query_cache_limit:
单个查询结果能缓存的最大值,在MariaDB 10.2.x版本中默认为10M,对于查询结果过大而无法缓存的语句,建议使用SQL_NO_CACHE
query_cache_size:
查询缓存总共可用的内存空间;单位字节,必须是1024的整数倍,最小值40KB,低于此值有警报
query_cache_wlock_invalidate:
如果某表被其它的会话锁定,是否仍然可以从查询缓存中返回结果,默认值为OFF,表示可以在表被其它会话锁定的场景中继续从缓存返回数据;ON则表示不允许
query_cache_type:
是否开启缓存功能,取值为ON, OFF, DEMAND
MariaDB [yinzhengjie]> SHOW VARIABLES LIKE 'query_cache%'; #查看Mariadb 10.2.x默认的缓存相关服务器变量。
+------------------------------+---------+
| Variable_name | Value |
+------------------------------+---------+
| query_cache_limit | 1048576 | #默认是10M
| query_cache_min_res_unit | 4096 | #默认是4K
| query_cache_size | 1048576 | #默认是10M
| query_cache_strip_comments | OFF |
| query_cache_type | OFF | #很显然,默认是没有开启缓存的
| query_cache_wlock_invalidate | OFF | #默认是关闭的
+------------------------------+---------+
rows in set (0.00 sec) MariaDB [yinzhengjie]>
MariaDB [yinzhengjie]>
MariaDB [yinzhengjie]> SHOW VARIABLES LIKE 'query_cache%'; #查看默认的缓存相关服务器变量(优化查询缓存流程图如下)
5>.SELECT语句的缓存控制
SQL_CACHE:
显式指定存储查询结果于缓存之中
SQL_NO_CACHE:
显式查询结果不予缓存
6>.query_cache_type参数变量
query_cache_type的值为OFF或0时,查询缓存功能关闭 query_cache_type的值为ON或1时,查询缓存功能打开,SELECT的结果符合缓存条件即会缓存,否则,不予缓存,显式指定SQL_NO_CACHE,不予缓存,此为默 query_cache_type的值为DEMAND或2时,查询缓存功能按需进行,显式指定SQL_CACHE的SELECT语句才会缓存;其它均不予缓存 博主推荐阅读:
https://mariadb.com/kb/en/library/server-system-variables/#query_cache_type
https://dev.mysql.com/doc/refman/5.7/en/query-cache-configuration.html
7>.查询缓存相关的状态变量
Qcache_free_blocks:
处于空闲状态 Query Cache中内存 Block 数
Qcache_total_blocks:
Query Cache 中总Block ,当Qcache_free_blocks相对此值较大时,可能用内存碎片,执行FLUSH QUERY CACHE清理碎片
Qcache_free_memory:
处于空闲状态的 Query Cache 内存总量
Qcache_hits:Query Cache:
命中次数
Qcache_inserts:
向 Query Cache 中插入新的 Query Cache 的次数,即没有命中的次数 Qcache_lowmem_prunes:
记录因为内存不足而被移除出查询缓存的查询数
Qcache_not_cached:
没有被 Cache 的 SQL 数,包括无法被 Cache 的 SQL 以及由于 query_cache_type 设置的不会被 Cache 的 SQL语句
Qcache_queries_in_cache:
在 Query Cache 中的 SQL 数量
MariaDB [yinzhengjie]> SHOW GLOBAL STATUS LIKE 'Qcache%'; #查询MariaDB 10.2.x 缓存相关的状态变量
+-------------------------+---------+
| Variable_name | Value |
+-------------------------+---------+
| Qcache_free_blocks | 1 |
| Qcache_free_memory | 1031336 |
| Qcache_hits | 0 |
| Qcache_inserts | 0 |
| Qcache_lowmem_prunes | 0 |
| Qcache_not_cached | 0 |
| Qcache_queries_in_cache | 0 |
| Qcache_total_blocks | 1 |
+-------------------------+---------+
8 rows in set (0.00 sec) MariaDB [yinzhengjie]>
MariaDB [yinzhengjie]> SHOW GLOBAL STATUS LIKE 'Qcache%'; #查询MariaDB 10.2.x 缓存相关的状态变量
8>.查询缓存中内存块的最小分配单位query_cache_min_res_unit计算公式
(query_cache_size - Qcache_free_memory) / Qcache_queries_in_cache
9>.查询缓存命中率计算公式
Qcache_hits / ( Qcache_hits + Qcache_inserts ) * 100%
10>.查询缓存内存使用率计算公式
(query_cache_size – qcache_free_memory) / query_cache_size * 100%
四.InnoDB存储引擎缓存
1>.InnoDB存储引擎的缓冲池
通常InnoDB存储引擎缓冲池的命中不应该小于99%.
2>.查看相关状态变量
Innodb_buffer_pool_reads:
表示从物理磁盘读取页的次数
Innodb_buffer_pool_read_ahead:
预读的次数
Innodb_buffer_pool_read_ahead_evicted:
预读页,但是没有读取就从缓冲池中被替换的页数量,一般用来判断预读的效率
Innodb_buffer_pool_read_requests:
从缓冲池中读取页次数
Innodb_data_read:
总共读入的字节数
Innodb_data_reads:
发起读取请求的次数,每次读取可能需要读取多个页
MariaDB [yinzhengjie]> SHOW GLOBAL STATUS LIKE 'innodb%read%'; #查看MariaDB 10.2.x默认相关状态变量
+--------------------------------------------------------+---------+
| Variable_name | Value |
+--------------------------------------------------------+---------+
| Innodb_buffer_pool_read_ahead_rnd | 0 |
| Innodb_buffer_pool_read_ahead | 0 |
| Innodb_buffer_pool_read_ahead_evicted | 0 |
| Innodb_buffer_pool_read_requests | 2951 |
| Innodb_buffer_pool_reads | 369 |
| Innodb_data_pending_reads | 0 |
| Innodb_data_read | 6113792 |
| Innodb_data_reads | 390 |
| Innodb_pages_read | 368 |
| Innodb_pages0_read | 11 |
| Innodb_rows_read | 179 |
| Innodb_system_rows_read | 0 |
| Innodb_secondary_index_triggered_cluster_reads | 0 |
| Innodb_secondary_index_triggered_cluster_reads_avoided | 0 |
| Innodb_encryption_rotation_pages_read_from_cache | 0 |
| Innodb_encryption_rotation_pages_read_from_disk | 0 |
+--------------------------------------------------------+---------+
16 rows in set (0.00 sec) MariaDB [yinzhengjie]>
MariaDB [yinzhengjie]> SHOW GLOBAL STATUS LIKE 'innodb%read%'; #查看MariaDB 10.2.x默认相关状态变量
3>.Innodb缓冲池命中率计算公式
(Innodb_buffer_pool_read_requests)/(Innodb_buffer_pool_read_requests + Innodb_buffer_pool_read_ahead + Innodb_buffer_pool_reads)
4>.平均每次读取的字节数计算公式
Innodb_data_read/Innodb_data_reads
MySQL/MariaDB数据库的查询缓存优化的更多相关文章
- MySQL/MariaDB数据库的索引工作原理和优化
MySQL/MariaDB数据库的索引工作原理和优化 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. 实际工作中索引这个技术是影响服务器性能一个非常重要的指标,因此我们得花时间去了 ...
- MySQL/MariaDB数据库的多表查询操作
MySQL/MariaDB数据库的多表查询操作 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. 一.单表查询小试牛刀 [root@node105.yinzhengjie.org.cn ...
- MySQL/MariaDB数据库的PROXY实现读写分离
MySQL/MariaDB数据库的PROXY实现读写分离 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. 一.ProxySQL概述 1>.各家互联网公司读写分离的解决方案 m ...
- MySQL/MariaDB数据库的mysqldump工具备份还原实战
MySQL/MariaDB数据库的mysqldump工具备份还原实战 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. 一.mysqldump概述 1>.逻辑备份工具 mysq ...
- MySQL/MariaDB数据库的各种日志管理
MySQL/MariaDB数据库的各种日志管理 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. 一.事务日志 (transaction log) 1>.Innodb事务日志相 ...
- MySQL/MariaDB数据库的并发控制
MySQL/MariaDB数据库的并发控制 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. 一.并发控制概述 1>.什么是并发控制 MySQL是一个服务器级别的数据库,它通常 ...
- MySQL/MariaDB数据库的存储引擎
MySQL/MariaDB数据库的存储引擎 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. 一.MySQL体系结构 连接管理模块: 负责接收远程用户的连接. 线程管理模块: 维护 ...
- mysql如何执行关联查询与优化
mysql如何执行关联查询与优化 一.前言 在数据库中执行查询(select)在我们工作中是非常常见的,工作中离不开CRUD,在执行查询(select)时,多表关联也非常常见,我们用的也比较多,那么m ...
- MySQL/MariaDB数据库的性能测试
MySQL/MariaDB数据库的性能测试 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. 一.数据库服务衡量指标 qps: query per second(每秒支持多少查询 ...
随机推荐
- python初级(302) 6 对象(一)
作业: 1.编写一个Dog类,并生成对象dog,属性包含颜色,大小,重量,可以汪汪叫,摇尾巴,跑 # -*- coding: utf-8 -*- class Dog: def __init__(sel ...
- Centos7根据yum源安装指定版本docker
yum install -y yum-utils device-mapper-persistent-data lvm2 yum-config-manager --add-repo https://mi ...
- Centos7环境下部署搭建discuz论坛
1.首先搭建lnmp环境 2.从官网复制git地址(https://gitee.com/ComsenzDiscuz/DiscuzX),在服务器上安装git命令 yum install git -y ...
- npm 的一些命令
查看项目中是否安装某个插件 npm [name] -v [name] 为要查询的插件的名字,如果已经安装就会显示该插件的版本号 npm list 查看项目中所有已安装的插件
- mysql 导入txt数据到数据表【原创】
1.如何将数据表导入到mysql的表中,可以使用:load data infile ... into table ... 示例: load data infile 'e:\datainfo.txt' ...
- (IO模型介绍,阻塞IO,非阻塞IO,多路复用IO,异步IO,IO模型比较分析,selectors模块,垃圾回收机制)
参考博客: https://www.cnblogs.com/xiao987334176/p/9056511.html 内容回顾 协程实际上是一个线程,执行了多个任务,遇到IO就切换 切换,可以使用yi ...
- 【javascript】日期转字符串
function dateFormat(fmt, date) { var ret; var tf = function(str, len){ if(str.length < len) { for ...
- Jmeter在Http Rest接口中自动生成签名(Json格式请求参数)
第一步: 签名的java类生成jar包,导入到jmeter的lib目录下(依赖的第三方包也要导入) 第二步:编写jmeter脚本,这里使用BeanShell 进行签名串的生成,目录结构如下: Bean ...
- 通过 SMB 共享目录
在 system1 上配置SMB服务 ,要求: 1.您的 SMB 服务器必须是 STAFF 工作组的一个成员 2.共享 /common 目录,共享名必须为 common 3.只有 group8.exa ...
- 「UER#2」谣言的传播
「UER#2」谣言的传播 写了个乱搞,怎么莫名其妙就AC了,这...,之后又想了30min结合题解终于会证了. 首先最大值比较简单,记 \(f_i\) 为第 \(i\) 个点能到达的点数,上界 \(\ ...