Skip to content

Commit

Permalink
[New feature] Force to make query cache.
Browse files Browse the repository at this point in the history
Recognize /*FORCE QUERY CACHE*/ SQL statement comment so that any read
only SELECT/with queries are cached. This is opposite to /*NO QUERY
CACHE*/ comment. This feature should be used carefully. See the manual
for more details.

Discussion: #56
  • Loading branch information
tatsuo-ishii committed Sep 28, 2024
1 parent 4ac2f88 commit bdbee93
Show file tree
Hide file tree
Showing 5 changed files with 129 additions and 21 deletions.
87 changes: 75 additions & 12 deletions doc.ja/src/sgml/memcache.sgml
Original file line number Diff line number Diff line change
Expand Up @@ -22,30 +22,93 @@
<note>
<para>
<!--
Basically following SELECTs will not be cached:
First of all if the query starts with SQL comment:
<programlisting>
SELECTs including non immutable functions
SELECTs including temp tables, unlogged tables
SELECT result is too large (memqcache_maxcache)
SELECT FOR SHARE/UPDATE
SELECT starting with "/*NO QUERY CACHE*/" comment
SELECT including system catalogs
SELECT uses TABLESAMPLE
</programlisting>
/*FORCE QUERY CACHE*/
</programlisting>
is checked (case insensitive). If so, the result of the query is
cached unconditionally as long as it is not SELECT or WITH + SELECT.
However you must be very careful to use this feature. For example,
<programlisting>
/*FORCE QUERY CACHE*/SELECT now();
</programlisting>
will return the same timestamp until pgpool restarts, once the
query is cached. The query cache will not be discarded even with a
query:
<programlisting>
/*NO QUERY CACHE*/SELECT now();
</programlisting>
Because it just prevents to create a cache entry for the query, and
does not affect the query using the FORCE QUERY CACHE comment.
</programlisting>
Because it just prevents to create a cache entry for the query, and
does not affect the query using the FORCE QUERY CACHE comment.
-->
まず、クエリが以下のSQLコメントで始まるかどうかがチェックされます(大文字小文字は区別されません)。
<programlisting>
/*FORCE QUERY CACHE*/
</programlisting>
もしこのコメントで始まっているなら、そのクエリがSELECTあるいはWITH + SELECTである限り無条件にキャッシュされます。
しかし、この機能は注意深く使う必要があります。
たとえば、
<programlisting>
/*FORCE QUERY CACHE*/SELECT now();
</programlisting>
このクエリがキャッシュされると、pgpoolが再起動するまで同じタイムスタンプを返し続けます。
このクエリキャッシュは、以下のクエリによってさえも削除されません。
<programlisting>
/*NO QUERY CACHE*/SELECT now();
</programlisting>
なぜなら、これはこのクエリのキャッシュエントリが作成されないようにするだけで、FORCE QUERY CACHEコメントを使ったクエリには影響を与えないからです。
</para>
<para>
<!--
Note that for following query:
<programlisting>
/*FORCE QUERY CACHE*/SELECT * FROM t1;
</programlisting>
usual cache validation due to an update to the table (in this case
t1) works.
-->
次のクエリ
<programlisting>
/*FORCE QUERY CACHE*/SELECT * FROM t1;
</programlisting>
に対しては、テーブル(この場合はt1)の更新によるキャッシュの削除は機能することに注意してください。
</para>
<para>
<!--
If the query does not start with FORCE QUERY CACHE comment,
following checks are performed. If one of followings is satisfied,
SELECT will not be cached.
<programlisting>
SELECT including non immutable functions
SELECT including temp tables, unlogged tables
SELECT including TIMESTAMP WITH TIMEZONE or TIME WITH TIMEZONE
SELECT including CAST to TIMESTAMP WITH TIMEZONE or TIME WITH TIMEZONE
SELECT including SQLValueFunction (CURRENT_TIME, CURRENT_USER etc.)
SELECT result is too large (memqcache_maxcache)
SELECT FOR SHARE/UPDATE
SELECT starting with "/*NO QUERY CACHE*/" comment (case insensitive)
SELECT including system catalogs
SELECT using TABLESAMPLE
SELECT uses row security enabled tables
</programlisting>
However, VIEWs and SELECTs accessing unlogged tables can be
cached by specifying in
the <xref linkend="guc-cache-safe-memqcache-table-list">.
-->
基本的に以下のSELECTはキャッシュされません。
クエリがFORCE QUERY CACHEコメントで始まっていなければ、以下のチェックが行われます。
以下の一つでも該当すれば、SELECTはキャッシュされません。
<programlisting>
immutableでない関数を含むSELECT
一時テーブル、unloggedテーブルを使ったSELECT
TIMESTAMP WITH TIMEZONE、TIME WITH TIMEZONEを返す関数を使っているSELECT
TIMESTAMP WITH TIMEZONE、TIME WITH TIMEZONEへのキャストを含むSELECT
SQLValueFunction (CURRENT_TIME, CURRENT_USERなど)を含むSELECT
一時テーブル、unloggedテーブルを使ったSELECT
検索結果が memqcache_maxcache を越えるようなSELECT
SELECT FOR SHARE/UPDATE
/*NO QUERY CACHE*/コメントで始まるSELECT
/*NO QUERY CACHE*/コメント(大文字小文字は区別されません)で始まるSELECT
システムカタログを使用しているSELECT
TABLESAMPLEを使っているSELECT
行セキュリティが設定されているテーブルを使っているSELECT
Expand Down
46 changes: 38 additions & 8 deletions doc/src/sgml/memcache.sgml
Original file line number Diff line number Diff line change
Expand Up @@ -22,18 +22,48 @@

<note>
<para>
Basically following SELECTs will not be cached:
First of all if the query starts with SQL comment:
<programlisting>
SELECTs including non immutable functions
SELECTs including temp tables, unlogged tables
SELECTs including TIMESTAMP WITH TIMEZONE or TIME WITH TIMEZONE
SELECTs including CAST to TIMESTAMP WITH TIMEZONE or TIME WITH TIMEZONE
SELECTs including SQLValueFunction (CURRENT_TIME, CURRENT_USER etc.)
/*FORCE QUERY CACHE*/
</programlisting>
is checked (case insensitive). If so, the result of the query is
cached unconditionally as long as it is not SELECT or WITH + SELECT.
However you must be very careful to use this feature. For example,
<programlisting>
/*FORCE QUERY CACHE*/SELECT now();
</programlisting>
will return the same timestamp until pgpool restarts, once the
query is cached. The query cache will not be discarded even with a
query:
<programlisting>
/*NO QUERY CACHE*/SELECT now();
</programlisting>
Because it just prevents to create a cache entry for the query, and
does not affect the query using the FORCE QUERY CACHE comment.
</para>
<para>
Note that for following query:
<programlisting>
/*FORCE QUERY CACHE*/SELECT * FROM t1;
</programlisting>
usual cache validation due to an update to the table (in this case
t1) works.
</para>
<para>
If the query does not start with FORCE QUERY CACHE comment,
following checks are performed. If one of followings is satisfied,
SELECT will not be cached.
<programlisting>
SELECT including non immutable functions
SELECT including temp tables, unlogged tables
SELECT including TIMESTAMP WITH TIMEZONE or TIME WITH TIMEZONE
SELECT including CAST to TIMESTAMP WITH TIMEZONE or TIME WITH TIMEZONE
SELECT including SQLValueFunction (CURRENT_TIME, CURRENT_USER etc.)
SELECT result is too large (memqcache_maxcache)
SELECT FOR SHARE/UPDATE
SELECT starting with "/*NO QUERY CACHE*/" comment
SELECT starting with "/*NO QUERY CACHE*/" comment (case insensitive)
SELECT including system catalogs
SELECT uses TABLESAMPLE
SELECT using TABLESAMPLE
SELECT uses row security enabled tables
</programlisting>
However, VIEWs and SELECTs accessing unlogged tables can be
Expand Down
3 changes: 3 additions & 0 deletions src/include/query_cache/pool_memqcache.h
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,9 @@
#include "pool.h"
#include <sys/time.h>

#define FORCE_QUERY_CACHE "/*FORCE QUERY CACHE*/"
#define FORCE_QUERY_CACHE_COMMENT_SZ (sizeof(FORCE_QUERY_CACHE)-1)

#define NO_QUERY_CACHE "/*NO QUERY CACHE*/"
#define NO_QUERY_CACHE_COMMENT_SZ (sizeof(NO_QUERY_CACHE)-1)

Expand Down
8 changes: 7 additions & 1 deletion src/query_cache/pool_memqcache.c
Original file line number Diff line number Diff line change
Expand Up @@ -925,7 +925,13 @@ pool_is_allow_to_cache(Node *node, char *query)
SelectContext ctx;

/*
* If NO QUERY CACHE comment exists, do not cache.
* If FORCE QUERY CACHE comment exists, cache it unconditionally.
*/
if (!strncasecmp(query, FORCE_QUERY_CACHE, FORCE_QUERY_CACHE_COMMENT_SZ))
return true;

/*
* If NO QUERY CACHE comment exists, do not cache unconditionally.
*/
if (!strncasecmp(query, NO_QUERY_CACHE, NO_QUERY_CACHE_COMMENT_SZ))
return false;
Expand Down
6 changes: 6 additions & 0 deletions src/test/regression/tests/006.memqcache/test.sh
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,10 @@ SELECT '2022-07-05 10:00:00'::TIMETZ;
SELECT '2022-07-05 10:00:00'::TIMETZ;
SELECT to_timestamp(0);
SELECT to_timestamp(0);
/*FORCE QUERY CACHE*/SELECT now();
/*FORCE QUERY CACHE*/SELECT now();
/*NO QUERY CACHE*/SELECT 1;
/*NO QUERY CACHE*/SELECT 1;
EOF

success=true
Expand All @@ -110,6 +114,8 @@ EOF
grep "fetched from cache" log/pgpool.log | grep 'TIMESTAMPTZ;' > /dev/null && success=false
grep "fetched from cache" log/pgpool.log | grep 'TIMETZ;' > /dev/null && success=false
grep "fetched from cache" log/pgpool.log | grep 'to_timestamp' > /dev/null && success=false
grep "fetched from cache" log/pgpool.log | grep 'FORCE QUERY CACHE' > /dev/null || success=false
grep "fetched from cache" log/pgpool.log | grep 'NO QUERY CACHE' > /dev/null && success=false

if [ $success = false ];then
./shutdownall
Expand Down

0 comments on commit bdbee93

Please sign in to comment.