MySQL Query Cache导入查询缓慢解决办法

进mysql:SHOW FULL PROCESSLIST;

Command多为Sleep,客户端过来的连接倒也正常,重复执行上述命令发现有些Command的状态为“Coping to tmp table”,果断打开my.cnf发现并无tmp_table_size的设置,MySQL环境是使用yum安装,这也是为什么要编译MySQL的缘故

mysql> SHOW VARIABLES LIKE 'tmp_table_size';
+----------------+----------+
| Variable_name  | Value    |
+----------------+----------+
| tmp_table_size | 16777216 |
+----------------+----------+
1 row in set (0.00 sec)
 
mysql> SHOW VARIABLES LIKE 'max_heap_table_size';
+---------------------+----------+
| Variable_name       | Value    |
+---------------------+----------+
| max_heap_table_size | 16777216 |
+---------------------+----------+
1 row in set (0.00 sec)

这样一看这两个设置的值并不低,看来并不是tmp table导致的问题,不过为了确保没问题,在my.cnf中增加:

tmpdir=/tmp
tmp_table_size=1073741824

重启MySQL,问题依旧。看来设置足够,还是其他的原因。打开下mysql-log,发现被查询的那个表正在不停地插入数据,按照这个网站的Pv数量可以判断有人在频繁使用检索功能,这个功能目前并没有配置sphinx全文索引,而是直接读取数据库,并且会实时统计用户输入的关键词。不过被人为的频繁插入新数据中,会导致mysql query cache在使用过程中不停地重建,也就是这个原因导致了mysqld的CPU使用率居高不下。看来这样实时的排序还是应该交给Memcache或者Redis去执行,并且再次验证GROUP

mysql的query_cache认识的误区

下面我们通过实验及源码具体分析。首先,我们先试验一下:

首先,我们看一下mysql query_cache的状态:

 

首先,我们可以确认,mysql的query_cache功能是打开的。

其次,我们看一下状态:

因为这个db是新的db,所以hits,inset都为0,现在我们执行一条select语句:

状态变为:

可以看到,执行一条select后,现在的qcache状态为,insert+1,这样我们就可以推断出,现在刚才那条select语句已经加入了qcache中。那我们现在再将刚才那条sql前面加上空格,看看会怎样呢?

请注意,这条sql,比刚才那条sql前面多了一个空格。

按照网上的理论,这条sql应该会作为另一个键而插入另一个cache,不会复用先前的cache,但结果呢?

我们可以看到,hits变为了1,而inserts根本没变,这就说明了,这条在前面加了空格的query命中了没有空格的query的结果集。从这,我们就可以得出结论,网上先前流传的说法,是不严谨的。

Query Cache 如何处理子查询的?
这是我遇到的最为常见的一个问题。其实 Query Cache 是以客户端请求提交的 Query 为对象来处理的,只要客户端请求的是一个 Query,无论这个 Query 是一个简单的单表查询还是多表 Join,亦或者是带有子查询的复杂 SQL,都被当作成一个 Query,不会被分拆成多个 Query 来进行 Cache。所以,存在子查询的复杂 Query 也只会产生一个Cache对象,子查询不会产生单独的Cache内容。UNION[ALL] 类型的语句也同样如此。

Query Cache 是以 block 的方式存储的数据块吗?
不是,Query Cache 中缓存的内容仅仅只包含该 Query 所需要的结果数据,是结果集。当然,并不仅仅只是结果数据,还包含与该结果相关的其他信息,比如产生该 Cache 的客户端连接的字符集,数据的字符集,客户端连接的 Default Database等。

Query Cache 为什么效率会非常高,即使所有数据都可以 Cache 进内存的情况下,有些时候也不如使用 Query Cache 的效率高?
Query Cache 的查找,是在 MySQL 接受到客户端请求后在对 Query 进行权限验证之后,SQL 解析之前。也就是说,当 MySQL 接受到客户端的SQL后,仅仅只需要对其进行相应的权限验证后就会通过 Query Cache 来查找结果,甚至都不需要经过 Optimizer 模块进行执行计划的分析优化,更不许要发生任何存储引擎的交互,减少了大量的磁盘 IO 和 CPU 运算,所以效率非常高。

客户端提交的 SQL 语句大小写对 Query Cache 有影响吗?
有,由于 Query Cache 在内存中是以 HASH 结构来进行映射,HASH 算法基础就是组成 SQL 语句的字符,所以必须要整个 SQL 语句在字符级别完全一致,才能在 Query Cache 中命中,即使多一个空格也不行。

一个 SQL 语句在 Query Cache 中的内容,在什么情况下会失效?
为了保证 Query Cache 中的内容与是实际数据绝对一致,当表中的数据有任何变化,包括新增,修改,删除等,都会使所有引用到该表的 SQL 的 Query Cache 失效。

为什么我的系统在开启了 Query Cache 之后整体性能反而下降了?
当开启了 Query Cache 之后,尤其是当我们的 query_cache_type 参数设置为 1 以后,MySQL 会对每个 SELECT 语句都进行 Query Cache 查找,查找操作虽然比较简单,但仍然也是要消耗一些 CPU 运算资源的。而由于 Query Cache 的失效机制的特性,可能由于表上的数据变化比较频繁,大量的 Query Cache 频繁的被失效,所以 Query Cache 的命中率就可能比较低下。所以有些场景下,Query Cache 不仅不能提高效率,反而可能造成负面影响。

如何确认一个系统的 Query Cache 的运行是否健康,命中率如何,设置量是否足够?
MySQL 提供了一系列的 Global Status 来记录 Query Cache 的当前状态,具体如下:

•Qcache_free_blocks:目前还处于空闲状态的 Query Cache 中内存 Block 数目
•Qcache_free_memory:目前还处于空闲状态的 Query Cache 内存总量
•Qcache_hits:Query Cache 命中次数
•Qcache_inserts:向 Query Cache 中插入新的 Query Cache 的次数,也就是没有命中的次数
•Qcache_lowmem_prunes:当 Query Cache 内存容量不够,需要从中删除老的 Query Cache 以给新的 Cache 对象使用的次数
•Qcache_not_cached:没有被 Cache 的 SQL 数,包括无法被 Cache 的 SQL 以及由于 query_cache_type 设置的不会被 Cache 的 SQL
•Qcache_queries_in_cache:目前在 Query Cache 中的 SQL 数量
•Qcache_total_blocks:Query Cache 中总的 Block 数量
可以根据这几个状态计算出 Cache 命中率,计算出 Query Cache 大小设置是否足够,总的来说,我个人不建议将 Query Cache 的大小设置超过256MB,这也是业界比较常用的做法。

MySQL Cluster 是否可以使用 Query Cache?
其实在我们的生产环境中也没有使用 MySQL Cluster,所以我也没有在 MySQL Cluster 环境中使用 Query Cache 的实际经验,只是 MySQL 文档中说明确实可以在 MySQL Cluster 中使用 Query Cache。从 MySQL Cluster 的原理来分析,也觉得应该可以使用,毕竟 SQL 节点和数据节点比较独立,各司其职,只是 Cache 的失效机制会要稍微复杂一点。

时间: 2024-10-27 09:56:32

MySQL Query Cache导入查询缓慢解决办法的相关文章

【转载】MySQL Query Cache 小结

      最近经常有人问我 MySQL Query Cache 相关的问题,就整理一点 MySQL Query Cache 的内容,以供参考.       顾名思义,MySQL Query Cache 就是用来缓存和 Query 相关的数据的.具体来说,Query Cache 缓存了我们客户端提交给 MySQL 的 SELECT 语句以及该语句的结果集.大概来讲,就是将 SELECT 语句和语句的结果做了一个 HASH 映射关系然后保存在一定的内存区域中.       在大部分的 MySQL

Linux下MySQL忘记超级用户口令的解决办法

解决办法一 MySQL忘记超级用户口令的解决办法  如果MySQL正在运行,首先杀之: killall -TERM mysqld. 启动MySQL:  代码如下 复制代码 bin/safe_mysqld --skip-grant-tables & 就可以不需要密码就进入MySQL了 然后就是  代码如下 复制代码 >use mysql >update user set password=password("new_pass") where user="ro

mysql query cache用法与性能详细介绍

mysql Query Cache 默认为打开.从某种程度可以提高查询的效果,但是未必是最优的解决方案,如果有的大量的修改和查询时,由于修改造成的cache失效,会给服务器造成很大的开销,可以通过query_cache_type[0(OFF)1(ON)2(DEMAND)]来控制缓存的开关. 需要注意的是mysql query cache 是对大小写敏感的,因为Query Cache 在内存中是以 HASH 结构来进行映射,HASH 算法基础就是组成 SQL 语句的字符,所以 任何sql语句的改变

linux-fedora安装mysql出现版本冲突有什么解决办法

问题描述 fedora安装mysql出现版本冲突有什么解决办法 在fedora15中用yum安装mysql,可能之前不太懂就把mysql-libs给更新了,然后问题就来了,如下: 错误:Package: mysql-5.5.23-1.fc15.i686 (updates) Requires: mysql-libs(x86-32) = 5.5.23-1.fc15 已安装: mysql-libs-5.5.24-1.fc15.i686 (@updates-testing) mysql-libs(x86

无法启动MYSQL服务”1067 进程意外终止”解决办法

启用MySql服务的时候出现"windows无法启动mysql服务(位于本地计算机上.错误1067:进程意外终止)",看看mysql服务并没有其它的依赖安系啊,于是突然想到进系统日志看看,果然发现很多MySql的很多错误,终于找到问题所在.     在win7的服务器里开启MySql服务提示"windows无法启动mysql服务(位于本地计算机上.错误1067:进程意外终止)" 进入"事件查看器""应用程序"果然发现很多MyS

MySQL忘记root密码的正确解决办法

mysql教程忘记root密码的正确解决办法 介绍的是mysql忘记root密码的正确解决办法,我们大家都知道在实际操作中忘记密码 是令人十分头疼的事情,以下就是针对这一问题给出的正确解决方案,望你在浏览之 后会收获不小. mysql忘记root密码解决办法: 在windows下: 打开命令行窗口,停止mysql服务: net stop mysql 启动mysql,一般到mysql的安装路径,找到 mysqld-nt.exe 来到该目录下: c:program filesmysqlmysql s

phpmyadmin 数据库导入2048kb的解决办法

  1.打开php.ini.找到 upload_max_filesize . memory_limit . post_max_size 这三个参数! (在默认的情况下,php只允许最大的上传数据为2M,也就是2048KB,而极限的最大使用内存memory_limit也仅为128M,Post的最大也为2M) MySQL数据库管理(phpMyAdmin) 官方最新版 2.按您的服务器的实际性能配置进行如下改动:(注意:以下是按我的服务器性能有硬件配置进行的更改..) upload_max_files

mysql Too many connections错误的解决办法

产生这种问题的原因是: 连接数超过了 MySQL 设置的值,与 max_connections 和 wait_timeout  都有关系.wait_timeout 的值越大,连接的空闲等待就越长,这样就会造成当前连接数越大. 解决方法: 修改MySQL配置文件/etc/my.cnf,设置成max_connections=1000,wait_timeout=5.如果没有此项设置可以自行添加,修改后重启MySQL服务即可.要不经常性报此错误,则要对服务器作整体性能优化 补充: 在工作中,大家或许常常

linux下MYSQL常见两个错误的解决办法

ERROR 2002 (HY000): Can't connect to local MySQL server through socket '/var/lib/mysql/mysql.sock' (2) 解决方法: 1)默认的mysql.sock文件是在/tmp目录下.2)我们建立一个软连接,ln -s /tmp/mysql.sock  /var/lib/mysql/mysql.sock 问题2:Timeout error occurred trying to start MySQL Daem