SelectDB Cloud
开发指南
数据存储
数据缓存

数据缓存

概述

SelectDB 的数据是放在远端存储上的,为了加速对数据的访问,实现了一个基于本地硬盘的缓存。缓存提供了两种管理策略: LRU 策略 和 TTL 策略,对索引相关的数据做了优化,让缓存尽可能 cache 住用户常用的数据。在多 cluster (计算集群)的应用场景,SelectDB 还提供了缓存预热功能。当新建一个集群的时候,用户可以让新 cluster 对指定的数据(表或 partition )进行预热,以便提高查询效率。

缓存空间管理

缓存数据

数据进入缓存主要有三种方式。

  1. 导入。新导入的数据会异步写到缓存中以加速第一次访问。
  2. 查询。如果判断查询的数据不在缓存,会从远端存储读取到内存,并会写到缓存中,以便下一次查询。
  3. 主动预热。尽管远端存储的数据可以多集群共享,但缓存并不会共享。当新建一个集群的时候,此时的缓存是空的,这时候可以通过主动去预热,让集群快速地从远端存储拉取想要的数据在本地缓存中。

缓存淘汰

缓存同时支持 LRU 和 TTL 两种策略。

  1. LRU 是缓存的默认策略,缓存会对该策略的数据维护一个队列,当访问队列中的某一块数据的时候,会把对应的数据移动到 LRU 队列的队首。如果有新写入缓存的数据,也会放在队首,避免过早被淘汰。当数据满的时候,会优先淘汰队列尾部的数据。
  2. TTL 策略主要用来确保新导入的数据在缓存中的一段时间内不被淘汰(过期时间是由导入时间 + 超时时间来计算的得出)。TTL 的数据的地位是最高且平等的。最高指当缓存满的时候,会通过淘汰 LRU 队列的数据,来让 TTL 的数据写进缓存中。平等是指所有 TTL 策略的数据并不会因为过期时间有差别而进行淘汰。当 TTL 的数据占满了缓存,之后的新导入的数据(无论有没有设置 TTL )或者从远端存储拉取下来的冷数据,都不会被写进缓存。
  3. TTL 策略可以用在希望常驻本地的小表。对于常驻表,可以设置一个比较大的 TTL 值来让它在缓存里的数据不会被其他大表的查询淘汰掉。或者对于动态 partition 的表,可以根据 partition 的 hot partition 的时间,设置对应的 TTL 值,来让 hot partition 不会被 cold partition 的查询淘汰掉。目前暂不支持查看 TTL 数据在缓存的占比。

缓存预热

SelectDB 提供多集群的能力,多个集群共享同一份数据,但不会共享同一份缓存。当创建新的 cluster 的时候,在新的 cluster 的缓存是空的,这时候进行查询数据,会比较慢。这时候可以通过手段预热数据,主动从远端存储的数据拉起到本地缓存。 目前支持三种模式:

  • 指定集群 A 的缓存预热到集群 B 。在 SelectDB 中,会定期采集每个集群一段时间内访问过的表或者分区的热点信息,然后作为内部表存储下来。当进行集群间的预热的时候,预热集群会根据源集群的热点信息来对某些表/分区进行预热。
  • 指定表 A 数据预热到新集群 。
  • 指定表 A 的分区 'p1' 的数据预热到新集群。

使用方法

设置 TTL 策略

在建表的时候设置对应的 PROPERTY,即可该表的数据使用 TTL 策略缓存下来。

  • file_cache_ttl_seconds : 新导入的数据期望在缓存中保持的时间,单位是秒。
# 设置TTL的例子,通过建表时指定对应 property
CREATE TABLE IF NOT EXISTS customer (
  C_CUSTKEY     INTEGER NOT NULL,
  C_NAME        VARCHAR(25) NOT NULL,
  C_ADDRESS     VARCHAR(40) NOT NULL,
  C_NATIONKEY   INTEGER NOT NULL,
  C_PHONE       CHAR(15) NOT NULL,
  C_ACCTBAL     DECIMAL(15,2)   NOT NULL,
  C_MKTSEGMENT  CHAR(10) NOT NULL,
  C_COMMENT     VARCHAR(117) NOT NULL
)
DUPLICATE KEY(C_CUSTKEY, C_NAME)
DISTRIBUTED BY HASH(C_CUSTKEY) BUCKETS 32
PROPERTIES(
    "file_cache_ttl_seconds"="300"
)

对于上面那张表,该表所有新导入的数据都会在缓存中被保留300s。目前也支持修改表的 TTL 时间,可以将 TTL 的时间延长或减短。注:修改的值目前暂时不会立刻生效,会有一定时间的延迟。

ALTER TABLE customer set ("file_cache_ttl_seconds"="3000");

如果建表的时候没有设置 TTL ,也可以通过 ALTER 语句进行修改。

缓存预热

目前支持三种模式:

  • 指定 cluster_name0 的缓存预热到 cluster_name1 。 查看当前warehouse下所有cluster的最频繁访问的表。
show cache hotspot '/';
+------------------------+-----------------------+----------------------------------------+
| cluster_name           | total_file_cache_size | top_table_name                         |
+------------------------+-----------------------+----------------------------------------+
| cluster_name0          |          751620511367 | regression_test.selectdb_cache_hotspot |
+------------------------+-----------------------+----------------------------------------+

查看 cluster_name0 下的所有 table 的最热 partition 信息

mysql> show cache hotspot '/cluster_name0';
+-----------------------------------------------------------+---------------------+--------------------+
| table_name                                                | last_access_time    | top_partition_name |
+-----------------------------------------------------------+---------------------+--------------------+
| regression_test.selectdb_cache_hotspot                    | 2023-05-29 12:38:02 | p20230529          |
| regression_test_cloud_load_copy_into_tpch_sf1_p1.customer | 2023-06-06 10:56:12 | customer           |
| regression_test_cloud_load_copy_into_tpch_sf1_p1.nation   | 2023-06-06 10:56:12 | nation             |
| regression_test_cloud_load_copy_into_tpch_sf1_p1.orders   | 2023-06-06 10:56:12 | orders             |
| regression_test_cloud_load_copy_into_tpch_sf1_p1.part     | 2023-06-06 10:56:12 | part               |
| regression_test_cloud_load_copy_into_tpch_sf1_p1.partsupp | 2023-06-06 10:56:12 | partsupp           |
| regression_test_cloud_load_copy_into_tpch_sf1_p1.region   | 2023-06-06 10:56:12 | region             |
| regression_test_cloud_load_copy_into_tpch_sf1_p1.supplier | 2023-06-06 10:56:12 | supplier           |
+-----------------------------------------------------------+---------------------+--------------------+

查看 cluster_name0 下的 table regression_test_cloud_load_copy_into_tpch_sf1_p1.customer 的信息

show cache hotspot '/cluster_name0/regression_test_cloud_load_copy_into_tpch_sf1_p1.customer';
+----------------+---------------------+
| partition_name | last_access_time    |
+----------------+---------------------+
| supplier       | 2023-06-06 10:56:12 |
+----------------+---------------------+

当执行下面这条 SQL,cluster_name1 集群会获取到 cluster_name0 集群的访问信息,来尽可能还原出与 cluster_name0 集群一样的缓存。

warm up cluster cluster_name1 with cluster cluster_name0
  • 指定 customer 数据预热到 cluster_name1。执行下面的 SQL ,可以把该表在远端存储上的数据全拉取到本地。
warm up cluster cluster_name1 with table customer
  • 指定 customer 的 partition 'p1' 的数据预热到 cluster_name1。执行下面的 SQL ,可以把该分区在远端存储上的数据全拉取到本地。
warm up cluster cluster_name1 with table customer partition p1

以上三条SQL都会返回一个JobID的结果。例如

mysql> warm up cluster cloud_warm_up with table test_warm_up;
+-------+
| JobId |
+-------+
| 13418 |
+-------+
1 row in set (0.01 sec)

然后通过下面的 SQL 来查看预热进度。

SHOW WARM UP JOB; // 获取job信息
SHOW WARM UP JOB WHERE ID = 13418; // 指定job_id
+-------+-------------------+---------+-------+-------------------------+-------------+----------+------------+
| JobId | ClusterName       | Status  | Type  | CreateTime              | FinishBatch | AllBatch | FinishTime |
+-------+-------------------+---------+-------+-------------------------+-------------+----------+------------+
| 13418 | cloud_warm_up     | RUNNING | TABLE | 2023-05-30 20:19:34.059 | 0           | 1        | NULL       |
+-------+-------------------+---------+-------+-------------------------+-------------+----------+------------+
1 row in set (0.02 sec)

根据 FinishBatch 和 All Batch 来判断当前任务进度,每个 Batch 约 10GB。 目前一个 cluster 同一时间内只支持执行一个预热的JOB。也可以停止正在进行的预热job

mysql> cancel warm up job where id = 13418;
Query OK, 0 rows affected (0.02 sec)

mysql> show warm up job where id = 13418;
+-------+-------------------+-----------+-------+-------------------------+-------------+----------+-------------------------+
| JobId | ClusterName       | Status    | Type  | CreateTime              | FinishBatch | AllBatch | FinishTime              |
+-------+-------------------+-----------+-------+-------------------------+-------------+----------+-------------------------+
| 13418 | cloud_warm_up     | CANCELLED | TABLE | 2023-05-30 20:19:34.059 | 0           | 1        | 2023-05-30 20:27:14.186 |
+-------+-------------------+-----------+-------+-------------------------+-------------+----------+-------------------------+
1 row in set (0.00 sec)

实践案例

某用户有若干张表,总数据量为3TB+,缓存只有1.2TB。其中经常访问的有两张表,其中有一张小表 200 MB,还有一张 100 GB 的表。其他的大表也会每天有流量,但不多,在LRU策略下,查询大表有可能淘汰掉需要经常访问的小表的数据,造成性能波动。为了让常驻的表的缓存不被淘汰,通过设置两张表的TTL时间,让这两张表的数据常驻在缓存中。对于小表,因为数据量较大,每天变动不大,设置了TTL超时1年来让他长期在缓存。对于另一张表,用户每天会做一次表的备份,然后再进行全量导入,所以推荐设置了1天的TTL超时时间。

© 2023 北京飞轮数据科技有限公司 京ICP备2022004029号 | Apache、Apache Doris 以及相关开源项目名称均为 Apache 基金会商标