关于starrocks过滤条件中携带函数,bitmap索引失效

为了更快的定位您的问题,请提供以下信息,谢谢
【详述】关于starrocks过滤条件中携带函数,bitmap索引失效
【背景】
建表SQL:
CREATE TABLE test
(
user_new_id varchar(65533) NOT NULL COMMENT “id”,
pt varchar(65533) NOT NULL COMMENT “full_partition”,
sr_auto_uuid bigint(20) NOT NULL AUTO_INCREMENT COMMENT “”,
capital_name varchar(65533) NULL COMMENT “部名称”,
user_guid varchar(65533) NULL COMMENT “户id”,
data_date varchar(65533) NULL COMMENT “筛日期”,
INDEX idx_data_date (data_date) USING BITMAP
) ENGINE = OLAP
PRIMARY KEY(user_new_id, pt, sr_auto_uuid)
COMMENT “测试数据”
PARTITION BY (pt)
DISTRIBUTED BY HASH(user_new_id) BUCKETS 1
PROPERTIES (
“replication_num” = “3”,
“bloom_filter_columns” = “product_name”,
“in_memory” = “false”,
“enable_persistent_index” = “false”,
“replicated_storage” = “true”,
“compression” = “LZ4”
);

data_date数据为:"2024-07-02"类型时间数据

1.使用select count(1) from test where data_date=‘2024-08-27’;可以命中bitmap索引
详细见query_profile:


2.使用select count(1) from test where str_to_date(data_date, ‘%Y-%m-%d’)=‘2024-08-27’,无法命中bitmap索引
详细见:

因为我们场景中在过滤数据中经常会对字段做函数处理,如果索引无法针对函数生效,那我们每次进行scan时,会相对的耗费时间,像这类场景,我们应该如何提升scan的效率呢
【业务影响】查询性能慢
【是否存算分离】 否
【StarRocks版本】3.2.8
【集群规模】例如:3fe+10be
【机器信息】CPU虚拟核/内存/网卡,例如:48C/64G/万兆

使用函数做处理后 目前没办法下推,无法使用bitmap索引过滤数据。
data_date 和 pt 有关联么,有的话可以考虑sql中用 pt 框选时间范围 来减少scan的数据量

目前关联性并不大,可能有部分的data_date数据在在其他分区中,所以没法关联起来,还有我们在过滤条件中确实会经常出现这种处理时间字符串的函数,遇到这样的过滤条件没有什么太合适的方式吗,只能进行全表扫描了?

https://docs.starrocks.io/zh/docs/sql-reference/sql-statements/generated_columns/ 生成列可以解决你的问题吗,可以试试,

好的,我先看看

@trueeyu咨询下,我通过生成列改写了我的时间字符串函数,那么是否支持在生成列上设置bitmap或者bloomFilter这类的索引呢

Try

mysql> create table t2(c1 int, c2 string, c3 date as str_to_date(c2, “%Y-%m-%d”), index i_c3(c3) using bitmap) primary key(c1) distributed by hash(c1) buckets 1;
Query OK, 0 rows affected (0.01 sec)

mysql> insert into t2 values (1, “2024-01-05 01:02:03”), (2, “2024-02-05 02:03:04”);
Query OK, 2 rows affected (0.60 sec)
{‘label’:‘insert_4076c333-6ab3-11ef-a0a3-c688f73e359f’, ‘status’:‘VISIBLE’, ‘txnId’:‘340281’}

mysql> select * from t2 where str_to_date(c2, “%Y-%m-%d”)=“2024-01-06”;
Empty set (0.03 sec)

           - SegmentInit: 1.053ms
             - BitmapIndexFilter: 143.259us
             - BitmapIndexFilterRows: 2

其实你这个场景不一定适合BitmapIndex,什么场景适合,可以看下这个: Bitmap索引适用场景和最佳实践

mysql> explain select * from t2 where str_to_date(c2, “%Y-%m-%d”)=“2024-01-06”;
±--------------------------------------+
| Explain String |
±--------------------------------------+
| PLAN FRAGMENT 0 |
| OUTPUT EXPRS:1: c1 | 2: c2 | 3: c3 |
| PARTITION: RANDOM |
| |
| RESULT SINK |
| |
| 0:OlapScanNode |
| TABLE: t2 |
| PREAGGREGATION: ON |
| PREDICATES: 3: c3 = ‘2024-01-06’ |
| partitions=1/1 |
| rollup: t2 |
| tabletRatio=1/1 |
| tabletList=394614 |
| cardinality=1 |
| avgRowSize=27.0 |
±--------------------------------------+
16 rows in set (0.01 sec)

是的,因为我发现无论我的前缀索引还是bitmap索引本质上都很难起到作用,都是相对基于低基数的字段建了索引,但还是试试看,毕竟能在scan上减少一部分数据,后续的聚合,exchange都会有很好的效果提升

有个办法可以让他有效果,就是让你的时间和排序的ID,近似有关联,并且把data_date改成datetime类型。

你的ID估计是UUID这种吗?

比如ID改成自增的,或是ID的前缀是个时间字段,这样后面那个时间字段和前的这个字段有一定的关联性,这样ZonemapINdex就会有效果了

当前字符串是没有ZonemapIndex的,所以最好是建成datetime类型

@trueeyu
select *
from (select * from test01 where pt <= ‘20240901’) t1
where (date_format(str_to_date(t1.data_date, ‘%Y-%m-%d’), ‘%Y-%m-%d %H:%i:%s’) >=
concat(cast(‘2024-08-28’ as varchar), cast(’ 19:39:50’ as varchar))) limit 1

select *
from test01
where (date_format(str_to_date(data_date, ‘%Y-%m-%d’), ‘%Y-%m-%d %H:%i:%s’) >=
concat(cast(‘2024-08-28’ as varchar), cast(’ 19:39:50’ as varchar)) and pt <= ‘20240901’) limit 1

生成列在字段上添加了别名就失效了

没看到加了别名啊

两个不同的explain
生成列表达式为:

你的意思是表有别名?