This is an automated email from the ASF dual-hosted git repository.

yiguolei pushed a commit to branch dev-1.1.2
in repository https://gitbox.apache.org/repos/asf/doris.git


The following commit(s) were added to refs/heads/dev-1.1.2 by this push:
     new 978f65a24c [Vectorized][Function] add orthogonal bitmap agg functions 
(#10126) (#11333)
978f65a24c is described below

commit 978f65a24c5ac27fa76b6738e7369ad6aab743cd
Author: starocean999 <[email protected]>
AuthorDate: Sat Jul 30 19:22:26 2022 +0800

    [Vectorized][Function] add orthogonal bitmap agg functions (#10126) (#11333)
    
    * [Vectorized][Function] add orthogonal bitmap agg functions
    save some file about orthogonal bitmap function
    add some file to rebase
    update functions file
    
    * refactor union_count function
    refactor orthogonal union count functions
    
    * remove bool is_variadic
    
    Co-authored-by: zhangstar333 
<[email protected]>
---
 be/src/exprs/bitmap_function.cpp                   |  256 +----
 be/src/runtime/string_value.h                      |    1 +
 be/src/util/bitmap_intersect.h                     |  245 +++++
 be/src/vec/CMakeLists.txt                          |    2 +
 .../aggregate_function_orthogonal_bitmap.cpp       |   99 ++
 .../aggregate_function_orthogonal_bitmap.h         |  247 +++++
 .../aggregate_function_simple_factory.cpp          |    2 +
 be/test/exprs/bitmap_function_test.cpp             |    7 +-
 docs/.vuepress/sidebar/en/docs.js                  | 1009 ++++++++++++++++++++
 docs/.vuepress/sidebar/zh-CN.js                    |    1 +
 .../bitmap-functions/intersect_count.md            |   57 ++
 .../bitmap-functions/intersect_count.md            |   56 ++
 .../apache/doris/analysis/FunctionCallExpr.java    |   13 +-
 .../apache/doris/catalog/AggregateFunction.java    |    7 +-
 .../java/org/apache/doris/catalog/FunctionSet.java |   21 +
 15 files changed, 1782 insertions(+), 241 deletions(-)

diff --git a/be/src/exprs/bitmap_function.cpp b/be/src/exprs/bitmap_function.cpp
index 5e38ab8f79..e45f7244b9 100644
--- a/be/src/exprs/bitmap_function.cpp
+++ b/be/src/exprs/bitmap_function.cpp
@@ -20,141 +20,12 @@
 #include "exprs/anyval_util.h"
 #include "gutil/strings/numbers.h"
 #include "gutil/strings/split.h"
+#include "util/bitmap_intersect.h"
 #include "util/bitmap_value.h"
 #include "util/string_parser.hpp"
 
 namespace doris {
 
-namespace detail {
-
-const int DATETIME_PACKED_TIME_BYTE_SIZE = 8;
-const int DATETIME_TYPE_BYTE_SIZE = 4;
-
-const int DECIMAL_BYTE_SIZE = 16;
-
-// get_val start
-template <typename ValType, typename T>
-T get_val(const ValType& x) {
-    DCHECK(!x.is_null);
-    return x.val;
-}
-
-template <>
-StringValue get_val(const StringVal& x) {
-    DCHECK(!x.is_null);
-    return StringValue::from_string_val(x);
-}
-
-template <>
-DateTimeValue get_val(const DateTimeVal& x) {
-    return DateTimeValue::from_datetime_val(x);
-}
-
-template <>
-DecimalV2Value get_val(const DecimalV2Val& x) {
-    return DecimalV2Value::from_decimal_val(x);
-}
-// get_val end
-
-// serialize_size start
-template <typename T>
-int32_t serialize_size(const T& v) {
-    return sizeof(T);
-}
-
-template <>
-int32_t serialize_size(const DateTimeValue& v) {
-    return DATETIME_PACKED_TIME_BYTE_SIZE + DATETIME_TYPE_BYTE_SIZE;
-}
-
-template <>
-int32_t serialize_size(const DecimalV2Value& v) {
-    return DECIMAL_BYTE_SIZE;
-}
-
-template <>
-int32_t serialize_size(const StringValue& v) {
-    return v.len + 4;
-}
-// serialize_size end
-
-// write_to start
-template <typename T>
-char* write_to(const T& v, char* dest) {
-    size_t type_size = sizeof(T);
-    memcpy(dest, &v, type_size);
-    dest += type_size;
-    return dest;
-}
-
-template <>
-char* write_to(const DateTimeValue& v, char* dest) {
-    DateTimeVal value;
-    v.to_datetime_val(&value);
-    *(int64_t*)dest = value.packed_time;
-    dest += DATETIME_PACKED_TIME_BYTE_SIZE;
-    *(int*)dest = value.type;
-    dest += DATETIME_TYPE_BYTE_SIZE;
-    return dest;
-}
-
-template <>
-char* write_to(const DecimalV2Value& v, char* dest) {
-    __int128 value = v.value();
-    memcpy(dest, &value, DECIMAL_BYTE_SIZE);
-    dest += DECIMAL_BYTE_SIZE;
-    return dest;
-}
-
-template <>
-char* write_to(const StringValue& v, char* dest) {
-    *(int32_t*)dest = v.len;
-    dest += 4;
-    memcpy(dest, v.ptr, v.len);
-    dest += v.len;
-    return dest;
-}
-// write_to end
-
-// read_from start
-template <typename T>
-void read_from(const char** src, T* result) {
-    size_t type_size = sizeof(T);
-    memcpy(result, *src, type_size);
-    *src += type_size;
-}
-
-template <>
-void read_from(const char** src, DateTimeValue* result) {
-    DateTimeVal value;
-    value.is_null = false;
-    value.packed_time = *(int64_t*)(*src);
-    *src += DATETIME_PACKED_TIME_BYTE_SIZE;
-    value.type = *(int*)(*src);
-    *src += DATETIME_TYPE_BYTE_SIZE;
-    *result = DateTimeValue::from_datetime_val(value);
-    ;
-}
-
-template <>
-void read_from(const char** src, DecimalV2Value* result) {
-    __int128 v = 0;
-    memcpy(&v, *src, DECIMAL_BYTE_SIZE);
-    *src += DECIMAL_BYTE_SIZE;
-    *result = DecimalV2Value(v);
-}
-
-template <>
-void read_from(const char** src, StringValue* result) {
-    int32_t length = *(int32_t*)(*src);
-    *src += 4;
-    *result = StringValue((char*)*src, length);
-    *src += length;
-}
-// read_from end
-
-} // namespace detail
-
 static StringVal serialize(FunctionContext* ctx, BitmapValue* value) {
     if (!value) {
         BitmapValue empty_bitmap;
@@ -168,98 +39,6 @@ static StringVal serialize(FunctionContext* ctx, 
BitmapValue* value) {
     }
 }
 
-// Calculate the intersection of two or more bitmaps
-// Usage: intersect_count(bitmap_column_to_count, filter_column, filter_values 
...)
-// Example: intersect_count(user_id, event, 'A', 'B', 'C'), meaning find the 
intersect count of user_id in all A/B/C 3 bitmaps
-// Todo(kks) Use Array type instead of variable arguments
-template <typename T>
-struct BitmapIntersect {
-public:
-    BitmapIntersect() {}
-
-    explicit BitmapIntersect(const char* src) { deserialize(src); }
-
-    void add_key(const T key) {
-        BitmapValue empty_bitmap;
-        _bitmaps[key] = empty_bitmap;
-    }
-
-    void update(const T& key, const BitmapValue& bitmap) {
-        if (_bitmaps.find(key) != _bitmaps.end()) {
-            _bitmaps[key] |= bitmap;
-        }
-    }
-
-    void merge(const BitmapIntersect& other) {
-        for (auto& kv : other._bitmaps) {
-            if (_bitmaps.find(kv.first) != _bitmaps.end()) {
-                _bitmaps[kv.first] |= kv.second;
-            } else {
-                _bitmaps[kv.first] = kv.second;
-            }
-        }
-    }
-
-    // intersection
-    BitmapValue intersect() const {
-        BitmapValue result;
-        auto it = _bitmaps.begin();
-        result |= it->second;
-        it++;
-        for (; it != _bitmaps.end(); it++) {
-            result &= it->second;
-        }
-        return result;
-    }
-
-    // calculate the intersection for _bitmaps's bitmap values
-    int64_t intersect_count() const {
-        if (_bitmaps.empty()) {
-            return 0;
-        }
-        return intersect().cardinality();
-    }
-
-    // the serialize size
-    size_t size() {
-        size_t size = 4;
-        for (auto& kv : _bitmaps) {
-            size += detail::serialize_size(kv.first);
-            ;
-            size += kv.second.getSizeInBytes();
-        }
-        return size;
-    }
-
-    //must call size() first
-    void serialize(char* dest) {
-        char* writer = dest;
-        *(int32_t*)writer = _bitmaps.size();
-        writer += 4;
-        for (auto& kv : _bitmaps) {
-            writer = detail::write_to(kv.first, writer);
-            kv.second.write(writer);
-            writer += kv.second.getSizeInBytes();
-        }
-    }
-
-    void deserialize(const char* src) {
-        const char* reader = src;
-        int32_t bitmaps_size = *(int32_t*)reader;
-        reader += 4;
-        for (int32_t i = 0; i < bitmaps_size; i++) {
-            T key;
-            detail::read_from(&reader, &key);
-            BitmapValue bitmap(reader);
-            reader += bitmap.getSizeInBytes();
-            _bitmaps[key] = bitmap;
-        }
-    }
-
-private:
-    std::map<T, BitmapValue> _bitmaps;
-};
-
 void BitmapFunctions::init() {}
 
 void BitmapFunctions::bitmap_init(FunctionContext* ctx, StringVal* dst) {
@@ -403,7 +182,7 @@ StringVal 
BitmapFunctions::bitmap_serialize(FunctionContext* ctx, const StringVa
     return result;
 }
 
-// This is a init function for intersect_count not for bitmap_intersect.
+// This is a init function for intersect_count not for bitmap_intersect, not 
for _orthogonal_bitmap_intersect(bitmap,t,t)
 template <typename T, typename ValType>
 void BitmapFunctions::bitmap_intersect_init(FunctionContext* ctx, StringVal* 
dst) {
     dst->is_null = false;
@@ -414,12 +193,14 @@ void 
BitmapFunctions::bitmap_intersect_init(FunctionContext* ctx, StringVal* dst
     for (int i = 2; i < ctx->get_num_constant_args(); ++i) {
         DCHECK(ctx->is_arg_constant(i));
         ValType* arg = reinterpret_cast<ValType*>(ctx->get_constant_arg(i));
-        intersect->add_key(detail::get_val<ValType, T>(*arg));
+        intersect->add_key(detail::Helper::get_val<ValType, T>(*arg));
     }
 
     dst->ptr = (uint8_t*)intersect;
 }
 
+// This is a update function for 
intersect_count/ORTHOGONAL_BITMAP_INTERSECT_COUNT/ORTHOGONAL_BITMAP_INTERSECT(bitmap,t,t)
+// not for bitmap_intersect(Bitmap)
 template <typename T, typename ValType>
 void BitmapFunctions::bitmap_intersect_update(FunctionContext* ctx, const 
StringVal& src,
                                               const ValType& key, int num_key, 
const ValType* keys,
@@ -427,13 +208,14 @@ void 
BitmapFunctions::bitmap_intersect_update(FunctionContext* ctx, const String
     auto* dst_bitmap = reinterpret_cast<BitmapIntersect<T>*>(dst->ptr);
     // zero size means the src input is a agg object
     if (src.len == 0) {
-        dst_bitmap->update(detail::get_val<ValType, T>(key),
+        dst_bitmap->update(detail::Helper::get_val<ValType, T>(key),
                            *reinterpret_cast<BitmapValue*>(src.ptr));
     } else {
-        dst_bitmap->update(detail::get_val<ValType, T>(key), 
BitmapValue((char*)src.ptr));
+        dst_bitmap->update(detail::Helper::get_val<ValType, T>(key), 
BitmapValue((char*)src.ptr));
     }
 }
 
+//only for intersect_count(bitmap,t,t)
 template <typename T>
 void BitmapFunctions::bitmap_intersect_merge(FunctionContext* ctx, const 
StringVal& src,
                                              const StringVal* dst) {
@@ -441,6 +223,7 @@ void 
BitmapFunctions::bitmap_intersect_merge(FunctionContext* ctx, const StringV
     dst_bitmap->merge(BitmapIntersect<T>((char*)src.ptr));
 }
 
+//only for intersect_count(bitmap,t,t)
 template <typename T>
 StringVal BitmapFunctions::bitmap_intersect_serialize(FunctionContext* ctx, 
const StringVal& src) {
     auto* src_bitmap = reinterpret_cast<BitmapIntersect<T>*>(src.ptr);
@@ -450,6 +233,7 @@ StringVal 
BitmapFunctions::bitmap_intersect_serialize(FunctionContext* ctx, cons
     return result;
 }
 
+//only for intersect_count(bitmap,t,t)
 template <typename T>
 BigIntVal BitmapFunctions::bitmap_intersect_finalize(FunctionContext* ctx, 
const StringVal& src) {
     auto* src_bitmap = reinterpret_cast<BitmapIntersect<T>*>(src.ptr);
@@ -928,13 +712,15 @@ StringVal 
BitmapFunctions::bitmap_subset_limit(FunctionContext* ctx, const Strin
 
     return serialize(ctx, &ret_bitmap);
 }
-
+// init ORTHOGONAL_BITMAP_UNION_COUNT(bitmap)
+// update bitmap_union()
 void BitmapFunctions::orthogonal_bitmap_union_count_init(FunctionContext* ctx, 
StringVal* dst) {
     dst->is_null = false;
     dst->len = sizeof(BitmapValue);
     dst->ptr = (uint8_t*)new BitmapValue();
 }
 
+// serialize for ORTHOGONAL_BITMAP_UNION_COUNT(bitmap)
 StringVal BitmapFunctions::orthogonal_bitmap_count_serialize(FunctionContext* 
ctx,
                                                              const StringVal& 
src) {
     if (src.is_null) {
@@ -950,7 +736,7 @@ StringVal 
BitmapFunctions::orthogonal_bitmap_count_serialize(FunctionContext* ct
     return result;
 }
 
-// This is a init function for bitmap_intersect.
+// This is a init function for orthogonal_bitmap_intersect(bitmap,t,t).
 template <typename T, typename ValType>
 void BitmapFunctions::orthogonal_bitmap_intersect_init(FunctionContext* ctx, 
StringVal* dst) {
     // constant args start from index 2
@@ -961,7 +747,7 @@ void 
BitmapFunctions::orthogonal_bitmap_intersect_init(FunctionContext* ctx, Str
 
         for (int i = 2; i < ctx->get_num_constant_args(); ++i) {
             ValType* arg = 
reinterpret_cast<ValType*>(ctx->get_constant_arg(i));
-            intersect->add_key(detail::get_val<ValType, T>(*arg));
+            intersect->add_key(detail::Helper::get_val<ValType, T>(*arg));
         }
 
         dst->ptr = (uint8_t*)intersect;
@@ -972,7 +758,7 @@ void 
BitmapFunctions::orthogonal_bitmap_intersect_init(FunctionContext* ctx, Str
     }
 }
 
-// This is a init function for intersect_count.
+// This is a init function for orthogonal_bitmap_intersect_count(bitmap,t,t).
 template <typename T, typename ValType>
 void BitmapFunctions::orthogonal_bitmap_intersect_count_init(FunctionContext* 
ctx, StringVal* dst) {
     if (ctx->get_num_constant_args() > 1) {
@@ -983,7 +769,7 @@ void 
BitmapFunctions::orthogonal_bitmap_intersect_count_init(FunctionContext* ct
         // constant args start from index 2
         for (int i = 2; i < ctx->get_num_constant_args(); ++i) {
             ValType* arg = 
reinterpret_cast<ValType*>(ctx->get_constant_arg(i));
-            intersect->add_key(detail::get_val<ValType, T>(*arg));
+            intersect->add_key(detail::Helper::get_val<ValType, T>(*arg));
         }
 
         dst->ptr = (uint8_t*)intersect;
@@ -995,6 +781,9 @@ void 
BitmapFunctions::orthogonal_bitmap_intersect_count_init(FunctionContext* ct
     }
 }
 
+// This is a serialize function for orthogonal_bitmap_intersect(bitmap,t,t).
+// merge is ths simple bitmap_union() function LINE(80);
+// finalize is the bitmap_serialize() function LINE(173)
 template <typename T>
 StringVal 
BitmapFunctions::orthogonal_bitmap_intersect_serialize(FunctionContext* ctx,
                                                                  const 
StringVal& src) {
@@ -1014,6 +803,8 @@ BigIntVal 
BitmapFunctions::orthogonal_bitmap_intersect_finalize(FunctionContext*
     return result;
 }
 
+// This is a merge function for orthogonal_bitmap_intersect_count(bitmap,t,t).
+// and merge for ORTHOGONAL_BITMAP_UNION_COUNT(bitmap)
 void BitmapFunctions::orthogonal_bitmap_count_merge(FunctionContext* context, 
const StringVal& src,
                                                     StringVal* dst) {
     if (dst->len != sizeof(int64_t)) {
@@ -1027,6 +818,8 @@ void 
BitmapFunctions::orthogonal_bitmap_count_merge(FunctionContext* context, co
     *(int64_t*)dst->ptr += *(int64_t*)src.ptr;
 }
 
+// This is a finalize function for 
orthogonal_bitmap_intersect_count(bitmap,t,t).
+// finalize for ORTHOGONAL_BITMAP_UNION_COUNT(bitmap)
 BigIntVal BitmapFunctions::orthogonal_bitmap_count_finalize(FunctionContext* 
context,
                                                             const StringVal& 
src) {
     auto* pval = reinterpret_cast<int64_t*>(src.ptr);
@@ -1035,6 +828,7 @@ BigIntVal 
BitmapFunctions::orthogonal_bitmap_count_finalize(FunctionContext* con
     return result;
 }
 
+// This is a serialize function for 
orthogonal_bitmap_intersect_count(bitmap,t,t).
 template <typename T>
 StringVal 
BitmapFunctions::orthogonal_bitmap_intersect_count_serialize(FunctionContext* 
ctx,
                                                                        const 
StringVal& src) {
diff --git a/be/src/runtime/string_value.h b/be/src/runtime/string_value.h
index cdf33ab57e..9ba7d4fc34 100644
--- a/be/src/runtime/string_value.h
+++ b/be/src/runtime/string_value.h
@@ -89,6 +89,7 @@ struct StringValue {
     StringValue(char* ptr, int len) : ptr(ptr), len(len) {}
     StringValue(const char* ptr, int len) : ptr(const_cast<char*>(ptr)), 
len(len) {}
     StringValue() : ptr(nullptr), len(0) {}
+    StringValue(const StringRef& str) : ptr(const_cast<char*>(str.data)), 
len(str.size) {}
 
     /// Construct a StringValue from 's'.  's' must be valid for as long as
     /// this object is valid.
diff --git a/be/src/util/bitmap_intersect.h b/be/src/util/bitmap_intersect.h
new file mode 100644
index 0000000000..dcda6ae5a5
--- /dev/null
+++ b/be/src/util/bitmap_intersect.h
@@ -0,0 +1,245 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements.  See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership.  The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License.  You may obtain a copy of the License at
+//
+//   http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied.  See the License for the
+// specific language governing permissions and limitations
+// under the License.
+#pragma once
+#include "runtime/string_value.h"
+#include "udf/udf.h"
+#include "util/bitmap_value.h"
+
+namespace doris {
+
+namespace detail {
+class Helper {
+public:
+    static const int DATETIME_PACKED_TIME_BYTE_SIZE = 8;
+    static const int DATETIME_TYPE_BYTE_SIZE = 4;
+    static const int DECIMAL_BYTE_SIZE = 16;
+
+    // get_val start
+    template <typename ValType, typename T>
+    static T get_val(const ValType& x) {
+        DCHECK(!x.is_null);
+        return x.val;
+    }
+
+    // serialize_size start
+    template <typename T>
+    static int32_t serialize_size(const T& v) {
+        return sizeof(T);
+    }
+
+    // write_to start
+    template <typename T>
+    static char* write_to(const T& v, char* dest) {
+        size_t type_size = sizeof(T);
+        memcpy(dest, &v, type_size);
+        dest += type_size;
+        return dest;
+    }
+
+    // read_from start
+    template <typename T>
+    static void read_from(const char** src, T* result) {
+        size_t type_size = sizeof(T);
+        memcpy(result, *src, type_size);
+        *src += type_size;
+    }
+};
+
+template <>
+inline StringValue Helper::get_val<StringVal>(const StringVal& x) {
+    DCHECK(!x.is_null);
+    return StringValue::from_string_val(x);
+}
+
+template <>
+inline DateTimeValue Helper::get_val<DateTimeVal>(const DateTimeVal& x) {
+    return DateTimeValue::from_datetime_val(x);
+}
+
+template <>
+inline DecimalV2Value Helper::get_val<DecimalV2Val>(const DecimalV2Val& x) {
+    return DecimalV2Value::from_decimal_val(x);
+}
+// get_val end
+
+template <>
+inline char* Helper::write_to<DateTimeValue>(const DateTimeValue& v, char* 
dest) {
+    DateTimeVal value;
+    v.to_datetime_val(&value);
+    *(int64_t*)dest = value.packed_time;
+    dest += DATETIME_PACKED_TIME_BYTE_SIZE;
+    *(int*)dest = value.type;
+    dest += DATETIME_TYPE_BYTE_SIZE;
+    return dest;
+}
+
+template <>
+inline char* Helper::write_to<DecimalV2Value>(const DecimalV2Value& v, char* 
dest) {
+    __int128 value = v.value();
+    memcpy(dest, &value, DECIMAL_BYTE_SIZE);
+    dest += DECIMAL_BYTE_SIZE;
+    return dest;
+}
+
+template <>
+inline char* Helper::write_to<StringValue>(const StringValue& v, char* dest) {
+    *(int32_t*)dest = v.len;
+    dest += 4;
+    memcpy(dest, v.ptr, v.len);
+    dest += v.len;
+    return dest;
+}
+// write_to end
+
+template <>
+inline int32_t Helper::serialize_size<DateTimeValue>(const DateTimeValue& v) {
+    return Helper::DATETIME_PACKED_TIME_BYTE_SIZE + 
Helper::DATETIME_TYPE_BYTE_SIZE;
+}
+
+template <>
+inline int32_t Helper::serialize_size<DecimalV2Value>(const DecimalV2Value& v) 
{
+    return Helper::DECIMAL_BYTE_SIZE;
+}
+
+template <>
+inline int32_t Helper::serialize_size<StringValue>(const StringValue& v) {
+    return v.len + 4;
+}
+// serialize_size end
+
+template <>
+inline void Helper::read_from<DateTimeValue>(const char** src, DateTimeValue* 
result) {
+    DateTimeVal value;
+    value.is_null = false;
+    value.packed_time = *(int64_t*)(*src);
+    *src += DATETIME_PACKED_TIME_BYTE_SIZE;
+    value.type = *(int*)(*src);
+    *src += DATETIME_TYPE_BYTE_SIZE;
+    *result = DateTimeValue::from_datetime_val(value);
+}
+
+template <>
+inline void Helper::read_from<DecimalV2Value>(const char** src, 
DecimalV2Value* result) {
+    __int128 v = 0;
+    memcpy(&v, *src, DECIMAL_BYTE_SIZE);
+    *src += DECIMAL_BYTE_SIZE;
+    *result = DecimalV2Value(v);
+}
+
+template <>
+inline void Helper::read_from<StringValue>(const char** src, StringValue* 
result) {
+    int32_t length = *(int32_t*)(*src);
+    *src += 4;
+    *result = StringValue((char*)*src, length);
+    *src += length;
+}
+// read_from end
+
+} // namespace detail
+
+// Calculate the intersection of two or more bitmaps
+// Usage: intersect_count(bitmap_column_to_count, filter_column, filter_values 
...)
+// Example: intersect_count(user_id, event, 'A', 'B', 'C'), meaning find the 
intersect count of user_id in all A/B/C 3 bitmaps
+// Todo(kks) Use Array type instead of variable arguments
+template <typename T>
+struct BitmapIntersect {
+public:
+    BitmapIntersect() = default;
+
+    explicit BitmapIntersect(const char* src) { deserialize(src); }
+
+    void add_key(const T key) {
+        BitmapValue empty_bitmap;
+        _bitmaps[key] = empty_bitmap;
+    }
+
+    void update(const T& key, const BitmapValue& bitmap) {
+        if (_bitmaps.find(key) != _bitmaps.end()) {
+            _bitmaps[key] |= bitmap;
+        }
+    }
+
+    void merge(const BitmapIntersect& other) {
+        for (auto& kv : other._bitmaps) {
+            if (_bitmaps.find(kv.first) != _bitmaps.end()) {
+                _bitmaps[kv.first] |= kv.second;
+            } else {
+                _bitmaps[kv.first] = kv.second;
+            }
+        }
+    }
+
+    // intersection
+    BitmapValue intersect() const {
+        BitmapValue result;
+        auto it = _bitmaps.begin();
+        result |= it->second;
+        it++;
+        for (; it != _bitmaps.end(); it++) {
+            result &= it->second;
+        }
+        return result;
+    }
+
+    // calculate the intersection for _bitmaps's bitmap values
+    int64_t intersect_count() const {
+        if (_bitmaps.empty()) {
+            return 0;
+        }
+        return intersect().cardinality();
+    }
+
+    // the serialize size
+    size_t size() {
+        size_t size = 4;
+        for (auto& kv : _bitmaps) {
+            size += detail::Helper::serialize_size(kv.first);
+            size += kv.second.getSizeInBytes();
+        }
+        return size;
+    }
+
+    //must call size() first
+    void serialize(char* dest) {
+        char* writer = dest;
+        *(int32_t*)writer = _bitmaps.size();
+        writer += 4;
+        for (auto& kv : _bitmaps) {
+            writer = detail::Helper::write_to(kv.first, writer);
+            kv.second.write(writer);
+            writer += kv.second.getSizeInBytes();
+        }
+    }
+
+    void deserialize(const char* src) {
+        const char* reader = src;
+        int32_t bitmaps_size = *(int32_t*)reader;
+        reader += 4;
+        for (int32_t i = 0; i < bitmaps_size; i++) {
+            T key;
+            detail::Helper::read_from(&reader, &key);
+            BitmapValue bitmap(reader);
+            reader += bitmap.getSizeInBytes();
+            _bitmaps[key] = bitmap;
+        }
+    }
+
+private:
+    std::map<T, BitmapValue> _bitmaps;
+};
+
+} // namespace doris
diff --git a/be/src/vec/CMakeLists.txt b/be/src/vec/CMakeLists.txt
index 5a81b42ccd..3b18357086 100644
--- a/be/src/vec/CMakeLists.txt
+++ b/be/src/vec/CMakeLists.txt
@@ -39,6 +39,8 @@ set(VEC_FILES
   aggregate_functions/aggregate_function_group_concat.cpp
   aggregate_functions/aggregate_function_percentile_approx.cpp
   aggregate_functions/aggregate_function_simple_factory.cpp
+  aggregate_functions/aggregate_function_java_udaf.h
+  aggregate_functions/aggregate_function_orthogonal_bitmap.cpp
   columns/collator.cpp
   columns/column.cpp
   columns/column_const.cpp
diff --git 
a/be/src/vec/aggregate_functions/aggregate_function_orthogonal_bitmap.cpp 
b/be/src/vec/aggregate_functions/aggregate_function_orthogonal_bitmap.cpp
new file mode 100644
index 0000000000..470a6c8388
--- /dev/null
+++ b/be/src/vec/aggregate_functions/aggregate_function_orthogonal_bitmap.cpp
@@ -0,0 +1,99 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements.  See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership.  The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License.  You may obtain a copy of the License at
+//
+//   http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied.  See the License for the
+// specific language governing permissions and limitations
+// under the License.
+
+#include "vec/aggregate_functions/aggregate_function_orthogonal_bitmap.h"
+
+#include <memory>
+
+#include "vec/aggregate_functions/aggregate_function_simple_factory.h"
+#include "vec/aggregate_functions/helpers.h"
+#include "vec/data_types/data_type_string.h"
+
+namespace doris::vectorized {
+
+template <template <typename> class Impl>
+AggregateFunctionPtr create_aggregate_function_orthogonal(const std::string& 
name,
+                                                          const DataTypes& 
argument_types,
+                                                          const Array& params,
+                                                          const bool 
result_is_nullable) {
+    if (argument_types.empty()) {
+        LOG(WARNING) << "Incorrect number of arguments for aggregate function 
" << name;
+        return nullptr;
+    } else if (argument_types.size() == 1) {
+        // only used at AGGREGATE (merge finalize) for variadic function
+        // and for orthogonal_bitmap_union_count function
+        return 
std::make_shared<AggFunctionOrthBitmapFunc<Impl<StringValue>>>(argument_types);
+    } else {
+        const IDataType& argument_type = *argument_types[1];
+        AggregateFunctionPtr 
res(create_with_numeric_type<AggFunctionOrthBitmapFunc, Impl>(
+                argument_type, argument_types));
+
+        WhichDataType which(argument_type);
+
+        if (res) {
+            return res;
+        } else if (which.is_string_or_fixed_string()) {
+            return 
std::make_shared<AggFunctionOrthBitmapFunc<Impl<StringValue>>>(argument_types);
+        }
+        LOG(WARNING) << "Incorrect Type " << argument_type.get_name()
+                     << " of arguments for aggregate function " << name;
+        return nullptr;
+    }
+}
+
+AggregateFunctionPtr create_aggregate_function_orthogonal_bitmap_intersect(
+        const std::string& name, const DataTypes& argument_types, const Array& 
parameters,
+        bool result_is_nullable) {
+    return create_aggregate_function_orthogonal<AggOrthBitMapIntersect>(
+            name, argument_types, parameters, result_is_nullable);
+}
+
+AggregateFunctionPtr 
create_aggregate_function_orthogonal_bitmap_intersect_count(
+        const std::string& name, const DataTypes& argument_types, const Array& 
parameters,
+        bool result_is_nullable) {
+    return create_aggregate_function_orthogonal<AggOrthBitMapIntersectCount>(
+            name, argument_types, parameters, result_is_nullable);
+}
+
+AggregateFunctionPtr create_aggregate_function_intersect_count(const 
std::string& name,
+                                                               const 
DataTypes& argument_types,
+                                                               const Array& 
parameters,
+                                                               bool 
result_is_nullable) {
+    return create_aggregate_function_orthogonal<AggIntersectCount>(name, 
argument_types, parameters,
+                                                                   
result_is_nullable);
+}
+
+AggregateFunctionPtr create_aggregate_function_orthogonal_bitmap_union_count(
+        const std::string& name, const DataTypes& argument_types, const Array& 
parameters,
+        const bool result_is_nullable) {
+    return create_aggregate_function_orthogonal<OrthBitmapUnionCountData>(
+            name, argument_types, parameters, result_is_nullable);
+}
+
+void 
register_aggregate_function_orthogonal_bitmap(AggregateFunctionSimpleFactory& 
factory) {
+    factory.register_function("orthogonal_bitmap_intersect",
+                              
create_aggregate_function_orthogonal_bitmap_intersect);
+
+    factory.register_function("orthogonal_bitmap_intersect_count",
+                              
create_aggregate_function_orthogonal_bitmap_intersect_count);
+
+    factory.register_function("orthogonal_bitmap_union_count",
+                              
create_aggregate_function_orthogonal_bitmap_union_count);
+
+    factory.register_function("intersect_count", 
create_aggregate_function_intersect_count);
+}
+} // namespace doris::vectorized
\ No newline at end of file
diff --git 
a/be/src/vec/aggregate_functions/aggregate_function_orthogonal_bitmap.h 
b/be/src/vec/aggregate_functions/aggregate_function_orthogonal_bitmap.h
new file mode 100644
index 0000000000..4f1fb69ec4
--- /dev/null
+++ b/be/src/vec/aggregate_functions/aggregate_function_orthogonal_bitmap.h
@@ -0,0 +1,247 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements.  See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership.  The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License.  You may obtain a copy of the License at
+//
+//   http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied.  See the License for the
+// specific language governing permissions and limitations
+// under the License.
+
+#pragma once
+
+#include "exprs/bitmap_function.h"
+#include "util/bitmap_intersect.h"
+#include "util/bitmap_value.h"
+#include "vec/aggregate_functions/aggregate_function.h"
+#include "vec/columns/column_complex.h"
+#include "vec/columns/column_nullable.h"
+#include "vec/columns/column_vector.h"
+#include "vec/common/assert_cast.h"
+#include "vec/core/types.h"
+#include "vec/data_types/data_type_bitmap.h"
+#include "vec/data_types/data_type_nullable.h"
+#include "vec/data_types/data_type_number.h"
+#include "vec/io/io_helper.h"
+
+namespace doris::vectorized {
+
+template <typename T>
+struct AggOrthBitmapBaseData {
+public:
+    using ColVecData = std::conditional_t<IsNumber<T>, ColumnVector<T>, 
ColumnString>;
+
+    void add(const IColumn** columns, size_t row_num) {
+        const auto& bitmap_col = static_cast<const ColumnBitmap&>(*columns[0]);
+        const auto& data_col = static_cast<const ColVecData&>(*columns[1]);
+        const auto& bitmap_value = bitmap_col.get_element(row_num);
+
+        if constexpr (IsNumber<T>) {
+            bitmap.update(data_col.get_element(row_num), bitmap_value);
+        } else {
+            bitmap.update(StringValue(data_col.get_data_at(row_num)), 
bitmap_value);
+        }
+    }
+
+    void init_add_key(const IColumn** columns, size_t row_num, int 
argument_size) {
+        if (first_init) {
+            DCHECK(argument_size > 1);
+            for (int idx = 2; idx < argument_size; ++idx) {
+                const auto& col = static_cast<const 
ColVecData&>(*columns[idx]);
+                if constexpr (IsNumber<T>) {
+                    bitmap.add_key(col.get_element(row_num));
+                } else {
+                    bitmap.add_key(StringValue(col.get_data_at(row_num)));
+                }
+            }
+            first_init = false;
+        }
+    }
+
+protected:
+    doris::BitmapIntersect<T> bitmap;
+    bool first_init = true;
+};
+
+template <typename T>
+struct AggOrthBitMapIntersect : public AggOrthBitmapBaseData<T> {
+public:
+    static constexpr auto name = "orthogonal_bitmap_intersect";
+
+    static DataTypePtr get_return_type() { return 
std::make_shared<DataTypeBitMap>(); }
+
+    void merge(const AggOrthBitMapIntersect& rhs) {
+        if (rhs.first_init) {
+            return;
+        }
+        result |= rhs.result;
+    }
+
+    void write(BufferWritable& buf) {
+        write_binary(AggOrthBitmapBaseData<T>::first_init, buf);
+        result = AggOrthBitmapBaseData<T>::bitmap.intersect();
+        DataTypeBitMap::serialize_as_stream(result, buf);
+    }
+
+    void read(BufferReadable& buf) {
+        read_binary(AggOrthBitmapBaseData<T>::first_init, buf);
+        DataTypeBitMap::deserialize_as_stream(result, buf);
+    }
+
+    void get(IColumn& to) const {
+        auto& column = static_cast<ColumnBitmap&>(to);
+        column.get_data().emplace_back(result);
+    }
+
+private:
+    BitmapValue result;
+};
+
+template <typename T>
+struct AggIntersectCount : public AggOrthBitmapBaseData<T> {
+public:
+    static constexpr auto name = "intersect_count";
+
+    static DataTypePtr get_return_type() { return 
std::make_shared<DataTypeInt64>(); }
+
+    void merge(const AggIntersectCount& rhs) {
+        if (rhs.first_init) {
+            return;
+        }
+        AggOrthBitmapBaseData<T>::bitmap.merge(rhs.bitmap);
+    }
+
+    void write(BufferWritable& buf) {
+        write_binary(AggOrthBitmapBaseData<T>::first_init, buf);
+        std::string data;
+        data.resize(AggOrthBitmapBaseData<T>::bitmap.size());
+        AggOrthBitmapBaseData<T>::bitmap.serialize(data.data());
+        write_binary(data, buf);
+    }
+
+    void read(BufferReadable& buf) {
+        read_binary(AggOrthBitmapBaseData<T>::first_init, buf);
+        std::string data;
+        read_binary(data, buf);
+        AggOrthBitmapBaseData<T>::bitmap.deserialize(data.data());
+    }
+
+    void get(IColumn& to) const {
+        auto& column = static_cast<ColumnVector<Int64>&>(to);
+        
column.get_data().emplace_back(AggOrthBitmapBaseData<T>::bitmap.intersect_count());
+    }
+};
+
+template <typename T>
+struct AggOrthBitMapIntersectCount : public AggOrthBitmapBaseData<T> {
+public:
+    static constexpr auto name = "orthogonal_bitmap_intersect_count";
+
+    static DataTypePtr get_return_type() { return 
std::make_shared<DataTypeInt64>(); }
+
+    void merge(const AggOrthBitMapIntersectCount& rhs) {
+        if (rhs.first_init) {
+            return;
+        }
+        result += rhs.result;
+    }
+
+    void write(BufferWritable& buf) {
+        write_binary(AggOrthBitmapBaseData<T>::first_init, buf);
+        result = AggOrthBitmapBaseData<T>::bitmap.intersect_count();
+        write_binary(result, buf);
+    }
+
+    void read(BufferReadable& buf) {
+        read_binary(AggOrthBitmapBaseData<T>::first_init, buf);
+        read_binary(result, buf);
+    }
+
+    void get(IColumn& to) const {
+        auto& column = static_cast<ColumnVector<Int64>&>(to);
+        column.get_data().emplace_back(result);
+    }
+
+private:
+    Int64 result = 0;
+};
+
+template <typename T>
+struct OrthBitmapUnionCountData {
+    static constexpr auto name = "orthogonal_bitmap_union_count";
+
+    static DataTypePtr get_return_type() { return 
std::make_shared<DataTypeInt64>(); }
+    // Here no need doing anything, so only given an function declaration
+    void init_add_key(const IColumn** columns, size_t row_num, int 
argument_size) {}
+
+    void add(const IColumn** columns, size_t row_num) {
+        const auto& column = static_cast<const ColumnBitmap&>(*columns[0]);
+        value |= column.get_data()[row_num];
+    }
+    void merge(const OrthBitmapUnionCountData& rhs) { result += rhs.result; }
+
+    void write(BufferWritable& buf) {
+        result = value.cardinality();
+        write_binary(result, buf);
+    }
+
+    void read(BufferReadable& buf) { read_binary(result, buf); }
+
+    void get(IColumn& to) const {
+        auto& column = static_cast<ColumnVector<Int64>&>(to);
+        column.get_data().emplace_back(result ? result : value.cardinality());
+    }
+
+private:
+    BitmapValue value;
+    int64_t result = 0;
+};
+
+template <typename Impl>
+class AggFunctionOrthBitmapFunc final
+        : public IAggregateFunctionDataHelper<Impl, 
AggFunctionOrthBitmapFunc<Impl>> {
+public:
+    String get_name() const override { return Impl::name; }
+
+    AggFunctionOrthBitmapFunc(const DataTypes& argument_types_)
+            : IAggregateFunctionDataHelper<Impl, 
AggFunctionOrthBitmapFunc<Impl>>(argument_types_,
+                                                                               
   {}),
+              _argument_size(argument_types_.size()) {}
+
+    DataTypePtr get_return_type() const override { return 
Impl::get_return_type(); }
+
+    void add(AggregateDataPtr __restrict place, const IColumn** columns, 
size_t row_num,
+             Arena*) const override {
+        this->data(place).init_add_key(columns, row_num, _argument_size);
+        this->data(place).add(columns, row_num);
+    }
+
+    void merge(AggregateDataPtr __restrict place, ConstAggregateDataPtr rhs,
+               Arena*) const override {
+        this->data(place).merge(this->data(rhs));
+    }
+
+    void serialize(ConstAggregateDataPtr __restrict place, BufferWritable& 
buf) const override {
+        this->data(const_cast<AggregateDataPtr>(place)).write(buf);
+    }
+
+    void deserialize(AggregateDataPtr __restrict place, BufferReadable& buf,
+                     Arena*) const override {
+        this->data(place).read(buf);
+    }
+
+    void insert_result_into(ConstAggregateDataPtr __restrict place, IColumn& 
to) const override {
+        this->data(place).get(to);
+    }
+
+private:
+    int _argument_size;
+};
+} // namespace doris::vectorized
\ No newline at end of file
diff --git 
a/be/src/vec/aggregate_functions/aggregate_function_simple_factory.cpp 
b/be/src/vec/aggregate_functions/aggregate_function_simple_factory.cpp
index 6315fd6600..3fa99b908d 100644
--- a/be/src/vec/aggregate_functions/aggregate_function_simple_factory.cpp
+++ b/be/src/vec/aggregate_functions/aggregate_function_simple_factory.cpp
@@ -46,6 +46,7 @@ void 
register_aggregate_function_group_concat(AggregateFunctionSimpleFactory& fa
 void register_aggregate_function_percentile(AggregateFunctionSimpleFactory& 
factory);
 void register_aggregate_function_window_funnel(AggregateFunctionSimpleFactory& 
factory);
 void 
register_aggregate_function_percentile_approx(AggregateFunctionSimpleFactory& 
factory);
+void 
register_aggregate_function_orthogonal_bitmap(AggregateFunctionSimpleFactory& 
factory);
 AggregateFunctionSimpleFactory& AggregateFunctionSimpleFactory::instance() {
     static std::once_flag oc;
     static AggregateFunctionSimpleFactory instance;
@@ -67,6 +68,7 @@ AggregateFunctionSimpleFactory& 
AggregateFunctionSimpleFactory::instance() {
         register_aggregate_function_percentile(instance);
         register_aggregate_function_percentile_approx(instance);
         register_aggregate_function_window_funnel(instance);
+        register_aggregate_function_orthogonal_bitmap(instance);
 
         // if you only register function with no nullable, and wants to add 
nullable automatically, you should place function above this line
         register_aggregate_function_combinator_null(instance);
diff --git a/be/test/exprs/bitmap_function_test.cpp 
b/be/test/exprs/bitmap_function_test.cpp
index 334ba7aa73..34c3155551 100644
--- a/be/test/exprs/bitmap_function_test.cpp
+++ b/be/test/exprs/bitmap_function_test.cpp
@@ -27,6 +27,7 @@
 #include "exprs/aggregate_functions.h"
 #include "exprs/anyval_util.h"
 #include "testutil/function_utils.h"
+#include "util/bitmap_intersect.h"
 #include "util/bitmap_value.h"
 #include "util/logging.h"
 
@@ -266,10 +267,10 @@ void test_bitmap_intersect(FunctionContext* ctx, ValType 
key1, ValType key2) {
     BitmapIntersect<ValueType> intersect2;
     for (size_t i = 2; i < const_vals.size(); i++) {
         ValType* arg = reinterpret_cast<ValType*>(const_vals[i]);
-        intersect2.add_key(detail::get_val<ValType, ValueType>(*arg));
+        intersect2.add_key(detail::Helper::get_val<ValType, ValueType>(*arg));
     }
-    intersect2.update(detail::get_val<ValType, ValueType>(key1), bitmap1);
-    intersect2.update(detail::get_val<ValType, ValueType>(key2), bitmap2);
+    intersect2.update(detail::Helper::get_val<ValType, ValueType>(key1), 
bitmap1);
+    intersect2.update(detail::Helper::get_val<ValType, ValueType>(key2), 
bitmap2);
     StringVal expected = convert_bitmap_intersect_to_string(ctx, intersect2);
     ASSERT_EQ(expected, intersect1);
 
diff --git a/docs/.vuepress/sidebar/en/docs.js 
b/docs/.vuepress/sidebar/en/docs.js
new file mode 100644
index 0000000000..f7ad6c58df
--- /dev/null
+++ b/docs/.vuepress/sidebar/en/docs.js
@@ -0,0 +1,1009 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+module.exports = [
+  {
+    title: "Getting Started",
+    directoryPath: "get-starting/",
+    initialOpenGroupIndex: -1,
+    children: [
+      "get-starting"
+    ],
+  },
+  {
+    title: "Doris Architecture",
+    directoryPath: "summary/",
+    initialOpenGroupIndex: -1,
+    children: [
+      "basic-summary",
+      "system-architecture"
+    ],
+  },
+  {
+    title: "Install And Deploy",
+    directoryPath: "install/",
+    initialOpenGroupIndex: -1,
+    children: [
+      "install-deploy",
+      {
+        title: "Compile",
+        directoryPath: "source-install/",
+        initialOpenGroupIndex: -1,
+        children: [
+          "compilation",
+          "compilation-with-ldb-toolchain",
+          "compilation-arm"
+        ],
+        sidebarDepth: 2,
+      },
+    ]
+  },
+  {
+    title: "Table Design",
+    directoryPath: "data-table/",
+    initialOpenGroupIndex: -1,
+    children: [
+      "data-model",
+      "data-partition",
+      "basic-usage",
+      "advance-usage",
+      "hit-the-rollup",
+      "best-practice",
+      {
+        title: "Index",
+        directoryPath: "index/",
+        initialOpenGroupIndex: -1,
+        children: [
+          "bloomfilter",
+          "prefix-index",
+          "bitmap-index"
+        ],
+      },
+    ],
+  },
+  {
+    title: "Data Operation",
+    directoryPath: "data-operate/",
+    initialOpenGroupIndex: -1,
+    children: [
+      {
+        title: "Import",
+        directoryPath: "import/",
+        initialOpenGroupIndex: -1,
+        children: [
+          "load-manual",
+          {
+            title: "Import Scenes",
+            directoryPath: "import-scenes/",
+            initialOpenGroupIndex: -1,
+            children: [
+              "local-file-load",
+              "external-storage-load",
+              "kafka-load",
+              "external-table-load",
+              "jdbc-load",
+              "load-atomicity",
+              "load-data-convert",
+              "load-strict-mode",
+            ],
+          },
+          {
+            title: "Import Way",
+            directoryPath: "import-way/",
+            initialOpenGroupIndex: -1,
+            children: [
+              "binlog-load-manual",
+              "broker-load-manual",
+              "routine-load-manual",
+              "spark-load-manual",
+              "stream-load-manual",
+              "s3-load-manual",
+              "insert-into-manual",
+              "load-json-format", 
+            ],
+          },                
+        ],
+      },
+      {
+        title: "Export",
+        directoryPath: "export/",
+        initialOpenGroupIndex: -1,
+        children: [
+          "export-manual",
+          "outfile",
+          "export_with_mysql_dump",
+        ],
+      },
+      {
+        title: "Update and Delete",
+        directoryPath: "update-delete/",
+        initialOpenGroupIndex: -1,
+        children: [
+          "update",
+          "sequence-column-manual",
+          "delete-manual",
+          "batch-delete-manual"
+        ],
+      },
+    ],
+  },
+  {
+    title: "Advanced Usage",
+    directoryPath: "advanced/",
+    initialOpenGroupIndex: -1,
+    children: [
+      "materialized-view",
+      {
+        title: "Alter Table",
+        directoryPath: "alter-table/",
+        initialOpenGroupIndex: -1,
+        children: [
+          "schema-change",
+          "replace-table"
+        ],
+      },
+      {
+        title: "Doris Partition",
+        directoryPath: "partition/",
+        initialOpenGroupIndex: -1,
+        children: [
+          "dynamic-partition",
+          "table-temp-partition"
+        ],
+      },
+      {
+        title: "Join Optimization",
+        directoryPath: "join-optimization/",
+        initialOpenGroupIndex: -1,
+        children: [
+          "bucket-shuffle-join",
+          "colocation-join",
+          "runtime-filter",
+          "doris-join-optimization"
+        ],
+      },
+      {
+        title: "Date Cache",
+        directoryPath: "cache/",
+        initialOpenGroupIndex: -1,
+        children: [
+          "partition-cache"
+        ],
+      },
+      "vectorized-execution-engine",
+      "broker",
+      "resource",
+      "orthogonal-bitmap-manual",
+      "using-hll",
+      "variables",
+      "time-zone",
+      "small-file-mgr",
+      {
+        title: "Best Practice",
+        directoryPath: "best-practice/",
+        initialOpenGroupIndex: -1,
+        children: [
+          "query-analysis",
+          "import-analysis",
+          "debug-log"
+        ]
+      }
+    ],
+  },
+  {
+    title: "Ecosystem",
+    directoryPath: "ecosystem/",
+    initialOpenGroupIndex: -1,
+    children: [
+      {
+        title: "Expansion table",
+        directoryPath: "external-table/",
+        initialOpenGroupIndex: -1,
+        children: [
+          "doris-on-es",
+          "odbc-of-doris",
+          "hive-of-doris",
+          "iceberg-of-doris",
+          "hudi-external-table"
+        ],
+      },
+      "audit-plugin",
+      "flink-doris-connector",
+      "spark-doris-connector",
+      "datax",
+      "logstash",
+      {
+        title: "Doris Manager",
+        directoryPath: "doris-manager/",
+        initialOpenGroupIndex: -1,
+        children: [
+          "compiling-deploying",
+          "initializing",
+          "cluster-managenent",
+          "space-list",
+          "space-management",
+          "system-settings"
+        ],
+      },
+      {
+        title: "SeaTunnel",
+        directoryPath: "seatunnel/",
+        initialOpenGroupIndex: -1,
+        children: [
+          "flink-sink",
+          "spark-sink"
+        ],
+      },
+      {
+        title: "UDF",
+        directoryPath: "udf/",
+        initialOpenGroupIndex: -1,
+        children: [
+          "native-user-defined-function",
+          "remote-user-defined-function",
+          "contribute-udf",
+          "java-user-defined-function"
+        ],
+      },
+    ],
+  },
+  {
+    title: "SQL Manual",
+    directoryPath: "sql-manual/",
+    initialOpenGroupIndex: -1,
+    children: [
+      {
+        title: "SQL Functions",
+        directoryPath: "sql-functions/",
+        initialOpenGroupIndex: -1,
+        children: [
+          {
+            title: "Date Functions",
+            directoryPath: "date-time-functions/",
+            initialOpenGroupIndex: -1,
+            children: [
+              "convert_tz",
+              "curdate",
+              "current_timestamp",
+              "curtime",
+              "date_add",
+              "date_format",
+              "date_sub",
+              "datediff",
+              "day",
+              "dayname",
+              "dayofmonth",
+              "dayofweek",
+              "dayofyear",
+              "from_days",
+              "from_unixtime",
+              "hour",
+              "makedate",
+              "minute",
+              "month",
+              "monthname",
+              "now",
+              "second",
+              "str_to_date",
+              "time_round",
+              "timediff",
+              "timestampadd",
+              "timestampdiff",
+              "to_days",
+              "unix_timestamp",
+              "utc_timestamp",
+              "week",
+              "weekday",
+              "weekofyear",
+              "year",
+              "yearweek",
+            ],
+          },
+          {
+            title: "GIS Functions",
+            directoryPath: "spatial-functions/",
+            initialOpenGroupIndex: -1,
+            children: [
+              "st_astext",
+              "st_circle",
+              "st_contains",
+              "st_distance_sphere",
+              "st_geometryfromtext",
+              "st_linefromtext",
+              "st_point",
+              "st_polygon",
+              "st_x",
+              "st_y",
+            ],
+          },
+          {
+            title: "String Functions",
+            directoryPath: "string-functions/",
+            initialOpenGroupIndex: -1,
+            children: [
+              "append_trailing_char_if_absent",
+              "ascii",
+              "bit_length",
+              "char_length",
+              "concat",
+              "concat_ws",
+              "ends_with",
+              "find_in_set",
+              "hex",
+              "instr",
+              "lcase",
+              "left",
+              "length",
+              "locate",
+              "lower",
+              "lpad",
+              "ltrim",
+              "money_format",
+              "null_or_empty",
+              "repeat",
+              "replace",
+              "reverse",
+              "right",
+              "rpad",
+              "split_part",
+              "starts_with",
+              "strleft",
+              "strright",
+              "substring",
+              "unhex",
+              {
+                title: "Fuzzy Match",
+                directoryPath: "like/",
+                initialOpenGroupIndex: -1,
+                children: [
+                  "like",
+                  "not_like",
+                ],
+              },
+              {
+                title: "Regular Match",
+                directoryPath: "regexp/",
+                initialOpenGroupIndex: -1,
+                children: [
+                  "regexp",
+                  "regexp_extract",
+                  "regexp_replace",
+                  "not_regexp",
+                ],
+              },
+            ],
+          },
+          {
+            title: "Aggregate Functions",
+            directoryPath: "aggregate-functions/",
+            initialOpenGroupIndex: -1,
+            children: [
+              "approx_count_distinct",
+              "avg",
+              "bitmap_union",
+              "count",
+              "group_concat",
+              "hll_union_agg",
+              "max",
+              "max_by",
+              "min",
+              "min_by",
+              "percentile",
+              "percentile_approx",
+              "stddev",
+              "stddev_samp",
+              "sum",
+              "topn",
+              "var_samp",
+              "variance",
+            ],
+          },
+          {
+            title: "Bitmap Functions",
+            directoryPath: "bitmap-functions/",
+            initialOpenGroupIndex: -1,
+            children: [
+              "bitmap_and",
+              "bitmap_contains",
+              "bitmap_empty",
+              "bitmap_from_string",
+              "bitmap_has_any",
+              "bitmap_has_all",
+              "bitmap_hash",
+              "bitmap_intersect",
+              "bitmap_or",
+              "bitmap_and_count",
+              "bitmap_or_count",
+              "bitmap_xor",
+              "bitmap_xor_count",
+              "bitmap_not",
+              "bitmap_and_not",
+              "bitmap_and_not_count",
+              "bitmap_subset_in_range",
+              "bitmap_subset_limit",
+              "sub_bitmap",
+              "bitmap_to_string",
+              "bitmap_union",
+              "bitmap_xor",
+              "to_bitmap",
+              "bitmap_max",
+              "intersect_count",
+              "orthogonal_bitmap_intersect",
+              "orthogonal_bitmap_intersect_count",
+              "orthogonal_bitmap_union_count",
+            ],
+          },
+          {
+            title: "Bitwise Functions",
+            directoryPath: "bitwise-functions/",
+            initialOpenGroupIndex: -1,
+            children: [
+              "bitand",
+              "bitor",
+              "bitxor",
+              "bitnot"
+            ],
+          },
+          {
+            title: "Condition Functions",
+            directoryPath: "conditional-functions/",
+            children: [
+              "case",
+              "coalesce",
+              "if",
+              "ifnull",
+              "nvl",
+              "nullif"
+            ],
+          },
+          {
+            title: "JSON Functions",
+            directoryPath: "json-functions/",
+            initialOpenGroupIndex: -1,
+            children: [
+              "get_json_double",
+              "get_json_int",
+              "get_json_string",
+              "json_array",
+              "json_object",
+              "json_quote",
+            ],
+          },
+          {
+            title: "Hash Functions",
+            directoryPath: "hash-functions/",
+            initialOpenGroupIndex: -1,
+            children: ["murmur_hash3_32"],
+          },
+          {
+            title: "Math Functions",
+            directoryPath: "math-functions/",
+            initialOpenGroupIndex: -1,
+            children: [
+              "conv",
+              "pmod"
+            ],
+          },
+          {
+            title: "Encryption Functions",
+            directoryPath: "encrypt-digest-functions/",
+            initialOpenGroupIndex: -1,
+            children: [
+              "aes",
+              "md5",
+              "md5sum",
+              "sm4",
+              "sm3",
+              "sm3sum"
+            ],
+          },
+          {
+            title: "Table Functions",
+            directoryPath: "table-functions/",
+            initialOpenGroupIndex: -1,
+            children: [
+              "explode-bitmap",
+              "explode-split",
+              "explode-json-array",
+              "outer-combinator"
+            ],
+          },
+          {
+            title: "Analytic(Window) Functions",
+            directoryPath: "window-functions/",
+            initialOpenGroupIndex: -1,
+            children: [
+              "WINDOW-FUNCTION",
+              "WINDOW-FUNCTION-SUM",
+              "WINDOW-FUNCTION-AVG",
+              "WINDOW-FUNCTION-COUNT",
+              "WINDOW-FUNCTION-MIN",
+              "WINDOW-FUNCTION-MAX",
+              "WINDOW-FUNCTION-LEAD",
+              "WINDOW-FUNCTION-LAG",
+              "WINDOW-FUNCTION-RANK",
+              "WINDOW-FUNCTION-DENSE-RANK",
+              "WINDOW-FUNCTION-FIRST-VALUE",
+              "WINDOW-FUNCTION-LAST-VALUE",
+              "WINDOW-FUNCTION-ROW-NUMBER",
+              "WINDOW-FUNCTION-NTILE",
+            ],
+          },
+          {
+            title: "Array Functions",
+            directoryPath: "array-functions/",
+            initialOpenGroupIndex: -1,
+            children: [
+              "array_contains",
+              "array_position",
+              "element_at",
+            ],
+          },
+          "cast",
+          "digital-masking",
+        ],
+      },
+      {
+        title: "SQL Reference",
+        directoryPath: "sql-reference/",
+        initialOpenGroupIndex: -1,
+        children: [
+          {
+            title: "Account Management",
+            directoryPath: "Account-Management-Statements/",
+            initialOpenGroupIndex: -1,
+            children: [
+              "CREATE-USER",
+              "CREATE-ROLE",
+              "DROP-ROLE",
+              "DROP-USER",
+              "GRANT",
+              "REVOKE",
+              "SET-PASSWORD",
+              "SET-PROPERTY",
+              "LDAP",
+            ],
+          },
+          {
+            title: "Cluster management",
+            directoryPath: "Cluster-Management-Statements/",
+            initialOpenGroupIndex: -1,
+            children: [
+              "ALTER-SYSTEM-ADD-BACKEND",
+              "ALTER-SYSTEM-ADD-FOLLOWER",
+              "ALTER-SYSTEM-ADD-OBSERVER",
+              "ALTER-SYSTEM-DECOMMISSION-BACKEND",
+              "ALTER-SYSTEM-DROP-BACKEND",
+              "ALTER-SYSTEM-DROP-FOLLOWER",
+              "ALTER-SYSTEM-DROP-OBSERVER",
+              "ALTER-SYSTEM-MODIFY-BROKER",
+              "CANCEL-ALTER-SYSTEM",
+            ],
+          },
+          {
+            title: "DDL",
+            directoryPath: "Data-Definition-Statements/",
+            initialOpenGroupIndex: -1,
+            children: [
+              {
+                title: "Alter",
+                directoryPath: "Alter/",
+                initialOpenGroupIndex: -1,
+                children: [
+                  "ALTER-DATABASE",
+                  "ALTER-RESOURCE",
+                  "ALTER-SQL-BLOCK-RULE",
+                  "ALTER-TABLE-COLUMN",
+                  "ALTER-TABLE-PARTITION",
+                  "ALTER-TABLE-PROPERTY",
+                  "ALTER-TABLE-RENAME",
+                  "ALTER-TABLE-REPLACE",
+                  "ALTER-TABLE-ROLLUP",
+                  "ALTER-VIEW",
+                  "CANCEL-ALTER-TABLE",
+                ],
+              },
+              {
+                title: "Backup and Restore",
+                directoryPath: "Backup-and-Restore/",
+                initialOpenGroupIndex: -1,
+                children: [
+                  "BACKUP",
+                  "CANCEL-BACKUP",
+                  "CANCEL-RESTORE",
+                  "CREATE-REPOSITORY",
+                  "DROP-REPOSITORY",
+                  "RESTORE",
+                ],
+              },
+              {
+                title: "Create",
+                directoryPath: "Create/",
+                initialOpenGroupIndex: -1,
+                children: [
+                  "CREATE-DATABASE",
+                  "CREATE-ENCRYPT-KEY",
+                  "CREATE-FILE",
+                  "CREATE-FUNCTION",
+                  "CREATE-INDEX",
+                  "CREATE-MATERIALIZED-VIEW",
+                  "CREATE-POLICY",
+                  "CREATE-RESOURCE",
+                  "CREATE-SQL-BLOCK-RULE",
+                  "CREATE-TABLE-LIKE",
+                  "CREATE-TABLE-AS-SELECT",
+                  "CREATE-TABLE",
+                  "CREATE-VIEW",
+                  "CREATE-EXTERNAL-TABLE",
+                ],
+              },
+              {
+                title: "Drop",
+                directoryPath: "Drop/",
+                initialOpenGroupIndex: -1,
+                children: [
+                  "DROP-DATABASE",
+                  "DROP-ENCRYPT-KEY",
+                  "DROP-FILE",
+                  "DROP-FUNCTION",
+                  "DROP-INDEX",
+                  "DROP-MATERIALIZED-VIEW",
+                  "DROP-RESOURCE",
+                  "DROP-SQL-BLOCK-RULE",
+                  "DROP-TABLE",
+                  "TRUNCATE-TABLE",
+                ],
+              },              
+            ],
+          },
+          {
+            title: "DML",
+            directoryPath: "Data-Manipulation-Statements/",
+            initialOpenGroupIndex: -1,
+            children: [
+              {
+                title: "Load",
+                directoryPath: "Load/",
+                initialOpenGroupIndex: -1,
+                children: [
+                  "ALTER-ROUTINE-LOAD",
+                  "BROKER-LOAD",
+                  "CANCEL-LOAD",
+                  "CREATE-ROUTINE-LOAD",
+                  "PAUSE-ROUTINE-LOAD",
+                  "RESUME-ROUTINE-LOAD",
+                  "STOP-ROUTINE-LOAD",
+                  "STREAM-LOAD",
+                  "PAUSE-SYNC-JOB",
+                  "RESUME-SYNC-JOB",
+                  "STOP-SYNC-JOB",
+                  "CREATE-SYNC-JOB",
+                ],
+              },
+              {
+                title: "Manipulation",
+                directoryPath: "Manipulation/",
+                initialOpenGroupIndex: -1,
+                children: [
+                  "DELETE",
+                  "INSERT",
+                  "UPDATE",
+                  "SELECT",
+                  "EXPORT"
+                ],
+              },
+              "OUTFILE"             
+            ],
+          },
+          {
+            title: "Database Administration",
+            directoryPath: "Database-Administration-Statements/",
+            initialOpenGroupIndex: -1,
+            children: [
+              "ADMIN-CANCEL-REPAIR",
+              "ADMIN-CHECK-TABLET",
+              "ADMIN-REPAIR-TABLE",
+              "ADMIN-SET-CONFIG",
+              "ADMIN-SET-REPLICA-STATUS",
+              "ADMIN-SHOW-CONFIG",
+              "ADMIN-SHOW-REPLICA-DISTRIBUTION",
+              "ADMIN-SHOW-REPLICA-STATUS",
+              "ENABLE-FEATURE",
+              "INSTALL-PLUGIN",
+              "KILL",
+              "RECOVER",
+              "SET-VARIABLE",
+              "UNINSTALL-PLUGIN",
+            ],
+          },
+          {
+            title: "Show",
+            directoryPath: "Show-Statements/",
+            initialOpenGroupIndex: -1,
+            children: [
+              "SHOW-ALTER",
+              "SHOW-BACKENDS",
+              "SHOW-BACKUP",
+              "SHOW-BROKER",
+              "SHOW-CHARSET",
+              "SHOW-COLLATION",
+              "SHOW-COLUMNS",
+              "SHOW-CREATE-DATABASE",
+              "SHOW-CREATE-FUNCTION",
+              "SHOW-CREATE-ROUTINE-LOAD",
+              "SHOW-CREATE-TABLE",
+              "SHOW-CREATE-MATERIALIZED-VIEW",
+              "SHOW-DATA",
+              "SHOW-DATABASE-ID",
+              "SHOW-DATABASES",
+              "SHOW-DELETE",
+              "SHOW-DYNAMIC-PARTITION",
+              "SHOW-ENCRYPT-KEY",
+              "SHOW-ENGINES",
+              "SHOW-EVENTS",
+              "SHOW-EXPORT",
+              "SHOW-FRONTENDS",
+              "SHOW-FUNCTIONS",
+              "SHOW-GRANTS",
+              "SHOW-INDEX",
+              "SHOW-LOAD-PROFILE",
+              "SHOW-LOAD-WARNINGS",
+              "SHOW-LOAD",
+              "SHOW-MIGRATIONS",
+              "SHOW-OPEN-TABLES",
+              "SHOW-PARTITION-ID",
+              "SHOW-PARTITIONS",
+              "SHOW-PLUGINS",
+              "SHOW-PROC",
+              "SHOW-PROCEDURE",
+              "SHOW-PROCESSLIST",
+              "SHOW-PROPERTY",
+              "SHOW-QUERY-PROFILE",
+              "SHOW-REPOSITORIES",
+              "SHOW-RESOURCES",
+              "SHOW-RESTORE",
+              "SHOW-ROLES",
+              "SHOW-ROLLUP",
+              "SHOW-ROUTINE-LOAD-TASK",
+              "SHOW-ROUTINE-LOAD",
+              "SHOW-SMALL-FILES",
+              "SHOW-SNAPSHOT",
+              "SHOW-SQL-BLOCK-RULE",
+              "SHOW-STATUS",
+              "SHOW-STREAM-LOAD",
+              "SHOW-SYNC-JOB",
+              "SHOW-TABLE-ID",
+              "SHOW-TABLES",
+              "SHOW-TABLE-STATUS",
+              "SHOW-TABLET",
+              "SHOW-TRANSACTION",
+              "SHOW-TRIGGERS",
+              "SHOW-TRASH",
+              // "SHOW-USER",
+              "SHOW-VARIABLES",
+              "SHOW-VIEW",
+              "SHOW-WARNING",
+              "SHOW-WHITE-LIST",
+            ],
+          },
+          {
+            title: "Data Types",
+            directoryPath: "Data-Types/",
+            initialOpenGroupIndex: -1,
+            children: [
+              "BIGINT",
+              "BITMAP",
+              "BOOLEAN",
+              "CHAR",
+              "DATE",
+              "DATETIME",
+              "DECIMAL",
+              "DOUBLE",
+              "FLOAT",
+              "HLL",
+              "INT",
+              "LARGEINT",
+              "SMALLINT",
+              "STRING",
+              "TINYINT",
+              "VARCHAR",
+              "ARRAY",
+            ],
+          },
+          {
+            title: "Utility",
+            directoryPath: "Utility-Statements/",
+            initialOpenGroupIndex: -1,
+            children: [
+              "DESCRIBE",
+              "HELP",
+              "USE",
+            ],
+          },
+        ],
+      },
+    ],
+  },
+  {
+    title: "Admin Manual",
+    directoryPath: "admin-manual/",
+    initialOpenGroupIndex: -1,
+    children: [
+      {
+        title: "cluster management",
+        directoryPath: "cluster-management/",
+        initialOpenGroupIndex: -1,
+        children: [
+          "upgrade",
+          "elastic-expansion",
+          "load-balancing"
+        ],
+      },
+      {
+        title: "Data Admin",
+        directoryPath: "data-admin/",
+        initialOpenGroupIndex: -1,
+        children: [
+          "backup",
+          "restore",
+          "delete-recover"
+        ],
+      },
+      "sql-interception",
+      "query-profile",
+      "optimization",
+      {
+        title: "Maintenance and Monitor",
+        directoryPath: "maint-monitor/",
+        initialOpenGroupIndex: -1,
+        children: [
+          {
+            title: "Monitor Metrics",
+            directoryPath: "monitor-metrics/",
+            initialOpenGroupIndex: -1,
+            children: [
+              "fe-metrics",
+              "be-metrics"
+            ],
+          },
+          "disk-capacity",
+          "metadata-operation",
+          "tablet-meta-tool",
+          "tablet-repair-and-balance",
+          "tablet-restore-tool",
+          "monitor-alert",
+          "doris-error-code",
+          "be-olap-error-code"
+        ],
+      },
+      {
+        title: "Config",
+        directoryPath: "config/",
+        initialOpenGroupIndex: -1,
+        children: [
+          "fe-config",
+          "be-config",
+          "user-property"
+        ],
+      },
+      {
+        title: "User Privilege and Ldap",
+        directoryPath: "privilege-ldap/",
+        initialOpenGroupIndex: -1,
+        children: [
+          "user-privilege",
+          "ldap"
+        ],
+      },
+      "multi-tenant",
+      {
+        title: "HTTP API",
+        directoryPath: "http-actions/",
+        initialOpenGroupIndex: -1,
+        children: [
+          {
+            title: "FE",
+            directoryPath: "fe/",
+            initialOpenGroupIndex: -1,
+            children: [
+              {
+                title: "MANAGER",
+                directoryPath: "manager/",
+                initialOpenGroupIndex: -1,
+                children: [
+                  "cluster-action",
+                  "node-action",
+                  "query-profile-action",
+                ],
+              },
+              "backends-action",
+              "bootstrap-action",
+              "cancel-load-action",
+              "check-decommission-action",
+              "check-storage-type-action",
+              "config-action",
+              "connection-action",
+              "get-ddl-stmt-action",
+              "get-load-info-action",
+              "get-load-state",
+              "get-log-file-action",
+              "get-small-file",
+              "ha-action",
+              "hardware-info-action",
+              "health-action",
+              "log-action",
+              "logout-action",
+              "meta-action",
+              "meta-info-action",
+              "meta-replay-state-action",
+              "profile-action",
+              "query-detail-action",
+              "query-profile-action",
+              "row-count-action",
+              "session-action",
+              "set-config-action",
+              "show-data-action",
+              "show-meta-info-action",
+              "show-proc-action",
+              "show-runtime-info-action",
+              "statement-execution-action",
+              "system-action",
+              "table-query-plan-action",
+              "table-row-count-action",
+              "table-schema-action",
+              "upload-action",
+            ],
+          },
+          "cancel-label",
+          "check-reset-rpc-cache",
+          "compaction-action",
+          "connection-action",
+          "fe-get-log-file",
+          "get-load-state",
+          "get-tablets",
+          "profile-action",
+          "query-detail-action",
+          "restore-tablet",
+          "show-data-action",
+          "tablet-migration-action",
+          "tablets_distribution",
+        ],
+        sidebarDepth: 1,
+      },
+    ],
+  },
+  {
+    title: "FAQ",
+    directoryPath: "faq/",
+    initialOpenGroupIndex: -1,
+    children: [
+      "install-faq",
+      "data-faq",
+      "sql-faq"
+    ],
+  },
+  {
+    title: "Benchmark",
+    directoryPath: "benchmark/",
+    initialOpenGroupIndex: -1,
+    children: [
+      "ssb",
+      "tpch"
+    ],
+  }
+];
diff --git a/docs/.vuepress/sidebar/zh-CN.js b/docs/.vuepress/sidebar/zh-CN.js
index 8a804841cb..ac30752025 100644
--- a/docs/.vuepress/sidebar/zh-CN.js
+++ b/docs/.vuepress/sidebar/zh-CN.js
@@ -469,6 +469,7 @@ module.exports = [
               "bitmap_xor",
               "to_bitmap",
               "bitmap_max",
+              "intersect_count",
               "orthogonal_bitmap_intersect",
               "orthogonal_bitmap_intersect_count",
               "orthogonal_bitmap_union_count",
diff --git 
a/docs/en/sql-reference/sql-functions/bitmap-functions/intersect_count.md 
b/docs/en/sql-reference/sql-functions/bitmap-functions/intersect_count.md
new file mode 100644
index 0000000000..938865d3ac
--- /dev/null
+++ b/docs/en/sql-reference/sql-functions/bitmap-functions/intersect_count.md
@@ -0,0 +1,57 @@
+---
+{
+"title": "intersect_count",
+"language": "en"
+}
+---
+
+<!-- 
+Licensed to the Apache Software Foundation (ASF) under one
+or more contributor license agreements.  See the NOTICE file
+distributed with this work for additional information
+regarding copyright ownership.  The ASF licenses this file
+to you under the Apache License, Version 2.0 (the
+"License"); you may not use this file except in compliance
+with the License.  You may obtain a copy of the License at
+  http://www.apache.org/licenses/LICENSE-2.0
+Unless required by applicable law or agreed to in writing,
+software distributed under the License is distributed on an
+"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+KIND, either express or implied.  See the License for the
+specific language governing permissions and limitations
+under the License.
+-->
+
+## intersect_count
+### description
+#### Syntax
+
+`BITMAP INTERSECT_COUNT(bitmap_column, column_to_filter, filter_values)`
+Calculate the intersection of two or more bitmaps
+Usage: intersect_count(bitmap_column_to_count, filter_column, filter_values 
...)
+Example: intersect_count(user_id, event, 'A', 'B', 'C'), meaning find the 
intersect count of user_id in all A/B/C 3 bitmaps
+
+### example
+
+```
+MySQL [test_query_qa]> select dt,bitmap_to_string(user_id) from pv_bitmap 
where dt in (3,4);
++------+-----------------------------+
+| dt   | bitmap_to_string(`user_id`) |
++------+-----------------------------+
+|    4 | 1,2,3                       |
+|    3 | 1,2,3,4,5                   |
++------+-----------------------------+
+2 rows in set (0.012 sec)
+
+MySQL [test_query_qa]> select intersect_count(user_id,dt,3,4) from pv_bitmap;
++----------------------------------------+
+| intersect_count(`user_id`, `dt`, 3, 4) |
++----------------------------------------+
+|                                      3 |
++----------------------------------------+
+1 row in set (0.014 sec)
+```
+
+### keywords
+
+    INTERSECT_COUNT,BITMAP
diff --git 
a/docs/zh-CN/sql-reference/sql-functions/bitmap-functions/intersect_count.md 
b/docs/zh-CN/sql-reference/sql-functions/bitmap-functions/intersect_count.md
new file mode 100644
index 0000000000..41f58f6da0
--- /dev/null
+++ b/docs/zh-CN/sql-reference/sql-functions/bitmap-functions/intersect_count.md
@@ -0,0 +1,56 @@
+---
+{
+"title": "intersect_count",
+"language": "zh-CN"
+}
+---
+
+<!-- 
+Licensed to the Apache Software Foundation (ASF) under one
+or more contributor license agreements.  See the NOTICE file
+distributed with this work for additional information
+regarding copyright ownership.  The ASF licenses this file
+to you under the Apache License, Version 2.0 (the
+"License"); you may not use this file except in compliance
+with the License.  You may obtain a copy of the License at
+  http://www.apache.org/licenses/LICENSE-2.0
+Unless required by applicable law or agreed to in writing,
+software distributed under the License is distributed on an
+"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+KIND, either express or implied.  See the License for the
+specific language governing permissions and limitations
+under the License.
+-->
+
+## intersect_count
+### description
+#### Syntax
+
+`BITMAP INTERSECT_COUNT(bitmap_column, column_to_filter, filter_values)`
+聚合函数,求bitmap交集大小的函数, 不要求数据分布正交
+第一个参数是Bitmap列,第二个参数是用来过滤的维度列,第三个参数是变长参数,含义是过滤维度列的不同取值
+
+### example
+
+```
+MySQL [test_query_qa]> select dt,bitmap_to_string(user_id) from pv_bitmap 
where dt in (3,4);
++------+-----------------------------+
+| dt   | bitmap_to_string(`user_id`) |
++------+-----------------------------+
+|    4 | 1,2,3                       |
+|    3 | 1,2,3,4,5                   |
++------+-----------------------------+
+2 rows in set (0.012 sec)
+
+MySQL [test_query_qa]> select intersect_count(user_id,dt,3,4) from pv_bitmap;
++----------------------------------------+
+| intersect_count(`user_id`, `dt`, 3, 4) |
++----------------------------------------+
+|                                      3 |
++----------------------------------------+
+1 row in set (0.014 sec)
+```
+
+### keywords
+
+    INTERSECT_COUNT,BITMAP
diff --git 
a/fe/fe-core/src/main/java/org/apache/doris/analysis/FunctionCallExpr.java 
b/fe/fe-core/src/main/java/org/apache/doris/analysis/FunctionCallExpr.java
index ae2414a695..80a7d631f7 100644
--- a/fe/fe-core/src/main/java/org/apache/doris/analysis/FunctionCallExpr.java
+++ b/fe/fe-core/src/main/java/org/apache/doris/analysis/FunctionCallExpr.java
@@ -501,20 +501,23 @@ public class FunctionCallExpr extends Expr {
             throw new AnalysisException("BITMAP_UNION_INT params only support 
TINYINT or SMALLINT or INT");
         }
 
-        if 
(fnName.getFunction().equalsIgnoreCase(FunctionSet.INTERSECT_COUNT)) {
+        if (fnName.getFunction().equalsIgnoreCase(FunctionSet.INTERSECT_COUNT) 
|| fnName.getFunction()
+                .equalsIgnoreCase(FunctionSet.ORTHOGONAL_BITMAP_INTERSECT) || 
fnName.getFunction()
+                
.equalsIgnoreCase(FunctionSet.ORTHOGONAL_BITMAP_INTERSECT_COUNT)) {
             if (children.size() <= 2) {
-                throw new AnalysisException("intersect_count(bitmap_column, 
column_to_filter, filter_values) " +
-                        "function requires at least three parameters");
+                throw new AnalysisException(fnName + "(bitmap_column, 
column_to_filter, filter_values) "
+                        + "function requires at least three parameters");
             }
 
             Type inputType = getChild(0).getType();
             if (!inputType.isBitmapType()) {
-                throw new AnalysisException("intersect_count function first 
argument should be of BITMAP type, but was " + inputType);
+                throw new AnalysisException(
+                        fnName + "function first argument should be of BITMAP 
type, but was " + inputType);
             }
 
             for (int i = 2; i < children.size(); i++) {
                 if (!getChild(i).isConstant()) {
-                    throw new AnalysisException("intersect_count function 
filter_values arg must be constant");
+                    throw new AnalysisException(fnName + " function 
filter_values arg must be constant");
                 }
             }
             return;
diff --git 
a/fe/fe-core/src/main/java/org/apache/doris/catalog/AggregateFunction.java 
b/fe/fe-core/src/main/java/org/apache/doris/catalog/AggregateFunction.java
index 8f35805523..8a8de8214f 100644
--- a/fe/fe-core/src/main/java/org/apache/doris/catalog/AggregateFunction.java
+++ b/fe/fe-core/src/main/java/org/apache/doris/catalog/AggregateFunction.java
@@ -48,8 +48,11 @@ public class AggregateFunction extends Function {
 
     private static final Logger LOG = 
LogManager.getLogger(AggregateFunction.class);
 
-    public static ImmutableSet<String> 
NOT_NULLABLE_AGGREGATE_FUNCTION_NAME_SET =
-            ImmutableSet.of("row_number", "rank", "dense_rank", 
"multi_distinct_count", "multi_distinct_sum", "hll_union_agg", "hll_union", 
"bitmap_union", "bitmap_intersect", FunctionSet.COUNT, "approx_count_distinct", 
"ndv", FunctionSet.BITMAP_UNION_INT, FunctionSet.BITMAP_UNION_COUNT, 
"ndv_no_finalize", FunctionSet.WINDOW_FUNNEL);
+    public static ImmutableSet<String> 
NOT_NULLABLE_AGGREGATE_FUNCTION_NAME_SET = ImmutableSet.of("row_number", "rank",
+            "dense_rank", "multi_distinct_count", "multi_distinct_sum", 
"hll_union_agg", "hll_union", "bitmap_union",
+            "bitmap_intersect", "orthogonal_bitmap_intersect", 
"orthogonal_bitmap_intersect_count", "intersect_count",
+            "orthogonal_bitmap_union_count", FunctionSet.COUNT, 
"approx_count_distinct", "ndv",
+            FunctionSet.BITMAP_UNION_INT, FunctionSet.BITMAP_UNION_COUNT, 
"ndv_no_finalize", FunctionSet.WINDOW_FUNNEL);
 
     public static ImmutableSet<String> 
ALWAYS_NULLABLE_AGGREGATE_FUNCTION_NAME_SET =
             ImmutableSet.of("stddev_samp", "variance_samp", "var_samp", 
"percentile_approx");
diff --git a/fe/fe-core/src/main/java/org/apache/doris/catalog/FunctionSet.java 
b/fe/fe-core/src/main/java/org/apache/doris/catalog/FunctionSet.java
index d0ff5711f3..d040f46715 100644
--- a/fe/fe-core/src/main/java/org/apache/doris/catalog/FunctionSet.java
+++ b/fe/fe-core/src/main/java/org/apache/doris/catalog/FunctionSet.java
@@ -1810,6 +1810,14 @@ public class 
FunctionSet<min_initIN9doris_udf12DecimalV2ValEEEvPNS2_15FunctionCo
                     BITMAP_INTERSECT_FINALIZE_SYMBOL.get(t),
                     true, false, true));
 
+            // VEC_INTERSECT_COUNT
+            addBuiltin(
+                    AggregateFunction.createBuiltin(INTERSECT_COUNT, 
Lists.newArrayList(Type.BITMAP, t, t), Type.BIGINT,
+                            Type.VARCHAR, true, 
BITMAP_INTERSECT_INIT_SYMBOL.get(t),
+                            BITMAP_INTERSECT_UPDATE_SYMBOL.get(t), 
BITMAP_INTERSECT_MERGE_SYMBOL.get(t),
+                            BITMAP_INTERSECT_SERIALIZE_SYMBOL.get(t), null, 
null,
+                            BITMAP_INTERSECT_FINALIZE_SYMBOL.get(t), true, 
false, true, true));
+
             // HLL_UNION_AGG
             addBuiltin(AggregateFunction.createBuiltin("hll_union_agg",
                     Lists.newArrayList(t), Type.BIGINT, Type.VARCHAR,
@@ -2168,6 +2176,15 @@ public class 
FunctionSet<min_initIN9doris_udf12DecimalV2ValEEEvPNS2_15FunctionCo
                     "",
                     
"_ZN5doris15BitmapFunctions32orthogonal_bitmap_count_finalizeEPN9doris_udf15FunctionContextERKNS1_9StringValE",
                     true, false, true));
+
+            //vec ORTHOGONAL_BITMAP_INTERSECT and 
ORTHOGONAL_BITMAP_INTERSECT_COUNT
+            addBuiltin(
+                    
AggregateFunction.createBuiltin(ORTHOGONAL_BITMAP_INTERSECT, 
Lists.newArrayList(Type.BITMAP, t, t),
+                            Type.BITMAP, Type.BITMAP, true, "", "", "", "", 
"", "", "", true, false, true, true));
+
+            
addBuiltin(AggregateFunction.createBuiltin(ORTHOGONAL_BITMAP_INTERSECT_COUNT,
+                    Lists.newArrayList(Type.BITMAP, t, t), Type.BIGINT, 
Type.BITMAP, true, "", "", "", "", "", "", "",
+                    true, false, true, true));
         }
         // bitmap
         addBuiltin(AggregateFunction.createBuiltin(BITMAP_UNION, 
Lists.newArrayList(Type.BITMAP),
@@ -2226,6 +2243,10 @@ public class 
FunctionSet<min_initIN9doris_udf12DecimalV2ValEEEvPNS2_15FunctionCo
                 null,
                 
"_ZN5doris15BitmapFunctions32orthogonal_bitmap_count_finalizeEPN9doris_udf15FunctionContextERKNS1_9StringValE",
                 true, true, true));
+        // ORTHOGONAL_BITMAP_UNION_COUNT vectorized
+        
addBuiltin(AggregateFunction.createBuiltin(ORTHOGONAL_BITMAP_UNION_COUNT, 
Lists.newArrayList(Type.BITMAP),
+                Type.BIGINT, Type.BITMAP, "", "", "", "", null, null, "", 
true, true, true, true));
+
         // TODO(ml): supply function symbol
         addBuiltin(AggregateFunction.createBuiltin(BITMAP_INTERSECT, 
Lists.newArrayList(Type.BITMAP),
                 Type.BITMAP, Type.VARCHAR,


---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to