MySQL/MariaDB数据库的查询缓存优化

摘要:
否则将追究法律责任。一.MySQL架构Connectors:  Connectors组件,是MySQL向外提供的交互组件,如Python,Golang,Java,C++,Php等语言可以通过该组件来操作SQL语句,实现与SQL的交互。ConnectionPool:  负责监听对客户端向MySQLServer端的各种请求,接收请求,转发请求到目标模块。每个成功连接MySQLServer的客户请求都会被创建或分配一个线程,该线程负责客户端与MySQLServer端的通信,接收客户端发送的命令,传递服务端的结果信息等。Optimlzer:  对SQL命令按照标准流程进行优化分析,选择最佳的查询路径。

MySQL/MariaDB数据库的查询缓存优化

作者:尹正杰

版权声明:原创作品,谢绝转载!否则将追究法律责任。

一.MySQL架构

MySQL/MariaDB数据库的查询缓存优化第1张

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等。
Filesystem(文件系统):
  存储引擎会帮我们和操作系统打交道,大家都直到数据持久化存储的依旧式在本地磁盘上。支持不同的文件系统,包括NTFS,EXT2/3/4,NFS,XFS等。
FIle &Logs:
  各种各样的数据库相关文件,如数据文件,日志文件等,如Redo(重做),Undo(撤销)等。
Management Service &Utilities(管理服务组件和工具组件):
  提供对MySQL的集成管理,如备份(Backup),恢复(Recovery),安全管理(Security)等

二.查询的执行路径

MySQL/MariaDB数据库的查询缓存优化第2张

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
MySQL/MariaDB数据库的查询缓存优化第3张MySQL/MariaDB数据库的查询缓存优化第4张
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.00sec)
MariaDB [yinzhengjie]>
MariaDB [yinzhengjie]> 
 
MariaDB [yinzhengjie]> SHOW VARIABLES LIKE 'query_cache%';    #查看默认的缓存相关服务器变量(优化查询缓存流程图如下)

MySQL/MariaDB数据库的查询缓存优化第5张

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 数量
MySQL/MariaDB数据库的查询缓存优化第3张MySQL/MariaDB数据库的查询缓存优化第7张
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.00sec)
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:
发起读取请求的次数,每次读取可能需要读取多个页
MySQL/MariaDB数据库的查询缓存优化第3张MySQL/MariaDB数据库的查询缓存优化第9张
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.00sec)
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数据库的查询缓存优化》仅用于学习参考。如对内容有疑问,请及时联系本站处理。

上篇select2搜索框查询加遍历如何美化windows桌面下篇

宿迁高防,2C2G15M,22元/月;香港BGP,2C5G5M,25元/月 雨云优惠码:MjYwNzM=

相关文章

【笔记】SpringBoot+Shiro 实现简单权限管理(使用mysql数据库)

网上翻了好久 都没有SpringBoot+Shiro的入门教程 原本想看《跟我学Shiro》 然后发现这是从头开始 但是我就需要和SpringBoot整一块 不需要那么多的东西 感觉这个当参考书不错 于是东拼西凑终于整成了 把别人的教程上我用不到的都删了 该改的改 终于拿到了我理想中的效果 先是数据库部分 因为是简单的实现 就没有弄得太复杂 三部分 用户...

小米监控 open-falcon部署

具体详情请参考官方文档  http://book.open-falcon.org/zh_0_2/quick_install/    centos6.8    建议centos7系统  否则后面按照官方文档来是有很多问题的   需要解决Python依赖问题    Python2.7 版本以上,由于centos6.8  pyhton默认版本是 2.6 环境准备...

[mysql] mysqldump 导出数据库表

1.mysqldump的几种常用方法: (1)导出整个数据库(包括数据库中的数据) mysqldump -u username -p dbname > dbname.sql (2)导出数据库结构(不含数据) mysqldump -u username -p -d dbname > dbname.sql (3)导出数据库中的某张数据表(包含...

MySQL 的简单介绍及实施

MySQL原本是一个开放源代码的关系数据库管理系统,原开发者为瑞典的MySQL AB公司,该公司于2008年被Sun公司收购。2009年,甲骨文公司收购Sun公司,MySQL成为Oracle旗下产品。MySQL 是最流行的关系型数据库管理系统(RDBMS)之一。 1. 数据库产品时代演变 第一代数据库架构:合的时代 RDBMS 关系型数据库时代   代...

Linux 安装mysql

一 安装前准备 1、检查是否已经安装过mysql,执行命令 rpm -qa | grep mysql 如果已存在,则执行删除命令 后边为Mysql目录 rpm -e --nodeps mysql-xxxx 2、查询所有Mysql对应的文件夹 whereis mysqlm find / -name mysql 删除相关目录或文件 rm -rf /usr/bi...

mysql事件调度器功能

一、前言 自MySQL5.1.6起,增加了一个非常有特色的功能–事件调度器(Event Scheduler),可以用做定时执行某些特定任务(例如:删除记录、对数据进行汇总等等),来取代原先只能由操作系统的计划任务来执行的工作。更值得 一提的是MySQL的事件调度器可以精确到每秒钟执行一个任务,而操作系统的计划任务(如:Linux下的CRON或Windows...