圆形`now()`用于更好的缓存?

时间:2013-11-13 17:38:25

标签: mysql performance datetime caching query-cache

如何最好地将now()的值向下舍入(即“下限”)到最近的小时?

这是为了使query cache能够有效地使用以下语句:

SELECT SQL_CACHE * FROM table WHERE appointment_date >= NOW()

2 个答案:

答案 0 :(得分:1)

除非您在应用程序层中进行舍入,否则不要指望MySQL足够聪明以使用查询缓存。 Any query that includes NOW() (and many other functions) will never be cached.

也就是说,如果你计算了应用程序层中最近的小时,它应该可以正常工作。

答案 1 :(得分:1)

如果您有无法缓存的查询,可以将其拆分为两个更简单的查询。第一个查询将根据不可缓存的函数返回行ID;第二个查询将完成剩下的工作。所以至少第二个查询将被缓存。

使用您的示例,您可以进行两次查询:

  1. SELECT ID FROM表WHERE appointment_date> = NOW();
  2. ...因此您的应用程序将收集ID。如果返回任何ID,请将它们组合为逗号分隔的字符串并运行第二个查询:

    1. SELECT * FROM table WHERE ID IN(“。$ ids。”);“
    2. 当然,您的查询非常简单,但如果您有非常复杂的大型查询,则可以通过编程方式对其进行拆分。例如,您可以使用正则表达式和函数来查明查询是否是不可缓存的,并且值得拆分它。例如,您可以使用以下PHP函数:

      function query_cannot_be_cached($query)
      {
        return preg_match("/\b(?:AES_DECRYPT|AES_ENCRYPT|BENCHMARK|CONNECTION_ID|CONVERT_TZ|CURDATE|CURRENT_DATE|CURRENT_TIME|CURRENT_TIMESTAMP|CURRENT_USER|CURTIME|DATABASE|ENCRYPT|FOUND_ROWS|GET_LOCK|IS_FREE_LOCK|IS_USED_LOCK|LAST_INSERT_ID|LOAD_FILE|MASTER_POS_WAIT|NOW|PASSWORD|RAND|RANDOM_BYTES|RELEASE_ALL_LOCKS|RELEASE_LOCK|SLEEP|SYSDATE|UNIX_TIMESTAMP|USER|UUID|UUID_SHORT)\b *\(/i", $query);
      }
      

      另一种解决方案是避免服务器端比较(Now())并仅使用客户端比较。我们在服务器中使用这种方法。如果查询只返回一些数据,则无法拆分它。但如果它返回大量数据,就像我在下面解释的那样。所以你的查询就是这样:

      • SELECT appointment_date,id FROM table;

      或者您可以设置日期粒度(例如,一个月,一天或一小时)并将其添加到比较中。此粒状日期应由您的软件预先计算,例如:

      • SELECT appointment_date,id FROM table WHERE appointment_date> '2017年5月10日';

      (此'2017-05-10'值应由您的软件计算,每天只更改一次。)

      然后您收到了appointment_date并将其与客户端的当前时间进行比较。如果时间匹配,则运行第二个查询,如上面的示例#2所示。

      当然,这些示例非常简单,我们在服务器中使用了更复杂的查询。