Clickhouse 二级索引是否类似于 MySQL 普通索引?
Is Clickhouse secondary index similar to MySQL normal index?
我对何时使用二级索引感到困惑。我有以下代码脚本来定义 MergeTree Table,table 有十亿行。
create table t_mt(
id UInt8,
name String,
job String,
birthday Date,
salary UINT8
) engine = MergeTable
primary key id
order by (id)
我会运行以下实时聚合查询:
select job, count(1), avg(salary)
from t_mt
group by job
where salary > 20000
在上面的查询中,我使用了条件过滤器:salary > 20000
和分组 job
。我会问在 salary
列上定义二级索引是否是一个好习惯。
我在这里要问的基本问题是我是否可以将 Clickhouse 二级索引视为 MySQL 普通索引。也就是说,如果我想按某些列进行过滤,那么我可以在该列上创建(二级)索引以加快查询速度。
不,MySQL 使用 b-tree
索引将随机查找降低到 O(log(N))
复杂度,其中 N 是 table
中的行
Clickhouse 二级索引使用了另一种方法,它是数据跳过索引
当您尝试执行像 SELECT ... WHERE field [operation] values
这样的查询时,其中包含来自二级索引的字段并且二级索引支持应用于 field
的比较 operation
,clickhouse 将读取二级索引granules 并尝试快速检查数据部分是否可以跳过搜索值,如果不是,则 clickhouse 将从数据部分读取整个列 granules
因此,二级索引不适用于分区内数据部分之间没有单调分布的高基数列
Clickhouse 中的此类行为可以使用按 (salary, id) 排序的物化视图(当您将行写入原始 table 时自动填充)有效地实现。按salary查询会比skip index快很多
create materialized view t_mt_by_salary partition by toYear(birthday) order by (salary, id)
populate as select id, name , job , birthday , salary from t_mt;
select * from t_mt_by_salary where salary > 20000
没有必要使用 MySQL 类型的二级索引,因为像 clickhouse 这样的列式 OLAP 在这些类型的查询中比 MySQL 快得多。加载二级索引并进行查找在理论上可以达到 O(N log N) 的复杂度,但在实践中可能不会比完全扫描更好,因为您遇到了磁盘查找的瓶颈。
如果您的查询中有一些罕见的值或数据中有额外的结构(与索引相关),则跳过索引(clickhouse 二级索引)会有所帮助。例如。假设您过滤薪水 >200000 但 99.9% 的薪水低于 200000 - 然后 skip index 告诉您,例如下一个区块的最高薪水是 19400,所以你不需要阅读这个区块。
另一方面,如果您需要加载大约 5% 的数据,随机分布在 8000 行的颗粒(块)中,那么您可能需要扫描几乎所有的颗粒。但是您仍然可以使用按薪水排序的物化视图进行非常快速的查询。
我对何时使用二级索引感到困惑。我有以下代码脚本来定义 MergeTree Table,table 有十亿行。
create table t_mt(
id UInt8,
name String,
job String,
birthday Date,
salary UINT8
) engine = MergeTable
primary key id
order by (id)
我会运行以下实时聚合查询:
select job, count(1), avg(salary)
from t_mt
group by job
where salary > 20000
在上面的查询中,我使用了条件过滤器:salary > 20000
和分组 job
。我会问在 salary
列上定义二级索引是否是一个好习惯。
我在这里要问的基本问题是我是否可以将 Clickhouse 二级索引视为 MySQL 普通索引。也就是说,如果我想按某些列进行过滤,那么我可以在该列上创建(二级)索引以加快查询速度。
不,MySQL 使用 b-tree
索引将随机查找降低到 O(log(N))
复杂度,其中 N 是 table
Clickhouse 二级索引使用了另一种方法,它是数据跳过索引
当您尝试执行像 SELECT ... WHERE field [operation] values
这样的查询时,其中包含来自二级索引的字段并且二级索引支持应用于 field
的比较 operation
,clickhouse 将读取二级索引granules 并尝试快速检查数据部分是否可以跳过搜索值,如果不是,则 clickhouse 将从数据部分读取整个列 granules
因此,二级索引不适用于分区内数据部分之间没有单调分布的高基数列
Clickhouse 中的此类行为可以使用按 (salary, id) 排序的物化视图(当您将行写入原始 table 时自动填充)有效地实现。按salary查询会比skip index快很多
create materialized view t_mt_by_salary partition by toYear(birthday) order by (salary, id)
populate as select id, name , job , birthday , salary from t_mt;
select * from t_mt_by_salary where salary > 20000
没有必要使用 MySQL 类型的二级索引,因为像 clickhouse 这样的列式 OLAP 在这些类型的查询中比 MySQL 快得多。加载二级索引并进行查找在理论上可以达到 O(N log N) 的复杂度,但在实践中可能不会比完全扫描更好,因为您遇到了磁盘查找的瓶颈。
如果您的查询中有一些罕见的值或数据中有额外的结构(与索引相关),则跳过索引(clickhouse 二级索引)会有所帮助。例如。假设您过滤薪水 >200000 但 99.9% 的薪水低于 200000 - 然后 skip index 告诉您,例如下一个区块的最高薪水是 19400,所以你不需要阅读这个区块。
另一方面,如果您需要加载大约 5% 的数据,随机分布在 8000 行的颗粒(块)中,那么您可能需要扫描几乎所有的颗粒。但是您仍然可以使用按薪水排序的物化视图进行非常快速的查询。