早期 clickhouse 仅支持单一存储设备,19.15 版本以后支持将数据分别保存在不同的存储设备,且能够自动在不同设备间移动数据。使 clickhouse 可以实现阶梯式多层存储,即将冷热数据分离,将冷热数据分别保存在不同类型的存储设备中。
日常交互式查询中,95% 查询访问近几天的数据,剩下 5% 的跑一些长周期批处理任务。我们可以通过阶梯式多层存储,将最新的热点数据放在高性能介质如 SSD,旧的历史数据放在廉价的机械硬盘中。此外,将数据存在多个存储设备中,以扩展服务器的存储能力,clickhouse 也能够自动在不同存储设备之间移动数据。
每张 MergeTree 表都有一个存储策略,用以规定该表数据如何写入;策略将不同的磁盘分到一个或多个卷中,并规定了数据的写入顺序以及如何在磁盘之间移动数据。
如果没有特别指定,每一个表都有一个默认的存储策略default
,该策略将数据存储在配置文件中path
指定的路径下。
初始状态在clickhouse配置文件中指定了数据存放目录为:
/home/work/bigdata/clickhouse/data/
启动客户端并查看当前clickhouse感知到的磁盘目录:
SELECT
name,
path,
formatReadableSize(free_space) AS free,
formatReadableSize(total_space) AS total,
formatReadableSize(keep_free_space) AS reserved
FROM system.disks
┌─name────┬─path────────────────────────────────┬─free─────┬─total────┬─reserved─┐
│ default │ /home/work/bigdata/clickhouse/data/ │ 1.16 TiB │ 3.52 TiB │ 0.00 B │
└─────────┴─────────────────────────────────────┴──────────┴──────────┴──────────┘
1 rows in set. Elapsed: 0.040 sec.
在服务器上挂载了额外的磁盘:
$ lsblk
NAME MAJ:MIN RM SIZE RO TYPE MOUNTPOINT
sdb 8:16 0 3.7T 0 disk
`-sdb1 8:17 0 3.7T 0 part /home/disk0
sdc 8:32 0 3.7T 0 disk
`-sdc1 8:33 0 3.7T 0 part /home/disk1
sdd 8:48 0 3.7T 0 disk
`-sdd1 8:49 0 3.7T 0 part /home/disk2
sde 8:64 0 3.7T 0 disk
`-sde1 8:65 0 3.7T 0 part /home/disk3
sdf 8:80 0 3.7T 0 disk
`-sdf1 8:81 0 3.7T 0 part /home/disk4
sdg 8:96 0 3.7T 0 disk
`-sdg1 8:97 0 3.7T 0 part /home/disk5
sdh 8:112 0 3.7T 0 disk
`-sdh1 8:113 0 3.7T 0 part /home/disk6
在每个磁盘中创建对应的存放clickhouse数据的目录,并修改目录所有者为click house用户
mkdir -p /home/disk0/clickhouse/
chown -R clickhouse.clickhouse /home/disk0/clickhouse/
修改clickhouse服务配置文件 /etc/clickhouse-server/config.xml
增加上述磁盘
/home/disk0/clickhouse/
/home/disk1/clickhouse/
/home/disk2/clickhouse/
/home/disk3/clickhouse/
/home/disk4/clickhouse/
/home/disk5/clickhouse/
/home/disk6/clickhouse/
重启clickhouse服务
service clickhouse-server stop
service clickhouse-server start
此时再查看clickhouse感知到的磁盘目录
SELECT
name,
path,
formatReadableSize(free_space) AS free,
formatReadableSize(total_space) AS total,
formatReadableSize(keep_free_space) AS reserved
FROM system.disks
┌─name────────┬─path────────────────────────────────┬─free─────┬─total────┬─reserved─┐
│ default │ /home/work/bigdata/clickhouse/data/ │ 1.34 TiB │ 3.52 TiB │ 0.00 B │
│ disk_name_0 │ /home/disk0/clickhouse/ │ 3.58 TiB │ 3.58 TiB │ 0.00 B │
│ disk_name_1 │ /home/disk1/clickhouse/ │ 3.58 TiB │ 3.58 TiB │ 0.00 B │
│ disk_name_2 │ /home/disk2/clickhouse/ │ 3.58 TiB │ 3.58 TiB │ 0.00 B │
│ disk_name_3 │ /home/disk3/clickhouse/ │ 3.58 TiB │ 3.58 TiB │ 0.00 B │
│ disk_name_4 │ /home/disk4/clickhouse/ │ 3.58 TiB │ 3.58 TiB │ 0.00 B │
│ disk_name_5 │ /home/disk5/clickhouse/ │ 3.58 TiB │ 3.58 TiB │ 0.00 B │
│ disk_name_6 │ /home/disk6/clickhouse/ │ 3.58 TiB │ 3.58 TiB │ 0.00 B │
└─────────────┴─────────────────────────────────────┴──────────┴──────────┴──────────┘
可以看到,除了原有的默认路径外,新增了我们新挂载的磁盘目录。
通过上述操作,为clickhouse配置了多个磁盘,但是仅仅这些并不能让表中的数据存在配置的多个磁盘中,可以通过试验观察:
CREATE TABLE sample1
(
`id` UInt64
)
ENGINE = MergeTree
ORDER BY id
Ok.
0 rows in set. Elapsed: 2.467 sec.
INSERT INTO sample1 SELECT *
FROM numbers(1000000)
← Progress: 1.05 million rows, 8.39 MB (10.84 million rows/s., 86.74 MB/s.) 99%Ok.
0 rows in set. Elapsed: 0.097 sec. Processed 1.05 million rows, 8.39 MB (10.84 million rows/s., 86.70 MB/s.)
SELECT
name,
data_paths
FROM system.tables
WHERE name = 'sample1'
┌─name────┬─data_paths───────────────────────────────────────────────────┐
│ sample1 │ ['/home/work/bigdata/clickhouse/data/data/default/sample1/'] │
└─────────┴──────────────────────────────────────────────────────────────┘
SELECT
name,
disk_name,
path
FROM system.parts
WHERE (table = 'sample1') AND active
┌─name──────┬─disk_name─┬─path───────────────────────────────────────────────────────────────┐
│ all_1_1_0 │ default │ /home/work/bigdata/clickhouse/data/data/default/sample1/all_1_1_0/ │
└───────────┴───────────┴────────────────────────────────────────────────────────────────────┘
可以看到该表数据仍然只保存在一个目录中,因为如果不加指定,clickhouse的表有一个默认的单一存储策略default:
SELECT
policy_name,
volume_name,
disks
FROM system.storage_policies
┌─policy_name─┬─volume_name─┬─disks───────┐
│ default │ default │ ['default'] │
└─────────────┴─────────────┴─────────────┘
为了使多个磁盘生效,仍需两个工作:
在配置文件中制定存储策略,并通过卷标签来组织多个磁盘
建表时通过
SETTINGS storage_policy=’’
来为表指定存储策略
JBOD(“Just a Bunch of Disks”),通过将多个磁盘分配在一个卷中,每次插入数据所生成的data part会以轮询的方式依次写入这些磁盘,该策略的优点:
通过直接追加磁盘的形式,可以便捷地扩展存储能力
在多线程并行访问多个不同磁盘时,可以提升读写速度
由于每个磁盘上的data parts变少,可以加快表的加载速度
在配置文件中添加如下的存储策略配置,并重启clickhouse服务。
disk_name_0
disk_name_1
disk_name_2
disk_name_3
disk_name_4
disk_name_5
disk_name_6
可以看到此时已经多了一个包含多磁盘的存储策略
SELECT policy_name,
volume_name,
disks
FROM system.storage_policies
┌─policy_name───┬─volume_name───┬─disks───────────────────────────────────────────────────────────────────────────────────────────────┐
│ default │ default │ ['default'] │
│ policy_name_1 │ volume_name_0 │ ['disk_name_0','disk_name_1','disk_name_2','disk_name_3','disk_name_4','disk_name_5','disk_name_6'] │
└───────────────┴───────────────┴─────────────────────────────────────────────────────────────────────────────────────────────────────┘
创建新表并进行测试
CREATE TABLE sample3 (id UInt64)
Engine=MergeTree
ORDER BY id
SETTINGS storage_policy = 'policy_name_1';
SELECT
name,
data_paths,
metadata_path,
storage_policy
FROM system.tables
WHERE name = 'sample3';
┌─name────┬─data_paths─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┬─metadata_path───────────────────────────────────────────────────┬─storage_policy─┐
│ sample3 │ ['/home/disk0/clickhouse/data/default/sample3/','/home/disk1/clickhouse/data/default/sample3/','/home/disk2/clickhouse/data/default/sample3/','/home/disk3/clickhouse/data/default/sample3/','/home/disk4/clickhouse/data/default/sample3/','/home/disk5/clickhouse/data/default/sample3/','/home/disk6/clickhouse/data/default/sample3/'] │ /home/work/bigdata/clickhouse/data/metadata/default/sample3.sql │ policy_name_1 │
└─────────┴────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┴─────────────────────────────────────────────────────────────────┴────────────────┘
insert into sample3 select * from numbers(1000000);
insert into sample3 select * from numbers(1000000);
insert into sample3 select * from numbers(1000000);
insert into sample3 select * from numbers(1000000);
select name, disk_name, path from system.parts where table = 'sample3';
┌─name──────┬─disk_name───┬─path───────────────────────────────────────────────────┐
│ all_1_1_0 │ disk_name_0 │ /home/disk0/clickhouse/data/default/sample3/all_1_1_0/ │
│ all_2_2_0 │ disk_name_1 │ /home/disk1/clickhouse/data/default/sample3/all_2_2_0/ │
│ all_3_3_0 │ disk_name_2 │ /home/disk2/clickhouse/data/default/sample3/all_3_3_0/ │
│ all_4_4_0 │ disk_name_3 │ /home/disk3/clickhouse/data/default/sample3/all_4_4_0/ │
└───────────┴─────────────┴────────────────────────────────────────────────────────┘
该表的多磁盘存储已经生效,且插入的测试数据也依次写入到多个磁盘中,
注意元数据仍然存在默认磁盘目录中。后台的合并任务会定期合并这些小的
data parts 并生成更大的data parts,同样采用轮询的方式写入这些磁盘中。
可以手动触发合并任务的执行:
OPTIMIZE TABLE sample3
Ok. 0 rows in set. Elapsed: 0.148 sec. Processed: 0 rows, 0.0B (0 rows/s, 0.0B/s)
SELECT
name,
disk_name,
path
FROM system.parts
WHERE (table = 'sample3') AND active;
┌─name──────┬─disk_name───┬─path───────────────────────────────────────────────────┐
│ all_1_4_1 │ disk_name_4 │ /home/disk4/clickhouse/data/default/sample3/all_1_4_1/ │
└───────────┴─────────────┴────────────────────────────────────────────────────────┘
识别下方二维码,回复“资料全集”,即可获得下载地址。