VastbaseG100

基于openGauss内核开发的企业级关系型数据库。

Menu

查询缓存

功能描述

Vastbase支持查询缓存功能,此功能实现了查询数据结果集的缓存功能,提升了同一个语句多次查询,且结果集相同时的性能。适用于读多写少的场景中,其通过减少访问磁盘、减少计算的方式来提升数据库响应查询的性能。

查询缓存不返回陈旧数据,可正常缓存查询结果集。为了保证查询的数据是最新的,一旦缓存的结果集发生变化,查询缓存会被刷出内存。

查询缓存存储SELECT命令以及发送到客户端的相应结果。如果以后收到相同的语句,服务器将从查询缓存中检索结果,而不是再次解析和执行该语句。查询缓存在会话之间共享,因此可以发送一个客户端生成的结果集,以响应另一个客户端发出的相同查询。

只有纳入查询语句判断的参数值相同且查询树相同的查询语句才会被认为是同一条语句。其中纳入查询语句判断的参数列表详见查询语句相同判断

注意事项

  • 开启查询缓存后,查询缓存功能不可关闭,只有在关闭参数后重启才可以关闭整个功能。

    • 功能是否正确开启可以通过查询系统视图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语句的结果集不能超过参数阈值。

  • 查询缓存是全局的,即整个数据库对象持有同一个缓存对象,所有连接访问的缓存内容相同。

  • 查询缓存的使用有很多限制,只有满足限制条件的语句可以使用查询缓存。包括GUC参数条件HINT条件语句内容限制条件

前提条件

GUC参数条件

开启查询缓存要求满足如下参数条件:

HINT条件

通过Hint,可以在查询缓存的使用中更加灵活。

  • Vastbase G100 Build 13支持的Hint如下:

    Hint 描述
    result_cache 语句是否新建或使用查询缓存。
    no_result_cache 语句是否不新建或不使用查询缓存
  • 当查询缓存对应的参数正确配置时,Hint的内容与result_cache_mode参数配置共同作用下是否可以使用查询缓存。协同关系可以见下表:

    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中若看到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)

相关链接

GUC参数变更说明查询缓存函数