doris分区
partition
range分区,根据时间范围进行分区,这种分区是物理隔离的,可以理解成单独的一张小表,删除、查询等操作非常快
bucket
在Doris的存储引擎中,用户数据被水平划分为若干个数据分片(Tablet,也称作数据分桶)。每个Tablet包含若干数据行。各个Tablet之间的数据没有交集,并且在物理上是独立存储的。
多个Tablet在逻辑上归属于不同的分区(Partition)。一个Tablet只属于一个Partition。而一个Partition包含若干个Tablet。因为Tablet在物理上是独立存储的,所以可以视为Partition在物理上也是独立。Tablet是数据移动、复制等操作的最小物理存储单元。
若干个Partition组成一个Table。Partition可以视为是逻辑上最小的管理单元。数据的导入与删除,都可以或仅能针对一个Partition进行。
一个 Partition 的 Bucket 数量一旦指定,不可更改。所以在确定 Bucket 数量时,需要预先考虑集群扩容的情况。比如当前只有 3 台 host,每台 host 有 1 块盘。如果 Bucket 的数量只设置为 3 或更小,那么后期即使再增加机器,也不能提高并发度。
doris查询条件
- 一个有所有三级类目权限的人,查询的时候,会添加三级类目in的查询条件,这是非常影响性能的,去掉这个条件之后,查询性能提升一倍;到底是in的影响,还是三级类目没在索引中的影响?
doris前缀索引
我们将一行数据的前 36 个字节 作为这行数据的前缀索引。当遇到 VARCHAR 类型时,前缀索引会直接截断
- http://doris.apache.org/master/zh-CN/getting-started/data-model-rollup.html#rollup
- https://km.sankuai.com/page/28276900
doris本地join
- 本地join的时候,两个表的查询都不能有group by
- 如果是两个事实表,如果想使用本地join,那么最好两张表的维度是一致的,这种情况下,两个表可以直接join,不需要先group by之后再join;假设有一张表是到类目维度,另一张表到事业部维度,计算销售额占比等指标,类目表可以直接关联事业部表,因为本身的计算就是需要两张表的维度不一样
- 如果是事实表和维表,例如一个事实表和时间维表,可以直接本地join
doris的分区查询
1 | select dim.dt, |
上面的这三种方式都无法走分区查询,最难理解的就是第二种,但是这个是doris的机制,如果想要走分区查询,那么需要查询两次:
- 从维表中查询日期的list
- 事实表的dt查询in这个list
doris前缀索引数序
一个unique模型的表,begin_date作为分区字段,date_scale是真正的时间维度的时间字段
第一种前缀索引的顺序:
- 因为date_scale是各种时间类型的时间值,必须是字符串类型,但是字符串类型的字段会截断前缀索引,后续的字段不会构建在前缀索引中了,所以想着把其他必查的字段放到前面
1 | CREATE TABLE kldp_data_stat.app_management_dashboard_product_with3p_merge_test ( |
第二种前缀索引顺序:
- date_scale放在前面其实也有好处,因为我们的查询条件中并没有添加分区字段,在扫描所有分区的时候,不在因为date_scale在最前,所以没有匹配到的日期的分区可以很快过滤掉
- 但是每个分区中都会有其他字段的各种信息,如果其他字段放在最前面,需要扫很多列才能扫到date_scale列,猜测这部分时间是比较长的
1 | CREATE TABLE kldp_data_stat.app_management_dashboard_product_with3p_merge ( |
测试性能的sql:
1 | select * |
发现两个表的查询时间基本一样,都是200ms左右,可能跟这个表结构比较简单有关系,如果数据量比较大,可能会有差异的比较明显,但是从这个表的测试看,两种情况基本相同
效果最明显的还是添加分区字段到查询条件中,表中的begin_date:
1 | select * |
加上分区条件,查询时间到了几十ms,效果十分明显~