SQL_NO_CACHE不起作用

Koe*_*err 30 mysql sql

我第一次运行这个sql,需要39秒,当我再次运行并增加SQL_NO_CACHE时,似乎没有生效:

mysql> select count(*) from `deal_expired` where `site`=8&&`area`=122 && 
endtime<1310444996056;
+----------+
| count(*) |
+----------+
|      497 |
+----------+
1 row in set (39.55 sec)

mysql> select SQL_NO_CACHE count(*) from `deal_expired` where `site`=8&&`area`=
122 && endtime<1310444996056;
+----------+
| count(*) |
+----------+
|      497 |
+----------+
1 row in set (0.16 sec)
Run Code Online (Sandbox Code Playgroud)

在这里尝试了各种方法

甚至重启mysql服务器或更改表名,但我还是不能让39秒运行这个SQL

我替换了另一个SQL,并在SQL_NO_CACHE上第一次运行增加,问题是一样的:

mysql> select SQL_NO_CACHE count(*) from `deal_expired` where `site`=25&&`area`=
134 && endtime<1310483196227;
+----------+
| count(*) |
+----------+
|      315 |
+----------+
1 row in set (2.17 sec)

mysql> select SQL_NO_CACHE count(*) from `deal_expired` where `site`=25&&`area`=
134 && endtime<1310483196227;
+----------+
| count(*) |
+----------+
|      315 |
+----------+
1 row in set (0.01 sec)
Run Code Online (Sandbox Code Playgroud)

是什么原因?如何获得相同的SQL运行时?

我想找到一种方法来优化这个SQL以执行39秒

顺便说一句:RESET QUERY CACHE FLUSH QUERY CACHE FLUSH TABLES SET SESSION query_cache_type=off不行

mysql状态缓存已关闭:

mysql> SHOW STATUS LIKE "Qcache%";
+-------------------------+-------+
| Variable_name           | Value |
+-------------------------+-------+
| Qcache_free_blocks      | 0     |
| Qcache_free_memory      | 0     |
| Qcache_hits             | 0     |
| Qcache_inserts          | 0     |
| Qcache_lowmem_prunes    | 0     |
| Qcache_not_cached       | 0     |
| Qcache_queries_in_cache | 0     |
| Qcache_total_blocks     | 0     |
+-------------------------+-------+
8 rows in set (0.04 sec)

mysql> select count(*) from `deal_expired` where `site`=25&&`area`=134 && endtime<1310
483196227;
+----------+
| count(*) |
+----------+
|      315 |
+----------+
1 row in set (0.01 sec)

mysql> SHOW STATUS LIKE "Qcache%";
+-------------------------+-------+
| Variable_name           | Value |
+-------------------------+-------+
| Qcache_free_blocks      | 0     |
| Qcache_free_memory      | 0     |
| Qcache_hits             | 0     |
| Qcache_inserts          | 0     |
| Qcache_lowmem_prunes    | 0     |
| Qcache_not_cached       | 0     |
| Qcache_queries_in_cache | 0     |
| Qcache_total_blocks     | 0     |
+-------------------------+-------+
8 rows in set (0.00 sec)
Run Code Online (Sandbox Code Playgroud)

解释这个SQL,使用site + endtime复合索引(名为site_endtime):

mysql> explain select count(*) from `deal_expired` where `site`=8&&`area`=122 && endti
me<1310444996056;
+--------+------+-------------------------------+--------------+---------+------
-+------+-------------+
| table  | type | possible_keys                 | key          | key_len | ref
 | rows | Extra       |
+--------+------+-------------------------------+--------------+---------+------
-+------+-------------+
| deal_expired | ref  | name,url,endtime,site_endtime | site_endtime |       4 | const
 |  353 | Using where |
+--------+------+-------------------------------+--------------+---------+------
-+------+-------------+
1 row in set (0.00 sec)
Run Code Online (Sandbox Code Playgroud)

Wil*_*ine 40

第一个查询应该使用SQL_NO_CACHE告诉MySQL不要将结果放入缓存中.第二个查询使用缓存并告诉MySQL不要缓存该查询的结果,该查询不执行任何操作.

tl; dr - 撤消您的查询.

  • 我不明白为什么没有选择这个正确答案.它应该是. (7认同)
  • 根据[MySQL docs](http://dev.mysql.com/doc/refman/5.6/en/query-cache-in-select.html),第二个SELECT上的SQL_NO_CACHE`应该跳过检查查询缓存,所以上面不应该需要:"服务器不使用查询缓存.它既不检查查询缓存,也不检查结果是否已缓存,也不缓存查询结果." (6认同)
  • **这个答案不正确**,因为带有`SQL_NO_CACHE`的查询也永远不能与查询缓存的响应一起提供.在运行SQL解析器之前,使用查询的*exact bytes*来检查查询缓存*以进行匹配.除非对由完全相同的字节组成的查询的响应已经在缓存中,否则不可能使用...并且因为来自带有`SQL_NO_CACHE`的查询的结果永远不会被写入查询缓存,它可以永远不会从缓存中提供服务.因此,"SQL_NO_CACHE"保证表现为OP期望,从不提供来自缓存的响应. (3认同)

Vla*_*oub 13

"如何获得相同的SQL运行时?"的答案.是 - 你不能.如果您的查询读取某些行,则它们将被缓存,具体取决于所使用的存储引擎,这些行位于OS缓存(myisam)或缓冲池(innodb)中.如果缓存行,则第二次运行相同的查询要快得多,因为MySQL不必从磁盘读取.

  • 在Linux上,您还可以执行`echo 3>/proc/sys/vm/drop_caches`来清除操作系统缓存. (3认同)
  • SQL_NO_CACHE告诉MySQL不要将结果放入缓存中.因此,只有在首次执行特定查询时使用SQL_NO_CACHE才能获得预期的结果.所以Mysql永远不会在缓存中找到结果 (3认同)
  • 通常,“优化”意味着运行得更快 :) 我没有看到很多人要求一种运行得更慢的方法。如果你使用的是 MyISAM,你可能不走运,但如果在 Linux 上使用 Innodb innodb_flush_method=O_DIRECT 应该避免在文件系统中缓存。 (2认同)

小智 7

我的印象是,包含在当前运行时计算的任何类型的SQL函数都不会缓存.你有没有试过像下面这样的事情?

select count(*), now() from `deal_expired` where `site`=8&&`area`=122 && endtime<1310444996056;
Run Code Online (Sandbox Code Playgroud)