有奖捉虫:行业应用 & 管理与支持文档专题 HOT
Doris 支持把一张表的所有数据或指定分区的数据缓存在内存中,内存表可以提高查询计算性能。但内存容量毕竟有限,因此最好仅使用数据总量较小的表。

用法

缓存整张表

对于新增表,建表时在 PROPERTIES 中加上配置"in_memory"="true" 即可,如:
CREATE TABLE IF NOT EXISTS example_db.expamle_tbl
(
`user_id` LARGEINT NOT NULL COMMENT "用户id",
`date` DATE NOT NULL COMMENT "数据灌入日期时间",
`city` VARCHAR(20) COMMENT "用户所在城市",
`age` SMALLINT COMMENT "用户年龄",
`sex` TINYINT COMMENT "用户性别",
`last_visit_date` DATETIME REPLACE DEFAULT "1970-01-01 00:00:00" COMMENT "用户最后一次访问时间",
`cost` BIGINT SUM DEFAULT "0" COMMENT "用户总消费",
`max_dwell_time` INT MAX DEFAULT "0" COMMENT "用户最大停留时间",
`min_dwell_time` INT MIN DEFAULT "99999" COMMENT "用户最小停留时间"
)
AGGREGATE KEY(`user_id`, `date`, `city`, `age`, `sex`)
DISTRIBUTED BY HASH(`user_id`) BUCKETS 1
PROPERTIES (
"replication_allocation" = "tag.location.default: 1",
"in_memory"="true"
);
对于存量表,修改表配置设置"in_memory"="true" 即可:
ALTER TABLE example_db.my_table set ("in_memory" = "true");

缓存指定分区

正式分区和临时分区都可缓存。 对于新增的分区,添加分区时设置"in_memory"="true" 即可:
ALTER TABLE example_db.my_table ADD [TEMPORARY] PARTITION p1 VALUES LESS THAN ("2020-02-01") ("in_memory" = "true", "replication_num" = "1")
对于已存在的分区,修改分区配置设置"in_memory"="true" 即可:
ALTER TABLE example_db.my_table MODIFY PARTITION (p1, p2, p4) SET("in_memory"="true");

去除数据缓存

当不需要缓存数据用于加速计算时需要及时把缓存数据从内存释放掉,减少不必要的数据释放。去除缓存只需修改相应表或分区的配置改为"in_memory"="false"即可。
ALTER TABLE example_db.my_table set ("in_memory" = "false");
ALTER TABLE example_db.my_table MODIFY PARTITION (p1, p2, p4) SET("in_memory"="false");

注意事项

in_memory 属性

当建表时指定了 "in_memory" = "true" 属性。则 Doris 会尽量将该表的数据块缓存在存储引擎的 PageCache 中,以减少磁盘 IO。但这个属性不会保证数据块常驻在内存中,仅作为一种尽力而为的标识。

相关配置参数

内存表 缓存内存的方式是使用 Doris 的 page cache,需要确保 page cache 功能开启和分配了合适的内存。相关的参数通过 be.conf 进行设置。
disable_storage_page_cache
类型:bool
描述:是否使用 page cache 进行 index 的缓存,该配置仅在 BETA 存储格式时生效。
默认值:false
chunk_reserved_bytes_limit
描述:Chunk Allocator的reserved bytes 限制,通常被设置为 mem_limit 的百分比。默认单位字节,值必须是2的倍数,且必须大于0,如果大于物理内存,将被设置为物理内存大小。增加这个变量可以提高性能,但是会获得更多其他模块无法使用的空闲内存。
默认值:10%

最佳实践

尝试比较开启内存表前后的性能差距。

环境准备

测试版本 :1.2.6
FE节点配置:4核16G 1个节点 硬盘400GB
BE节点配置:4核16G 3个节点 硬盘300GB
配置:chunk_reserved_bytes_limit=30%

开展测试

使用 TPC-H 测试集的 supplier 表测试,其中 supplier 表为内存表,supplier1 表为非内存表。

enter image description here


大小均为250M,共100W条记录。

enter image description here


使用 mysqlslap 进行压测,压测 SQL 为针对 supplier 的全表遍历。
[root@9 data]# tail test.sql
select * from supplier where s_suppkey=1;
...
select * from supplier where s_suppkey=999991;
select * from supplier where s_suppkey=999992;
select * from supplier where s_suppkey=999993;
select * from supplier where s_suppkey=999994;
select * from supplier where s_suppkey=999995;
select * from supplier where s_suppkey=999996;
select * from supplier where s_suppkey=999997;
select * from supplier where s_suppkey=999998;
select * from supplier where s_suppkey=999999;
[root@9 data]# tail test2.sql
select * from supplier1 where s_suppkey=1;
...
select * from supplier1 where s_suppkey=999991;
select * from supplier1 where s_suppkey=999992;
select * from supplier1 where s_suppkey=999993;
select * from supplier1 where s_suppkey=999994;
select * from supplier1 where s_suppkey=999995;
select * from supplier1 where s_suppkey=999996;
select * from supplier1 where s_suppkey=999997;
select * from supplier1 where s_suppkey=999998;
select * from supplier1 where s_suppkey=999999;
压测 SQL:
mysqlslap -h127.0.0.1 -uadmin -P9030 -pxxxxx --iterations=1 --concurrency=500 --number-of-queries=1000000 --create-schema=tpch_100_d --query="/data/test1.sql" --delimiter=";";

测试结果

内存表 平均耗时160s


enter image description here



非内存表 平均耗时260s


enter image description here


内存表相对非内存表提升38%。

 使用建议

配置内存表的数据不宜过大,建议在300M以下。
主要考虑到 page cache 是全局共用的缓存,单表数据过大会挤占其他 sql page cache 的空间。同时内存表也并不保证表的所有 page 都被加载进内存,只是告诉系统尽力而为的一个标志, 也容易跟其他表数据 page cache 相互挤占,导致 page cache 的内存停驻时间变少,而降低了page cache 的命中率。