From c97434d7fd322b6489d89c520ea44e384f48a713 Mon Sep 17 00:00:00 2001 From: yangj1211 Date: Fri, 12 Apr 2024 11:57:26 +0800 Subject: [PATCH 1/4] add doc of bitmap --- .../Aggregate-Functions/bitmap.md | 382 ++++++++++++++++++ .../matrixone-function-list.md | 1 + mkdocs.yml | 1 + 3 files changed, 384 insertions(+) create mode 100644 docs/MatrixOne/Reference/Functions-and-Operators/Aggregate-Functions/bitmap.md diff --git a/docs/MatrixOne/Reference/Functions-and-Operators/Aggregate-Functions/bitmap.md b/docs/MatrixOne/Reference/Functions-and-Operators/Aggregate-Functions/bitmap.md new file mode 100644 index 0000000000..d5ef3b16bc --- /dev/null +++ b/docs/MatrixOne/Reference/Functions-and-Operators/Aggregate-Functions/bitmap.md @@ -0,0 +1,382 @@ +# bitmap 函数 + +## 函数说明 + +`BITMAP` 函数是一组用于处理位图(bitmap)的内置函数,bitmap 是存储为二进制数据类型的连续内存片段。这些函数特别适用于处理层次化聚合(如多个分组集合)时的不同值(distinct values)的计数,返回结果与 [`count(distinct)`]( count.md) 一致,但更高效。 + +我们可以只使用一个 bit 位标识一个元素的存在与否,存在为 1,不存在则为 0,用 bitmap 的第 n 个 bit 来记录这个元素是否存在。 + +我们规定 bitmap 最大宽度为 32768(2^15 = 4K),对于非负整数 n,取其低 15 位(二进制)作为在 bitmap 的位置,其它高位作为位图桶 (bitmap bucket) 的编号。下图为 bitmap 的逻辑图: + +![](https://community-shared-data-1308875761.cos.ap-beijing.myqcloud.com/artwork/docs/reference/bitmap.png) + +每个 bucket 是一个 bitmap,由于各个 bucket 是正交的,每个 bucket 做运算 (or,bit_count) 可以只在当前 bucket 中进行,而不必关心其它 bucket。 + +以下是一些常用的 `BITMAP` 函数及其用法: + +### BITMAP_BUCKET_NUMBER + +`BITMAP_BUCKET_NUMBER()` 函数的目的是确定给定值所属的 bucket 的编号。bucket 是一个更大的位集合,可以包含多个位,每个位代表数据集中的一个特定值。这个函数返回 bucket 的编号。一个 bucket 编号通常用于在执行聚合操作时对 bitmap 进行分组。 + +#### 语法 + +``` +> BITMAP_BUCKET_NUMBER(numeric_expr) +``` + +#### 参数释义 + +| 参数 | 说明 | +| ---- | ---- | +| numeric_expr | 必需的。可以 cast 成非负整型的表达式。| + +#### 示例 + +```sql +mysql> SELECT bitmap_bucket_number(0);-- 返回 0,表示属于第一个 bucket,第一个 bucket 记录 0-32767 的位置 ++-------------------------+ +| bitmap_bucket_number(0) | ++-------------------------+ +| 0 | ++-------------------------+ +1 row in set (0.00 sec) + +mysql> SELECT bitmap_bucket_number(32767);-- 返回 0,因为 32767 属于第一个 bucket 的末尾位置 ++-----------------------------+ +| bitmap_bucket_number(32767) | ++-----------------------------+ +| 0 | ++-----------------------------+ +1 row in set (0.00 sec) + +mysql> SELECT bitmap_bucket_number(32768);-- 返回 1,因为 32768 属于第二个 bucket 的起始位置 ++-----------------------------+ +| bitmap_bucket_number(32768) | ++-----------------------------+ +| 1 | ++-----------------------------+ +1 row in set (0.00 sec) +``` + +### BITMAP_BIT_POSITION + +`BITMAP_BIT_POSITION()` 函数用于返回给定值在 bucket 中的相对位位置(从 0 开始索引到 32767 结束)。与 `BITMAP_BUCKET_NUMBER()` 配合使用,可以唯一标识 bitmap 中的任何数字。因为实际 `BITMAP_BIT_POSITION()` 标记参数的低 15 位(以二进制表示),`BITMAP_BUCKET_NUMBER()` 标记参数的高位。 + +#### 语法 + +``` +BITMAP_BIT_POSITION(numeric_expr) +``` + +#### 参数释义 + +| 参数 | 说明 | +| ---- | ---- | +| numeric_expr | 必需的。可以 cast 成非负整型的表达式。| + +#### 示例 + +```sql + +mysql> SELECT bitmap_bit_position(0);-- 返回 0,因为 0 在第一个 bucket 的第一个位置 ++------------------------+ +| bitmap_bit_position(0) | ++------------------------+ +| 0 | ++------------------------+ +1 row in set (0.00 sec) + +mysql> SELECT bitmap_bit_position(32767);-- 返回 32767,因为 32767 在第一个 bucket 中的位置是最后一个 ++----------------------------+ +| bitmap_bit_position(32767) | ++----------------------------+ +| 32767 | ++----------------------------+ +1 row in set (0.00 sec) + +mysql> SELECT bitmap_bit_position(32768);-- 返回 0,因为 32768 在第二个 bucket 的第一个位置 ++----------------------------+ +| bitmap_bit_position(32768) | ++----------------------------+ +| 0 | ++----------------------------+ +1 row in set (0.00 sec) + +--40000 的二进制为:1001110001000000,bitmap_bit_position 记录低 15 位:001110001000000,bitmap_bucket_number 记录高位:1 +mysql> select bin(bitmap_bucket_number(40000)), bin(bitmap_bit_position(40000)),bin(40000); ++----------------------------------+---------------------------------+------------------+ +| bin(bitmap_bucket_number(40000)) | bin(bitmap_bit_position(40000)) | bin(40000) | ++----------------------------------+---------------------------------+------------------+ +| 1 | 1110001000000 | 1001110001000000 | ++----------------------------------+---------------------------------+------------------+ +1 row in set (0.01 sec) +``` + +### BITMAP_COUNT + +`BITMAP_COUNT()` 函数用于计算 bitmap 中设置为 1 的位的数量,从而得到不同值的总数。这相当于对 bitmap 执行 `COUNT(DISTINCT)` 操作,但通常比传统的 `COUNT(DISTINCT)` 查询更快。 + +`BITMAP_COUNT()` 函数一般结合下述的 `BITMAP_CONSTRUCT_AGG()`、`BITMAP_OR_AGG()` 函数使用。 + +### `BITMAP_CONSTRUCT_AGG` + +`BITMAP_CONSTRUCT_AGG()` 是一个聚合函数,它在数据库中用于构建 bitmap。 + +当需要对一组密集的非重复整数值进行计数时,`BITMAP_CONSTRUCT_AGG()` 函数非常有用,因为它可以高效地将这些值转换为 bitmap 形式。 + +#### 语法 + +``` +BITMAP_CONSTRUCT_AGG( ) +``` + +#### 参数释义 + +| 参数 | 说明 | +| ---- | ---- | +| bit_position | 必需的。在 bitmap 中的位置(BITMAP_BIT_POSITION 函数返回)| + +#### 示例 + +```sql +CREATE TABLE t1 ( n1 int); +INSERT INTO t1 VALUES(0),(1),(1),(32767);--插入 [0,32767] 内的数据 + +mysql> select * from t1; ++-------+ +| n1 | ++-------+ +| 0 | +| 1 | +| 1 | +| 32767 | ++-------+ +4 rows in set (0.01 sec) + +mysql> SELECT BITMAP_CONSTRUCT_AGG(BITMAP_BIT_POSITION(n1)) AS bitmap FROM t1; ++------------------------+ +| bitmap | ++------------------------+ +| :0 ? | ++------------------------+ +1 row in set (0.00 sec) +``` + +!!! note + bitmap 列包含 bitmap 的物理表示形式,不可读。为了确定哪些位被设置,我们应结合使用 `BITMAP` 函数(而不是自己检查二进制值)。 + +```sql +mysql> SELECT bitmap_count(BITMAP_CONSTRUCT_AGG(BITMAP_BIT_POSITION(n1))) AS n1_discnt FROM t1;--bitmap 中设置为 1 的数量 ++-----------+ +| n1_discnt | ++-----------+ +| 3 | ++-----------+ +1 row in set (0.00 sec) + +mysql> SELECT count(DISTINCT n1) AS n1_discnt FROM t1;--返回一致 ++-----------+ +| n1_discnt | ++-----------+ +| 3 | ++-----------+ +1 row in set (0.01 sec) + +INSERT INTO t1 VALUES(32768),(32769),(65535);--插入大于 32767 的数据 + +mysql> select * from t1; ++-------+ +| n1 | ++-------+ +| 0 | +| 1 | +| 1 | +| 32767 | +| 32768 | +| 32769 | +| 65535 | ++-------+ +7 rows in set (0.01 sec) + +--结果与第一次插入一样,因为 bucket_bit_position = n1 % 32768,第二次插入的数据与第一次插入的数据位于不同 bucket 的相同位置,所以被去重了。 +mysql> SELECT bitmap_count(BITMAP_CONSTRUCT_AGG(BITMAP_BIT_POSITION(n1))) AS n1_discnt FROM t1; ++-----------+ +| t1_bitmap | ++-----------+ +| 3 | ++-----------+ +1 row in set (0.00 sec) + +mysql> SELECT bitmap_bit_position(0),bitmap_bit_position(1),bitmap_bit_position(32767),bitmap_bit_position(32768),bitmap_bit_position(65535); ++------------------------+------------------------+----------------------------+----------------------------+----------------------------+ +| bitmap_bit_position(0) | bitmap_bit_position(1) | bitmap_bit_position(32767) | bitmap_bit_position(32768) | bitmap_bit_position(65535) | ++------------------------+------------------------+----------------------------+----------------------------+----------------------------+ +| 0 | 1 | 32767 | 0 | 32767 | ++------------------------+------------------------+----------------------------+----------------------------+----------------------------+ +1 row in set (0.00 sec) +``` + +因此如果要对大于 32767 的数据去重需结合 `BITMAP_BUCKET_NUMBER()` 函数。 + +```sql +--以 bucket 分组,第一个 bucket 里面有三个非重复数(0,1,32767),第二个 bucket 里有三个非重复数 (32768,32769,65535)。 +mysql> SELECT bitmap_count(BITMAP_CONSTRUCT_AGG(BITMAP_BIT_POSITION(n1))) AS t1_bitmap FROM t1 GROUP BY BITMAP_BUCKET_NUMBER(n1); ++-----------+ +| t1_bitmap | ++-----------+ +| 3 | +| 3 | ++-----------+ +2 rows in set (0.01 sec) + +--结合 sum() 函数计算 n1 的非重复值 +mysql> SELECT SUM(t1_bitmap) FROM ( + -> SELECT bitmap_count(BITMAP_CONSTRUCT_AGG(BITMAP_BIT_POSITION(n1))) AS t1_bitmap + -> FROM t1 + -> GROUP BY BITMAP_BUCKET_NUMBER(n1) + -> ); ++----------------+ +| sum(t1_bitmap) | ++----------------+ +| 6 | ++----------------+ +1 row in set (0.01 sec) +``` + +### BITMAP_OR_AGG + +`BITMAP_OR_AGG()` 函数用于计算多个 bitmap 的按位或(OR)结果。通常用于合并多个 bitmap,以便在一个 bitmap 中表示所有输入 bitmap 的组合信息。 + +当需要对不同维度的数据进行集合并集操作时,`BITMAP_OR_AGG()` 十分有用,尤其是在数据仓库和分析型查询中。 + +#### 语法 + +``` +BITMAP_OR_AGG( bitmap ) +``` + +#### 参数释义 + +| 参数 | 说明 | +| ---- | ---- | +| bitmap | 必需的。所有 bitmap 按位或合并得到的 bitmap。| + +#### 示例 + +```sql + +--创建一张表,用来存储作者出版书籍的信息,包含作者名称,出版年份和书籍 id +CREATE TABLE book_table( + id int auto_increment primary key, + author varchar(100), + pub_year varchar(100), + book_id int +); +INSERT INTO book_table(author,pub_year,book_id) VALUES +('A 作者','2020',1),('A 作者','2020',1),('A 作者','2020',32768), +('A 作者','2021',32767),('A 作者','2021',32768),('A 作者','2021',65536), +('B 作者','2020',2),('B 作者','2020',10),('B 作者','2020',32769), +('B 作者','2021',5),('B 作者','2021',65539); + +mysql> select * from book_table; ++------+----------+----------+---------+ +| id | author | pub_year | book_id | ++------+----------+----------+---------+ +| 1 | A 作者 | 2020 | 1 | +| 2 | A 作者 | 2020 | 1 | +| 3 | A 作者 | 2020 | 32768 | +| 4 | A 作者 | 2021 | 32767 | +| 5 | A 作者 | 2021 | 32768 | +| 6 | A 作者 | 2021 | 65536 | +| 7 | B 作者 | 2020 | 2 | +| 8 | B 作者 | 2020 | 10 | +| 9 | B 作者 | 2020 | 32769 | +| 10 | B 作者 | 2021 | 5 | +| 11 | B 作者 | 2021 | 65539 | ++------+----------+----------+---------+ +11 rows in set (0.00 sec) + +--定义一张预计算表,把粗粒度的计算结果保存在表中,后续各种不同维度聚合可以使用预计算表中的结果,经过简单的计算就可以得到结果,加速查询。 +CREATE TABLE precompute AS +SELECT + author, + pub_year, + BITMAP_BUCKET_NUMBER(book_id) as bucket, + BITMAP_CONSTRUCT_AGG(BITMAP_BIT_POSITION(book_id)) as bitmap +FROM book_table +GROUP BY author,pub_year,bucket; + +mysql> select * from precompute; ++---------+----------+--------+----------------------+ +| author | pub_year | bucket | bitmap | ++---------+----------+--------+----------------------+ +| A作者 | 2020 | 0 | :0 | +| A作者 | 2020 | 1 | :0 | +| A作者 | 2021 | 0 | :0 ? | +| A作者 | 2021 | 1 | :0 | +| A作者 | 2021 | 2 | :0 | +| B作者 | 2020 | 0 | :0 | +| B作者 | 2020 | 1 | :0 | +| B作者 | 2021 | 0 | :0 | +| B作者 | 2021 | 2 | :0 | ++---------+----------+--------+----------------------+ + +--计算在作者和出版年份聚合情况下 book_id 的去重数量,反应的是作者在不同年份出版书籍类型的数量。 +--sum() 函数累加不同 bucket 的 bitmap 中 1 的数量。 +--例如当 author=A 作者,pub_year=2020 时,book_id=(1,1,32768),去重后为 book_id=(1,32768),但是 1 位于第一个 bucket,32768 位于第二个 bucket,所以需要 sum 作累加。 +mysql> SELECT + -> author, + -> pub_year, + -> SUM(BITMAP_COUNT(bitmap)) + -> FROM precompute + -> GROUP BY author,pub_year; ++---------+----------+---------------------------+ +| author | pub_year | sum(bitmap_count(bitmap)) | ++---------+----------+---------------------------+ +| A作者 | 2020 | 2 | +| A作者 | 2021 | 3 | +| B作者 | 2020 | 3 | +| B作者 | 2021 | 2 | ++---------+----------+---------------------------+ +4 rows in set (0.00 sec) + +mysql> SELECT author,pub_year,count( DISTINCT book_id) FROM book_table group by author,pub_year;--返回一致 ++----------+----------+-------------------------+ +| author | pub_year | count(distinct book_id) | ++----------+----------+-------------------------+ +| A 作者 | 2020 | 2 | +| A 作者 | 2021 | 3 | +| B 作者 | 2020 | 3 | +| B 作者 | 2021 | 2 | ++----------+----------+-------------------------+ +4 rows in set (0.00 sec) + +--计算在作者聚合情况下 book_id 的去重数量,反应的是作者一共出版书籍类型的数量。 +--BITMAP_OR_AGG() 函数合并不同维度(相同作者不同年份)的 bitmap。 +--例如当 author=A 作者,pub_date=2020 时,book_id 去重后为 (1,32768),pub_date=2021 时,book_id 去重后为 (32767,32768,65536),BITMAP_OR_AGG 对两个不同年份的 bitmap 做或运算得到 book_id=(1,32767,32768,65536),最后 sum() 累加不同 bucktet 的 book_id。 +mysql> SELECT author, SUM(cnt) FROM ( + -> SELECT + -> author, + -> BITMAP_COUNT(BITMAP_OR_AGG(bitmap)) cnt + -> FROM precompute + -> GROUP BY author,bucket + -> ) + -> GROUP BY author; ++---------+----------+ +| author | sum(cnt) | ++---------+----------+ +| A作者 | 4 | +| B作者 | 5 | ++---------+----------+ +2 rows in set (0.01 sec) + +mysql> SELECT author,count(DISTINCT book_id) FROM book_table GROUP BY author;--返回一致 ++----------+-------------------------+ +| author | count(distinct book_id) | ++----------+-------------------------+ +| A 作者 | 4 | +| B 作者 | 5 | ++----------+-------------------------+ +2 rows in set (0.00 sec) + +``` diff --git a/docs/MatrixOne/Reference/Functions-and-Operators/matrixone-function-list.md b/docs/MatrixOne/Reference/Functions-and-Operators/matrixone-function-list.md index f9ffa7070f..52f48a9180 100644 --- a/docs/MatrixOne/Reference/Functions-and-Operators/matrixone-function-list.md +++ b/docs/MatrixOne/Reference/Functions-and-Operators/matrixone-function-list.md @@ -8,6 +8,7 @@ | ------------------------------------------------------ | --------------------------------------- | | [ANY_VALUE()](./Aggregate-Functions/any-value.md) | 在参数范围内任选一个值返回| | [AVG()](./Aggregate-Functions/avg.md) | 计算参数列的算术平均值。| +| [BITMAP](./Aggregate-Functions/bitmap.md) | 一组用于处理位图的内置函数,主要用于计算不同值| | [BIT_AND()](./Aggregate-Functions/bit_and.md) | 计算了列中所有位的按位与| | [BIT_OR()](./Aggregate-Functions/bit_or.md) | 计算了列中所有位的按位或| | [BIT_XOR()](./Aggregate-Functions/bit_xor.md) | 计算了列中所有位的按位异或| diff --git a/mkdocs.yml b/mkdocs.yml index c8bc0b32f2..7ecbeacb48 100644 --- a/mkdocs.yml +++ b/mkdocs.yml @@ -451,6 +451,7 @@ nav: - 聚合函数: - ANY_VALUE: MatrixOne/Reference/Functions-and-Operators/Aggregate-Functions/any-value.md - AVG: MatrixOne/Reference/Functions-and-Operators/Aggregate-Functions/avg.md + - BITMAP: MatrixOne/Reference/Functions-and-Operators/Aggregate-Functions/bitmap.md - BIT_AND: MatrixOne/Reference/Functions-and-Operators/Aggregate-Functions/bit_and.md - BIT_OR: MatrixOne/Reference/Functions-and-Operators/Aggregate-Functions/bit_or.md - BIT_XOR: MatrixOne/Reference/Functions-and-Operators/Aggregate-Functions/bit_xor.md From 5b1eb7f15618a65446d3027c3124ef8b419595e3 Mon Sep 17 00:00:00 2001 From: yangj1211 Date: Fri, 12 Apr 2024 11:59:04 +0800 Subject: [PATCH 2/4] add doc of bitmap --- .../Functions-and-Operators/Aggregate-Functions/bitmap.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/MatrixOne/Reference/Functions-and-Operators/Aggregate-Functions/bitmap.md b/docs/MatrixOne/Reference/Functions-and-Operators/Aggregate-Functions/bitmap.md index d5ef3b16bc..5bbcd50f1d 100644 --- a/docs/MatrixOne/Reference/Functions-and-Operators/Aggregate-Functions/bitmap.md +++ b/docs/MatrixOne/Reference/Functions-and-Operators/Aggregate-Functions/bitmap.md @@ -1,4 +1,4 @@ -# bitmap 函数 +# BITMAP 函数 ## 函数说明 From e7b469ff9733892cc5b593450f1d01679b2943c0 Mon Sep 17 00:00:00 2001 From: yangj1211 Date: Wed, 17 Apr 2024 10:40:47 +0800 Subject: [PATCH 3/4] update doc of bitmap --- .../MatrixOne/Develop/distinct-data/bitmap.md | 134 ++++++++++++++++++ .../Develop/distinct-data/count-distinct.md | 59 ++++++++ .../Aggregate-Functions/bitmap.md | 2 +- mkdocs.yml | 3 + 4 files changed, 197 insertions(+), 1 deletion(-) create mode 100644 docs/MatrixOne/Develop/distinct-data/bitmap.md create mode 100644 docs/MatrixOne/Develop/distinct-data/count-distinct.md diff --git a/docs/MatrixOne/Develop/distinct-data/bitmap.md b/docs/MatrixOne/Develop/distinct-data/bitmap.md new file mode 100644 index 0000000000..07946d53f9 --- /dev/null +++ b/docs/MatrixOne/Develop/distinct-data/bitmap.md @@ -0,0 +1,134 @@ +# 使用 BITMAP 对数据去重 + +Matrixone 支持使用 [`BITMAP`](../../Reference/Functions-and-Operators/Aggregate-Functions/bitmap.md) 处理不同值(distinct values)的计数。 + +本篇文章将介绍 `BITMAP` 的一些应用场景和案例。 + +## 应用场景 + +在 MatrixOne 中,`BITMAP` 用于优化特定类型的查询操作,尤其是在处理具有低基数(low cardinality)的列时,帮助用户在大数据环境中实现了快速的数据分析和决策支持。以下是一些 `BITMAP` 的使用场景: + +1. **用户行为分析**:假设一个电商平台想要分析不同用户的行为模式。他们有一个事件表,记录了用户的每一次点击事件,包括用户 ID、时间戳、事件类型等。通过使用 `BITMAP`,可以快速地对用户的行为进行分类和统计,例如,找出所有进行过“购买”行为的用户数量。 + +2. **多维度分析**:在数据仓库中,经常需要对多个维度进行分析,例如,分析特定时间段内不同地区的销售情况。通过 `BITMAP`,可以快速地对日期和地区这两个维度进行筛选,从而提高查询效率。 + +3. **统计不同值的数量**:在处理具有大量唯一值的列时,如产品类别或用户状态,使用 `BITMAP` 可以高效地计算这些列中不同值的数量。例如,一个社交媒体平台可能需要统计其用户活跃状态(在线、离线)的不同数量。 + +4. **层次化聚合加速**:在需要进行层次化聚合查询时,如对销售数据进行季度和年度汇总,`BITMAP` 可以加速计算过程。通过使用 `BITMAP`,可以快速地对数据进行分组和聚合,从而得到所需的统计信息。 + +5. **优化复杂查询**:对于包含多个条件的复杂查询,`BITMAP` 可以快速筛选出符合条件的数据。例如,一个金融公司可能需要找出同时满足“高净值客户”和“投资于特定基金”的用户。 + +## 开始前准备 + +已完成[单机部署 MatrixOne](../../Get-Started/install-standalone-matrixone.md)。 + +## 案例 + +根据上述场景一设计案例,分析电商平台不同用户的行为模式。 + +### 步骤 + +#### 1. 建立用户表并导入数据 + +准备一个名为 `user_behavior_table` 的表以及对应的 csv 数据,这个 csv 数据表共有 39270760 行数据。 + +```sql +CREATE TABLE user_behavior_table( +user_id int,--用户 id +behavior varchar(100),--行为,包括 browser,purchase,returns +occur_year varchar(100)--行为发生年份 +); + +LOAD DATA INFILE '/your_path/user_behavior_table.csv' INTO TABLE user_behavior_table FIELDS TERMINATED BY ',' OPTIONALLY ENCLOSED BY '"'; +``` + +#### 2. 定义预计算表 + +把粗粒度的计算结果保存在预计算表中,后续各种不同维度聚合可以使用预计算表中的结果,经过简单的计算就可以得到结果,加速查询。 + +```sql +CREATE TABLE precompute AS +SELECT + behavior, + occur_year, + BITMAP_BUCKET_NUMBER(user_id) as bucket, + BITMAP_CONSTRUCT_AGG(BITMAP_BIT_POSITION(user_id)) as bitmap +FROM user_behavior_table +GROUP BY behavior,occur_year,bucket; +``` + +#### 3. 按不同维度聚合筛选数据 + +计算在用户行为和年份聚合情况下 user_id 的去重数量,反应的是在不同年份进行商品浏览、购买和退货的用户数量。 + +```sql +mysql> SELECT + -> behavior, + -> occur_year, + -> SUM(BITMAP_COUNT(bitmap)) + -> FROM precompute + -> GROUP BY behavior,occur_year; ++----------+------------+---------------------------+ +| behavior | occur_year | sum(bitmap_count(bitmap)) | ++----------+------------+---------------------------+ +| browser | 2022 | 939995 | +| browser | 2023 | 1003173 | +| purchase | 2022 | 669474 | +| purchase | 2023 | 660605 | +| returns | 2023 | 4910 | +| returns | 2022 | 4350 | ++----------+------------+---------------------------+ +6 rows in set (0.01 sec) + +mysql> select behavior,occur_year,count(distinct user_id) from user_behavior_table group by +behavior,occur_year; ++----------+------------+-------------------------+ +| behavior | occur_year | count(distinct user_id) | ++----------+------------+-------------------------+ +| purchase | 2022 | 669474 | +| browser | 2022 | 939995 | +| browser | 2023 | 1003173 | +| purchase | 2023 | 660605 | +| returns | 2023 | 4910 | +| returns | 2022 | 4350 | ++----------+------------+-------------------------+ +6 rows in set (2.19 sec) +``` + +计算 2022-2023 年进行商品浏览、购买和退货的用户数量。 + +```sql +mysql> SELECT behavior, SUM(cnt) FROM ( + -> SELECT + -> behavior, + -> BITMAP_COUNT(BITMAP_OR_AGG(bitmap)) cnt + -> FROM precompute + -> GROUP BY behavior,bucket + -> ) + -> GROUP BY behavior; ++----------+----------+ +| behavior | sum(cnt) | ++----------+----------+ +| browser | 1003459 | +| purchase | 780308 | +| returns | 9260 | ++----------+----------+ +3 rows in set (0.01 sec) + +mysql> select behavior,count(distinct user_id) from user_behavior_table group by behavior; ++----------+-------------------------+ +| behavior | count(distinct user_id) | ++----------+-------------------------+ +| browser | 1003459 | +| purchase | 780308 | +| returns | 9260 | ++----------+-------------------------+ +3 rows in set (1.44 sec) +``` + +对比两种查询的返回时间,显然使用 `BITMAP` 更高效。通过使用 `BITMAP`,商家能够迅速地筛选出特定类型的事件,从而统计出具有某种行为的用户总数。 + +## 参考文档 + +- [BITMAP](../../Reference/Functions-and-Operators/Aggregate-Functions/bitmap.md) +- [COUNT](../../Reference/Functions-and-Operators/Aggregate-Functions/count.md) diff --git a/docs/MatrixOne/Develop/distinct-data/count-distinct.md b/docs/MatrixOne/Develop/distinct-data/count-distinct.md new file mode 100644 index 0000000000..77cf834f19 --- /dev/null +++ b/docs/MatrixOne/Develop/distinct-data/count-distinct.md @@ -0,0 +1,59 @@ +# 使用 COUNT(DISTINCT) 对数据去重 + +`COUNT(DISTINCT)` 提供了精确的去重计数结果,但可能在大数据集上效率较低。如需处理大型数据集请使用 [BITMAP](bitmap.md)。 + +本篇文章将介绍如何使用 `COUNT(DISTINCT)` 对少量数据去重。 + +## 开始前准备 + +已完成[单机部署 MatrixOne](../../Get-Started/install-standalone-matrixone.md)。 + +## 示例 + +```sql +--建立 orders 表,有 customer_id 和 product_id 两个字段,分别表示客户和产品的唯一标识符。 +CREATE TABLE orders ( + order_id INT AUTO_INCREMENT PRIMARY KEY, + customer_id INT, + product_id INT, + order_date DATE, + quantity INT +); + +--插入一些示例数据: +INSERT INTO orders (customer_id, product_id, order_date, quantity) +VALUES + (1, 101, '2023-04-01', 2), + (1, 102, '2023-04-02', 1), + (2, 101, '2023-04-03', 5), + (3, 103, '2023-04-04', 3), + (2, 104, '2023-04-05', 1), + (4, 101, '2023-04-06', 2), + (4, 102, '2023-04-07', 1), + (5, 105, '2023-04-08', 4), + (1, 101, '2023-04-09', 2); + +--计算不同客户的数量: +mysql> SELECT COUNT(DISTINCT customer_id) AS unique_customer_count FROM orders; ++-----------------------+ +| unique_customer_count | ++-----------------------+ +| 5 | ++-----------------------+ +1 row in set (0.01 sec) + +--计算不同产品的数量: +mysql> SELECT COUNT(DISTINCT product_id) AS unique_product_count FROM orders; ++----------------------+ +| unique_product_count | ++----------------------+ +| 5 | ++----------------------+ +1 row in set (0.01 sec) +``` + +这两个查询将分别返回 orders 表中唯一客户的数量和唯一产品的数量。这些信息对于分析客户多样性和产品销售范围非常有用。 + +## 参考文档 + +- [COUNT](../../Reference/Functions-and-Operators/Aggregate-Functions/count.md) diff --git a/docs/MatrixOne/Reference/Functions-and-Operators/Aggregate-Functions/bitmap.md b/docs/MatrixOne/Reference/Functions-and-Operators/Aggregate-Functions/bitmap.md index 5bbcd50f1d..1e40298a8f 100644 --- a/docs/MatrixOne/Reference/Functions-and-Operators/Aggregate-Functions/bitmap.md +++ b/docs/MatrixOne/Reference/Functions-and-Operators/Aggregate-Functions/bitmap.md @@ -118,7 +118,7 @@ mysql> select bin(bitmap_bucket_number(40000)), bin(bitmap_bit_position(40000)), `BITMAP_COUNT()` 函数一般结合下述的 `BITMAP_CONSTRUCT_AGG()`、`BITMAP_OR_AGG()` 函数使用。 -### `BITMAP_CONSTRUCT_AGG` +### BITMAP_CONSTRUCT_AGG `BITMAP_CONSTRUCT_AGG()` 是一个聚合函数,它在数据库中用于构建 bitmap。 diff --git a/mkdocs.yml b/mkdocs.yml index 7ecbeacb48..9036c0bff3 100644 --- a/mkdocs.yml +++ b/mkdocs.yml @@ -131,6 +131,9 @@ nav: - 窗口函数: - 标准窗口: MatrixOne/Develop/read-data/window-function/window-function.md - 时间窗口: MatrixOne/Develop/read-data/window-function/time-window.md + - 数据去重: + - COUNT(DISTINCT): MatrixOne/Develop/distinct-data/count-distinct.md + - BITMAP: MatrixOne/Develop/distinct-data/bitmap.md - 租户设计: - 多租户概述: MatrixOne/Develop/Publish-Subscribe/multi-account-overview.md - 发布订阅: MatrixOne/Develop/Publish-Subscribe/pub-sub-overview.md From 12e079295824f8c0d6b5d8c23611dd1e4619b0a1 Mon Sep 17 00:00:00 2001 From: yangj1211 Date: Wed, 17 Apr 2024 10:44:49 +0800 Subject: [PATCH 4/4] update doc of bitmap --- .../MatrixOne/Develop/distinct-data/bitmap.md | 25 +++++++++---------- 1 file changed, 12 insertions(+), 13 deletions(-) diff --git a/docs/MatrixOne/Develop/distinct-data/bitmap.md b/docs/MatrixOne/Develop/distinct-data/bitmap.md index 07946d53f9..0d2ac2e070 100644 --- a/docs/MatrixOne/Develop/distinct-data/bitmap.md +++ b/docs/MatrixOne/Develop/distinct-data/bitmap.md @@ -80,19 +80,18 @@ mysql> SELECT +----------+------------+---------------------------+ 6 rows in set (0.01 sec) -mysql> select behavior,occur_year,count(distinct user_id) from user_behavior_table group by -behavior,occur_year; -+----------+------------+-------------------------+ -| behavior | occur_year | count(distinct user_id) | -+----------+------------+-------------------------+ -| purchase | 2022 | 669474 | -| browser | 2022 | 939995 | -| browser | 2023 | 1003173 | -| purchase | 2023 | 660605 | -| returns | 2023 | 4910 | -| returns | 2022 | 4350 | -+----------+------------+-------------------------+ -6 rows in set (2.19 sec) +mysql> select behavior,occur_year,count(distinct user_id) from user_behavior_table group by behavior,occur_year; ++----------+------------+---------------------------+ +| behavior | occur_year | sum(bitmap_count(bitmap)) | ++----------+------------+---------------------------+ +| browser | 2022 | 939995 | +| browser | 2023 | 1003173 | +| purchase | 2022 | 669474 | +| purchase | 2023 | 660605 | +| returns | 2023 | 4910 | +| returns | 2022 | 4350 | ++----------+------------+---------------------------+ +6 rows in set (3.26 sec) ``` 计算 2022-2023 年进行商品浏览、购买和退货的用户数量。