查询缓存
功能描述
Vastbase支持查询缓存功能,此功能实现了查询数据结果集的缓存功能,提升了同一个语句多次查询,且结果集相同时的性能。适用于读多写少的场景中,其通过减少访问磁盘、减少计算的方式来提升数据库响应查询的性能。
查询缓存不返回陈旧数据,可正常缓存查询结果集。为了保证查询的数据是最新的,一旦缓存的结果集发生变化,查询缓存会被刷出内存。
查询缓存存储SELECT命令以及发送到客户端的相应结果。如果以后收到相同的语句,服务器将从查询缓存中检索结果,而不是再次解析和执行该语句。查询缓存在会话之间共享,因此可以发送一个客户端生成的结果集,以响应另一个客户端发出的相同查询。
只有纳入查询语句判断的参数值相同且查询树相同的查询语句才会被认为是同一条语句。其中纳入查询语句判断的参数列表详见查询语句相同判断。
从Build 14版本开始,集群主节点和备节点都支持查询缓存功能。用户可以在主节点和备节点上单独开启或关闭此功能,且主备节点之间的查询缓存没有关联,主备机间不会进行缓存的同步。落在主机上的查询只能使用主机上的缓存(若主机无缓存则建立在主机上的缓存)。备机同理。
由于DDL/DML操作只能落在主节点上,所以主机上的DDL/DML操作会同步使得备节点上的相应查询缓存失效。
注意事项
开启查询缓存后,查询缓存功能不可关闭,只有在关闭参数后重启数据库才可以关闭整个功能。
功能是否正确开启可以通过查询系统视图
select * from pg_catalog.vb_result_cache_items;
如果正常返回结果,没有出现报错信息,说明缓存功能已经正常开启。也可以通过vb_result_cache_status函数结果为enable看出。
查询缓存功能支持PBE协议进入到server的查询,支持JDBC中使用prepared Statement的方式构建带有参数的查询语句。
仅当SQL的查询树相同且参数值、参数个数、参数类型都相同时,才会被认为是相同的SQL语句。
使用PBE协议作为入口构建查询缓存时,必须要求此计划是有效的才能构建缓存,或者使用缓存,否则本次不能使用查询缓存,待计划有效时,才会产生缓存的构建或者使用操作。
PBE和SimpleQuery协议共用同一个查询缓存结构对象,但是不会因为sql语句一样就会互相命中,这是因为他们的查询树结构不同。所以通过PBE协议产生的查询缓存结果和SimpleQuery协议产生的缓存结果不会互相访问。
若查询中使用白名单功能,则用到的表必须满足白名单限制。
若使用查询缓存功能,必须满足各参数的约束,SQL语句的结果集不能超过参数阈值。
查询缓存是全局的,即整个数据库对象持有同一个缓存对象,所有连接访问的缓存内容相同。
前提条件
开启查询缓存要求满足如下参数条件:
enable_global_result_cache取值为true。
result_cache_max_size取值大于0。
result_cache_max_result取值大于0。
通过Hint,可以在查询缓存的使用中更加灵活。
Vastbase G100 V2.2 Build 13及以后支持的Hint如下:
Hint 描述 result_cache 语句是否新建或使用查询缓存。 no_result_cache 语句是否不新建或不使用查询缓存 当查询缓存对应的参数正确配置时,Hint的内容与result_cache_mode参数配置共同作用下是否可以使用查询缓存。
- 在单机使用查询缓存功能时,协同关系可以见表1。
在主备架构中使用查询缓存功能时,有如下情况:
主机开启查询缓存功能时,主机的result_cache_mode不支持设置为AUXILIARY。主机和备机的result_cache_mode取值与Hint的协同关系可见表1(若备机无查询缓存需要,备机也可不开启查询缓存功能)。
主机关闭查询缓存功能,则只有当主机的result_cache_mode设置为AUXILIARY,备机才可以单独启用查询缓存功能,此时备机的result_cache_mode取值与Hint的协同关系可见表1。
result_cache_mode取值 Hint 是否使用或新建缓存 Manual 无Hint 否 result_cache 是 no_result_cache 否 Force 无Hint 是 result_cache 是 no_result_cache 否
使用查询缓存的语句,除了满足上述参数和Hint的要求外,还应满足内容的限制要求。对于一条sql语句,若:
为非查询语句,则不能使用查询缓存。
包含存储过程、自定义函数、触发器等PL/pgSQL范畴内的查询语句,则不能使用查询缓存。
查询语句中使用的所有函数包含非最稳定(immuitable)函数,则不能使用查询缓存。
在查询语句中使用了自定义函数,则不能使用查询缓存。
影响结果集的GUC参数在构建缓存和使用缓存时不同,则不能使用查询缓存。例如behavior_compat_options的变更。
包含可能的collation、locate变更,则不能使用查询缓存。
查询语句中使用了非行存表、系统表、临时表,则不能使用查询缓存。
使用到了视图、物化视图,则不能使用查询缓存。
涉及表的个数超过了result_cache_max_tables,则不能使用查询缓存。
查询语句在事务中,则其父事务的其他子事务中不能存在DDL/DML操作,否则不能使用查询缓存。如:
begin; insert into table xxx; select * from table; commit;
存在缓存白名单,但使用的表不在白名单列表中,则不能使用查询缓存。
默认事务的隔离级别不是ReadCommited,且当前不是ReadCommited,则不能使用查询缓存。
查询中没有使用到表,则不能使用查询缓存。
开启了行级别安全策略,则不能使用查询缓存。
如果查询中有虚拟列、系统列、序列、CTE、用户自定义变量,则不能使用查询缓存。
生成缓存记录
生成一条查询缓存的记录可通过以下方式查看:
explain查看计划。
首次执行查询时,explain中若看到
ResultCache on Enter
的节点,即可认为缓存可以存入。但是具体是否已经存入,还是需要通过系统函数或系统视图确认。通过函数vb_result_cache_items查看记录。
通过系统视图vb_result_cache_items查看记录。
select * from pg_catalog.vb_result_cache_items;
缓存记录失效
缓存记录失效有以下四种情况:
缓存占满配置空间时,需要释放最久没用过的缓存记录。
调用用户接口函数vb_result_cache_flush。该接口为系统函数,可以令所有缓存失效,正在使用的缓存不会受到影响,使用完后会自动失效。
调用用户接口函数vb_result_cache_invalidate。该函数可令cache_id对应的相应缓存失效。sql语句对应的cache_id可通过vb_result_cache_items接口查到。
DML或DDL语句产生表数据、表结构变更:
当前查询缓存,所有dml操作都会在真正提交前令缓存失效。dml操作包括增、删、改。
目前被认为不会影响缓存使用的DDL语句有如下:
ALTER COLUMN DEFAULT ALTER COLUMN DROP NOT NULL ALTER COLUMN SET NOT NUL ALTER COLUMN SET STATISTICS ADD STATISTICS DELETE STATISTICS ALTER COLUMN SET ( options ) ALTER COLUMN RESET ( options ) ALTER COLUMN SET ( options ) ALTER COLUMN RESET ( options ) ALTER COLUMN SET STORAGE ADD PARTITION ADD SUBPARTITION ADD INDEX READD INDEX ADD CONSTRAINT ADD CONSTRAINT WITH RECURSION ADD CONSTRAINT USING INDEX READD CONSTRAINT VALIDATE CONSTRAINT VALIDATE CONSTRAINT with recursion DROP CONSTRAINT DROP CONSTRAINT with recursion ALTER ENABLE CONSTRAINT ALTER TABLE ENABLE ROW MOVEMENT ALTER TABLE DISABLE ROW MOVEMENT ALTER TABLE SET AUTO INCREMENT ALTER TABLE ADD TABLE OF ALTER TABLE DROP TABLE OF ALTER TABLE ADD COMMENTS ALTER TABLE DROP COMMENTS ALTER TABLE SET COMPRESS
查询语句相同判断
纳入判断的GUC参数值相同且查询树相同的查询语句才会被认为是同一条语句,具体情况如下:
查询树判断
不是一个查询语句中的所有信息都会纳入到查询树的比较中,例如仅仅hint不同的两个语句就不会被认为是两条语句。
参与比较的查询树是否相同的内容为:
查询语句使用到的所有表。
查询语句的各个部分使用的表达式。
各个表达式的类型和值。
语句法的位置(是否是顶层查询)。
参数判断的列表
当前纳入查询语句相同判断的GUC参数列表如下:
standard_conforming_strings extra_float_digits Transform_null_equals div_precision_increment DateStyle IntervalStyle TimeZone timezone_abbreviations lc_messages lc_monetary lc_numeric lc_time ignore_checksum_failure zero_damaged_pages hll_default_expthresh hll_default_log2explicit hll_default_log2m hll_default_log2sparse hll_default_regwidth hll_default_sparseon hll_duplicate_check hll_max_sparse bytea_output default_transaction_isolation default_transaction_deferrable xmlbinary xmloption transaction_isolation default_transaction_deferrable enable_compress_hll nls_date_format behavior_compat_options nls_timestamp_format
示例
前置步骤
1、设置GUC参数。
alter system set enable_global_result_cache to on;
alter system set result_cache_max_size to 409600000;
alter system set result_cache_max_result to 10;
2、重启数据库。
vb_ctl restart
修改以上三个GUC参数后需要重启数据库。
示例1 表中没有数据,生成查询缓存后调用函数查看内存使用情况。
1、创建测试表。
create table test1(id int,name varchar(20));
2、生成查询缓存。
select /*+ result_cache */ * from test1 ; explain (costs off) select /*+ result_cache */ * from test1;
结果显示为如下:
id | name ----+------ (0 rows) QUERY PLAN ------------------------- ResultCache on Query -> Seq Scan on test1 (2 rows)
3、查询缓存。
select * from vb_result_cache_memory_report;
结果显示为如下:
TotalMemory | UsedMemory | ElementCount | MaxResultSize -------------+------------+--------------+--------------- 409600000 | 0 | 1 | 0 (1 row)
示例2 在MySQL兼容模式下给表字段添加注释,查询缓存不会失效。
1、创建兼容模式为MySQL的库db_mysql,并进入。
create database db_mysql dbcompatibility='B'; \c db_mysql;
2、创建创建测试表。
CREATE TABLE products ( id SERIAL PRIMARY KEY, name TEXT, price NUMERIC(10,2) COMMENT 'the price of the product' ); insert into products values(1,'aa',3.1);
3、生成查询缓存。
select /*+ result_cache */ * FROM products; explain (costs off) select /*+ result_cache */ * from products;
结果显示为如下:
id | name | price ----+------+------- 1 | aa | 3.1 (1 row) QUERY PLAN ---------------------------- ResultCache on Query -> Seq Scan on products (2 rows)
4、执行语句。
COMMENT ON TABLE products IS 'table containing all available products'; COMMENT ON COLUMN products.id IS 'unique identifier for each product'; COMMENT ON COLUMN products.name IS 'name of the product';
5、查看查询缓存是否失效。
explain (costs off) select /*+ result_cache */ * from products; select * from pg_catalog.vb_result_cache_items(); select * from vb_result_cache_memory_report;
结果显示为如下,查询缓存不会失效:
QUERY PLAN ---------------------------- ResultCache on Query -> Seq Scan on products (2 rows) cache_id | query_string | ref_count ----------+-----------------------------------------------+----------- 1 | select /*+ result_cache */ * from test1 ; | 2 2 | select /*+ result_cache */ * FROM products; | 2 (2 rows) TotalMemory | UsedMemory | ElementCount | MaxResultSize -------------+------------+--------------+--------------- 409600000 | 30 | 2 | 30 (1 row)
示例3 当查询位于事务中,且有其他DML操作时,查询缓存生成失败。
1、创建测试表并插入数据。
CREATE TABLE employees ( id NUMBER, name VARCHAR2(100), salary NUMBER, row_id ROWID ); INSERT INTO employees (id, name, salary) VALUES (1, 'Alice', 5000); INSERT INTO employees (id, name, salary) VALUES (2, 'Bob', 6000);
2、查看当前已有缓存。
本步骤是为了对比生成查询缓存前后的状态。
若用户环境中的当前已有缓存已失效或确定可清理时,可以执行如下语句清理已有缓存:
select vb_result_cache_flush();
select * from pg_catalog.vb_result_cache_items(); select * from vb_result_cache_memory_report;
3、执行带有DML语句的事务。
begin; INSERT INTO employees (id, name, salary) VALUES (3, 'Charlie', 7000); explain (costs off) select /*+ result_cache */ * from employees; commit;
结果显示为如下:
QUERY PLAN ----------------------- Seq Scan on employees (1 row)
4、查看系统函数。
select * from pg_catalog.vb_result_cache_items(); select * from vb_result_cache_memory_report;
结果显示为如下,即生成查询缓存失败。
本步骤查询结果为执行了清理缓存函数vb_result_cache_flush()后的结果。
若用户未执行清理缓存,则本结果应与步骤2的返回结果一致。
cache_id | query_string | ref_count ----------+-----------------------------------------------+----------- (0 rows) TotalMemory | UsedMemory | ElementCount | MaxResultSize -------------+------------+--------------+--------------- 409600000 | 0 | 0 | 0 (1 row)
相关链接