在本教程中,将讲解一个简单的方法来在共享内存中试用“基于内存的查询缓存”。
你需要的是一个安装有 PostgreSQL 和 pgpool-II 的 Linux 测试环境。你可以在任何模式中使用 基于内存的查询缓存:复制模式,主/备模式和原始模式。
设置 "memory_cache_enabled" 为 on 以启用基于内存的查询缓存功能。
# If on, use the memory cache functionality, off by default memory_cache_enabled = on
pgpool 会建立“OID 映射”文件,它用于指明哪个缓存用于哪个数据库和表。指定你希望用于这个用途的目录。
# Temporary work directory to record table oids memqcache_oiddir = '/var/log/pgpool/oiddir'
参数 "memqcache_method" 用于选择缓存的存储类型,默认为 "shmem"。
# Cache storage method. either 'shmem'(shared memory) or 'memcached'. 'shmem' by default memqcache_method = 'shmem'
参数 "log_per_node_statement" 可以帮助你了解某个查询是在哪个后端上执行。设置本参数为 on。
log_per_node_statement = on # Log all statements # with node and backend informations
使用 "-n" 参数(表示以非守护进程模式)启动 pgpool-II 并重定向日志消息到 pgpool.log 中。
$ {installed_dir}/bin/pgpool -n -f {installed_dir}/etc/pgpool.conf > pgpool.log 2>&1
建立数据库和表。
$ createdb -p 9999 test $ psql -p 9999 test test=> CREATE TABLE table_cache_ok (a INT); CREATE TABLE test=> INSERT INTO table_cache_ok VALUES (1), (2), (3); INSERT 0 3 test=> SELECT * FROM table_cache_ok ORDER BY a; a --- 1 2 3 (3 rows)
执行一个 SELECT 语句。
test=> SELECT * FROM table_cache_ok WHERE a = 1; a --- 1 (1 row)
log_per_node_statement 的输出显示 SELECT 语句被实际执行了。
LOG: DB node id: 0 backend pid: 11203 statement: SELECT * FROM table_cache_ok WHERE a = 1;
再次执行相同的 SELECT 语句。
test=> SELECT * FROM table_cache_ok WHERE a = 1; a --- 1 (1 row)
这次日志消息显示 SELECT 语句的结果来源于缓存。
LOG: query result fetched from cache. statement: SELECT * FROM table_cache_ok WHERE a = 1;
当一个表被更新,这个表中缓存的 SELECT 的结果会过期。 pgpool 默认情况下会自动忽略那个表上的所有缓存。
通过 "memqcache_auto_cache_invalidation" 指定动作。它的默认值是 "on"。
# If on, invalidation of query cache is triggered by corresponding # DDL/DML/DCL(and memqcache_expire). If off, it is only triggered # by memqcache_expire. on by default. memqcache_auto_cache_invalidation = on
修改这个参数的值后,重启 pgpool。
确认你可以从缓存中获得 SELECT 语句的结果。
test=> SELECT * FROM table_cache_ok WHERE a = 1; LOG: query result fetched from cache. statement: SELECT * FROM table_cache_ok WHERE a = 1;
在这个表中执行 INSERT INTO 。
test=> INSERT INTO table_cache_ok VALUES (5); INSERT 0 1
再次执行相同的 SELECT 语句,这条 SELECT 语句被实际执行。
test=> SELECT * FROM table_cache_ok WHERE a = 1; LOG: DB node id: 0 backend pid: 11203 statement: SELECT * FROM table_cache_ok WHERE a = 1;
pgpool 会忽略比指定过期周期更旧的缓存。
通过 "memqcache_expire" 指定过期周期。默认为 0 秒,不过为了测试我们在这里设置为 5 秒。
# Memory cache entry life time specified in seconds. # 0 means infinite life time. 0 by default. memqcache_expire = 5
修改这个参数的值后,重启 pgpool。
确认你可以从缓存中获得 SELECT 语句的结果。
test=> SELECT * FROM table_cache_ok WHERE a = 1; LOG: query result fetched from cache. statement: SELECT * FROM table_cache_ok WHERE a = 1;
等 5 秒钟...
再次执行相同的 SELECT 语句,这条 SELECT 语句被实际执行。
test=> SELECT * FROM table_cache_ok WHERE a = 1; LOG: DB node id: 0 backend pid: 11203 statement: SELECT * FROM table_cache_ok WHERE a = 1;
如果你只想缓存某些表的结果,可以通过 "white_memqcache_table_list" 指定。
可以使用正则表达式(会自动添加 ^ 和 $)。
white_memqcache_table_list = '.*_cache_ok' # Comma separated list of table names to memcache # that don't write to database # Regexp are accepted
修改这个参数的值后,重新加载配置文件。
$ {installed_dir}/bin/pgpool reload
建立一个不需要缓存的表
$ psql -p 9999 test test=> CREATE TABLE table_cache_ng (a INT); CREATE TABLE test=> INSERT INTO table_cache_ng VALUES (1), (2), (3); INSERT 0 3
确认是否 SELECT FROM 在 white_memqcache_table_list 中的表被缓存。
test=> SELECT * FROM table_cache_ok WHERE a = 1; LOG: DB node id: 0 backend pid: 11203 statement: SELECT oid FROM pg_database WHERE datname = 'test' test=> SELECT * FROM table_cache_ok WHERE a = 1; LOG: query result fetched from cache. statement: SELECT * FROM table_cache_ok WHERE a = 1;
确认是否 SELECT FROM 不在 white_memqcache_table_list 中的表不被缓存。
test=> SELECT * FROM table_cache_ng WHERE a = 1; LOG: DB node id: 0 backend pid: 11203 statement: SELECT * FROM table_cache_ok WHERE a = 1; test=> SELECT * FROM table_cache_ng WHERE a = 1; LOG: DB node id: 0 backend pid: 11203 statement: SELECT * FROM table_cache_ok WHERE a = 1;
如果你不想缓存某些表的结果,可以通过 "black_memqcache_table_list" 指定。
可以使用正则表达式(会自动添加 ^ 和 $)。
black_memqcache_table_list = '.*_cache_ng' # Comma separated list of table names not to memcache # that don't write to database # Regexp are accepted
修改这个参数的值后,重新加载配置文件。
$ {installed_dir}/bin/pgpool reload
确认是否 SELECT FROM 在 black_memqcache_table_list 中的表不被缓存。
test=> SELECT * FROM table_cache_ng WHERE a = 1; LOG: DB node id: 0 backend pid: 11203 statement: SELECT * FROM table_cache_ok WHERE a = 1; test=> SELECT * FROM table_cache_ng WHERE a = 1; LOG: DB node id: 0 backend pid: 11203 statement: SELECT * FROM table_cache_ok WHERE a = 1;
确认是否 SELECT FROM 不在 black_memqcache_table_list 中的表被缓存。
test=> SELECT * FROM table_cache_ok WHERE a = 1; LOG: DB node id: 0 backend pid: 11203 statement: SELECT oid FROM pg_database WHERE datname = 'test' test=> SELECT * FROM table_cache_ok WHERE a = 1; LOG: query result fetched from cache. statement: SELECT * FROM table_cache_ok WHERE a = 1;
SELECT 的结果集的大小会受限于 "memqcache_maxcache"。
# Maximum SELECT result size in bytes. # Must be smaller than memqcache_cache_block_size. Defaults to 400KB. memqcache_maxcache = 409600
如果结果集大于 memqcache_maxcache,日志信息会告诉我们。 以下是一个示例,memqcache_maxcache 被设置为 1024 字节而 SELECT 出来的表的大小超过 10 MB。
LOG: DB node id: 0 backend pid: 17749 statement: SELECT * FROM pgbench_accounts ; LOG: pool_add_temp_query_cache: data size exceeds memqcache_maxcache. current:983 requested:110 memq_maxcache:1024
如果白名单和黑名单还不够用,可以在查询最开始的地方 put the text "/* NO QUERY CACHE */" at the head of the queries.
LOG: statement: SELECT * FROM table_cache_ok WHERE a = 1; LOG: query result fetched from cache. statement: SELECT * FROM table_cache_ok WHERE a = 1; LOG: statement: /* NO QUERY CACHE */ SELECT * FROM table_cache_ok WHERE a = 1; LOG: DB node id: 0 backend pid: 18070 statement: /* NO QUERY CACHE */ SELECT * FROM table_cache_ok WHERE a = 1; LOG: statement: /* NO QUERY CACHE */ SELECT * FROM table_cache_ok WHERE a = 1; LOG: DB node id: 0 backend pid: 18070 statement: /* NO QUERY CACHE */ SELECT * FROM table_cache_ok WHERE a = 1;
当然,这种方法需要修改你的程序。