Todos os produtos
Search
Central de documentação

AnalyticDB:Funções de segmentação de usuários (Roaring Bitmap)

Última atualização: Jun 27, 2026

O Roaring Bitmap é um formato de bitmap compactado e otimizado para operações de conjuntos de alto desempenho. Utilize-o no AnalyticDB for MySQL para deduplicação, filtragem de usuários baseada em tags e cálculos de séries temporais em grandes volumes de dados.

Quando usar o Roaring Bitmap

O Roaring Bitmap supera as consultas padrão COUNT(DISTINCT ...) quando cada grupo no bitmap contém menos de 100 milhões de entradas. Para espaços de UID maiores, aumente proporcionalmente o número de grupos (por exemplo, um espaço de UID de 10 bilhões exige pelo menos 100 grupos).

Requisitos de versão

Tipo de tabela

Versão mínima

Tabelas externas do OSS

3.1.6.4

Tabelas internas

3.2.1.0

A versão V3.2.8.0 e posteriores suportam dados BIGINT no Roaring Bitmap, estendendo o intervalo de valores para inteiros de 64 bits. Entre em contato com o suporte técnico para ativar essa funcionalidade. Após a ativação, funções selecionadas aceitam entradas BIGINT e seu tipo de retorno muda de INTEGER para BIGINT. Para mais detalhes, consulte Funções.

Para visualizar ou atualizar a versão do seu cluster, acesse a seção Configuration Information na página Cluster Information no console do AnalyticDB for MySQL.

Limitações

  • Não é possível executar SELECT diretamente em colunas ROARINGBITMAP. Utilize UNNEST para visualizar os elementos:

    SELECT * FROM unnest(RB_BUILD(ARRAY[1,2,3]));
  • Clusters anteriores à versão V3.2.1.0 suportam ROARINGBITMAP apenas em tabelas externas do OSS. Para realizar operações de bitmap em tabelas internas nessas versões, armazene os bitmaps como VARBINARY e converta-os no momento da consulta usando RB_BUILD_VARBINARY:

    -- Define an internal table with VARBINARY
    CREATE TABLE test_rb_cstore (id INT, rb VARBINARY);
    
    -- Query using bitmap functions
    SELECT RB_CARDINALITY(RB_BUILD_VARBINARY(rb)) FROM test_rb_cstore;

Construir um Roaring Bitmap

Três funções constroem um Roaring Bitmap, cada uma destinada a uma fonte de entrada diferente:

Função

Entrada

Quando usar

RB_BUILD(array)

Array de inteiros

Para criar um bitmap a partir de um array literal

RB_BUILD_AGG(integer)

Inteiro (agregado)

Para agregar inteiros no nível de linha em um bitmap

RB_BUILD_VARBINARY(varbinary)

VARBINARY

Para ler bitmaps armazenados como VARBINARY em tabelas internas

Funções

Funções escalares

Função

Tipo de entrada

Tipo de saída

Descrição

Exemplo

RB_BUILD

ARRAY(INT) ou ARRAY(BIGINT)

ROARING BITMAP

Cria um Roaring Bitmap a partir de um array de inteiros.

RB_BUILD(ARRAY[1,2,3])

RB_BUILD_RANGE

INT, INT ou BIGINT, BIGINT

ROARING BITMAP

Gera um Roaring Bitmap a partir de um intervalo: início (inclusivo) até fim (exclusivo).

RB_BUILD_RANGE(0, 10000)

RB_BUILD_VARBINARY

VARBINARY

ROARING BITMAP

Constrói um Roaring Bitmap a partir de dados VARBINARY.

RB_BUILD_VARBINARY(RB_TO_VARBINARY(RB_BUILD(ARRAY[1,2,3])))

RB_CARDINALITY

ROARING BITMAP

BIGINT

Retorna a quantidade de elementos no bitmap.

RB_CARDINALITY(RB_BUILD(ARRAY[1,2,3]))

RB_CONTAINS

ROARING BITMAP, INT ou ROARING BITMAP, BIGINT

BOOLEAN

Retorna true se o bitmap contiver o inteiro especificado.

RB_CONTAINS(RB_BUILD(ARRAY[1,2,3]), 3)

RB_CONTAINS

ROARING BITMAP, ROARING BITMAP

BOOLEAN

Devolve true caso o primeiro bitmap contenha todos os elementos do segundo.

RB_CONTAINS(RB_BUILD(ARRAY[1,2,3]), RB_BUILD(ARRAY[3]))

RB_AND

ROARING BITMAP, ROARING BITMAP

ROARING BITMAP

Calcula a interseção (AND) de dois bitmaps.

RB_AND(RB_BUILD(ARRAY[1,2,3]), RB_BUILD(ARRAY[2,3,4]))

RB_OR

ROARING BITMAP, ROARING BITMAP

ROARING BITMAP

Realiza a união (OR) de dois bitmaps.

RB_OR(RB_BUILD(ARRAY[1,2,3]), RB_BUILD(ARRAY[2,3,4]))

RB_XOR

ROARING BITMAP, ROARING BITMAP

ROARING BITMAP

Executa o OR exclusivo (XOR) entre dois bitmaps.

RB_XOR(RB_BUILD(ARRAY[1,2,3]), RB_BUILD(ARRAY[2,3,4]))

RB_AND_NULL2EMPTY

ROARING BITMAP, ROARING BITMAP

ROARING BITMAP

Operação AND com tratamento seguro para nulos: se uma entrada for NULL, a outra é utilizada; se uma entrada for {}, o resultado será {}.

RB_AND_NULL2EMPTY(RB_BUILD(null), RB_BUILD(ARRAY[3,4,5]))

RB_OR_NULL2EMPTY

ROARING BITMAP, ROARING BITMAP

ROARING BITMAP

Operação OR segura contra nulos: entradas NULL são tratadas como {}.

RB_OR_NULL2EMPTY(RB_BUILD(null), RB_BUILD(ARRAY[3,4,5]))

RB_ANDNOT_NULL2EMPTY

ROARING BITMAP, ROARING BITMAP

ROARING BITMAP

Operação ANDNOT com proteção contra nulos: entradas NULL são interpretadas como {}.

RB_ANDNOT_NULL2EMPTY(RB_BUILD(null), RB_BUILD(ARRAY[3,4,5]))

RB_AND_CARDINALITY

ROARING BITMAP, ROARING BITMAP

BIGINT

Obtém a cardinalidade do resultado da operação AND.

RB_AND_CARDINALITY(RB_BUILD(ARRAY[1,2,3]), RB_BUILD(ARRAY[3,4,5]))

RB_AND_NULL2EMPTY_CARDINALITY

ROARING BITMAP, ROARING BITMAP

BIGINT

Retorna a cardinalidade do resultado AND; entradas NULL são consideradas como {}.

RB_AND_NULL2EMPTY_CARDINALITY(RB_BUILD(null), RB_BUILD(ARRAY[3,4,5]))

RB_OR_CARDINALITY

ROARING BITMAP, ROARING BITMAP

BIGINT

Fornece a cardinalidade resultante da operação OR.

RB_OR_CARDINALITY(RB_BUILD(ARRAY[1,2,3]), RB_BUILD(ARRAY[3,4,5]))

RB_OR_NULL2EMPTY_CARDINALITY

ROARING BITMAP, ROARING BITMAP

BIGINT

Calcula a cardinalidade do resultado OR; entradas NULL equivalem a {}.

RB_OR_NULL2EMPTY_CARDINALITY(RB_BUILD(null), RB_BUILD(ARRAY[3,4,5]))

RB_XOR_CARDINALITY

ROARING BITMAP, ROARING BITMAP

BIGINT

Indica a cardinalidade do resultado XOR.

RB_XOR_CARDINALITY(RB_BUILD(ARRAY[1,2,3]), RB_BUILD(ARRAY[3,4,5]))

RB_ANDNOT_CARDINALITY

ROARING BITMAP, ROARING BITMAP

BIGINT

Mostra a cardinalidade após a operação ANDNOT.

RB_ANDNOT_CARDINALITY(RB_BUILD(ARRAY[1,2,3]), RB_BUILD(ARRAY[3,4,5]))

RB_ANDNOT_NULL2EMPTY_CARDINALITY

ROARING BITMAP, ROARING BITMAP

BIGINT

Apura a cardinalidade do resultado ANDNOT; valores NULL são tratados como {}.

RB_ANDNOT_NULL2EMPTY_CARDINALITY(RB_BUILD(ARRAY[1,2,3]), RB_BUILD(ARRAY[3,4,5]))

RB_IS_EMPTY

ROARING BITMAP

BOOLEAN

Verifique se o bitmap está vazio, retornando true nesse caso.

RB_IS_EMPTY(RB_BUILD(ARRAY[]))

RB_CLEAR

ROARING BITMAP, BIGINT, BIGINT

ROARING BITMAP

Remove elementos no intervalo especificado: início (inclusivo) até fim (exclusivo).

RB_CLEAR(RB_BUILD('{1,2,3}'), 2, 3)

RB_FLIP

ROARING BITMAP, INT, INT ou ROARING BITMAP, BIGINT, BIGINT

ROARING BITMAP

Inverte os bits no intervalo de deslocamento definido.

RB_FLIP(RB_BUILD(ARRAY[1,2,3,4,5]), 2, 5)

RB_MINIMUM

ROARING BITMAP

INT ou BIGINT

Encontra o menor elemento. Gera erro se o bitmap estiver vazio.

RB_MINIMUM(RB_BUILD(ARRAY[1,2,3]))

RB_MAXIMUM

ROARING BITMAP

INT ou BIGINT

Identifica o maior elemento. Falha caso o bitmap não tenha dados.

RB_MAXIMUM(RB_BUILD(ARRAY[1,2,3]))

RB_RANK

ROARING BITMAP, INT ou ROARING BITMAP, BIGINT

BIGINT

Conta quantos elementos são menores ou iguais ao deslocamento informado.

RB_RANK(RB_BUILD(ARRAY[1,2,3]), 2)

RB_TO_ARRAY

ROARING BITMAP

ARRAY(INT)

Converte os elementos em um array INT.

RB_TO_ARRAY(RB_BUILD(ARRAY[1,2,3]))

RB_TO_LONG_ARRAY

ROARING BITMAP

ARRAY(BIGINT)

Transforma os elementos em um array BIGINT.

RB_TO_LONG_ARRAY(RB_BUILD(ARRAY[4,5,6]))

RB_TO_VARBINARY

ROARING BITMAP

VARBINARY

Serializa o bitmap para o formato VARBINARY.

RB_TO_VARBINARY(RB_BUILD(ARRAY[1,2,3]))

RB_RANGE_CARDINALITY

ROARING BITMAP, INT, INT ou ROARING BITMAP, BIGINT, BIGINT

BIGINT

Calcula a cardinalidade dos elementos nas posições de início (inclusivo) a fim (exclusivo). A posição baseia-se em 1. Requer versão 3.1.10.0 ou superior.

RB_RANGE_CARDINALITY(RB_BUILD(ARRAY[1,2,3]), 2, 3)

RB_SELECT

ROARING BITMAP, BIGINT, BIGINT

ROARING BITMAP

Extrai elementos nas posições de início (inclusivo) a fim (exclusivo). A contagem de posição começa em 1. Disponível a partir da versão 3.1.10.0.

RB_SELECT(RB_BUILD(ARRAY[1,3,4,5,7,9]), 2, 3)

Funções de agregação

Função

Tipo de entrada

Tipo de saída

Descrição

Exemplo

RB_BUILD_AGG

INT ou BIGINT

ROARING BITMAP

Consolida valores inteiros de várias linhas em um único bitmap.

RB_CARDINALITY(RB_BUILD_AGG(1))

RB_OR_AGG

ROARING BITMAP

ROARING BITMAP

Aplica agregação OR em múltiplos bitmaps.

RB_CARDINALITY(RB_OR_AGG(RB_BUILD(ARRAY[1,2,3])))

RB_AND_AGG

ROARING BITMAP

ROARING BITMAP

Efetua agregação AND entre diversos bitmaps.

RB_CARDINALITY(RB_AND_AGG(RB_BUILD(ARRAY[1,2,3])))

RB_XOR_AGG

ROARING BITMAP

ROARING BITMAP

Processa agregação XOR sobre vários bitmaps.

RB_CARDINALITY(RB_XOR_AGG(RB_BUILD(ARRAY[1,2,3])))

RB_OR_CARDINALITY_AGG

ROARING BITMAP

INT ou BIGINT

Execute agregação OR e devolve a cardinalidade total.

RB_OR_CARDINALITY_AGG(RB_BUILD(ARRAY[1,2,3]))

RB_AND_CARDINALITY_AGG

ROARING BITMAP

INT ou BIGINT

Realiza agregação AND e retorna a cardinalidade correspondente.

RB_AND_CARDINALITY_AGG(RB_BUILD(ARRAY[1,2,3]))

RB_XOR_CARDINALITY_AGG

ROARING BITMAP

INT ou BIGINT

Faz agregação XOR e fornece a cardinalidade resultante.

RB_XOR_CARDINALITY_AGG(RB_BUILD(ARRAY[1,2,3]))

Uso básico

Os exemplos a seguir demonstram como criar uma tabela, inserir dados de bitmap e executar consultas escalares e de agregação.

Tabela interna

  1. Crie uma tabela interna com uma coluna ROARINGBITMAP.

    CREATE TABLE `test_rb` (
      `id` INT,
      `rb` ROARINGBITMAP
    );
  2. Insira dados de bitmap.

    INSERT INTO test_rb VALUES (1, '[1, 2, 3]');
    INSERT INTO test_rb VALUES (2, '[2, 3, 4, 5, 6]');
  3. Obtenha a cardinalidade de cada linha.

    SELECT id, RB_CARDINALITY(rb) FROM test_rb;
    +------+--------------------+
    | id   | rb_cardinality(rb) |
    +------+--------------------+
    |    2 |                  5 |
    |    1 |                  3 |
    +------+--------------------+
  4. Calcule a cardinalidade da união de todas as linhas.

    SELECT RB_OR_CARDINALITY_AGG(rb) FROM test_rb;
    +---------------------------+
    | rb_or_cardinality_agg(rb) |
    +---------------------------+
    |                         6 |
    +---------------------------+

Tabela externa

  1. Crie uma tabela externa do OSS com uma coluna ROARINGBITMAP.

    CREATE TABLE `test_rb` (
      `id` INT,
      `rb` ROARINGBITMAP
    ) engine = 'oss'
    TABLE_PROPERTIES = '{
      "endpoint": "oss-cn-zhangjiakou.aliyuncs.com",
      "accessid": "************",
      "accesskey": "************",
      "url": "oss://testBucketName/roaringbitmap/test_for_user/",
      "format": "parquet"
    }';

    Para parâmetros de tabelas externas, consulte Tabela externa não particionada do OSS.

  2. Insira dados de bitmap.

    Importante

    O comando INSERT INTO é ineficiente para gravações em grande escala. Para grandes conjuntos de dados, gere arquivos Parquet usando uma ferramenta ETL e faça upload deles no caminho do OSS antes de criar a tabela externa.

    INSERT INTO test_rb SELECT 1, rb_build(ARRAY[1,2,3]);
    INSERT INTO test_rb SELECT 2, rb_build(ARRAY[2,3,4,5]);
  3. Consulte a cardinalidade por linha.

    SELECT id, RB_CARDINALITY(rb) FROM test_rb;
    +------+--------------------+
    | id   | rb_cardinality(rb) |
    +------+--------------------+
    |    2 |                  4 |
    |    1 |                  3 |
    +------+--------------------+
  4. Determine a cardinalidade da união em todas as linhas.

    SELECT RB_OR_CARDINALITY_AGG(rb) FROM test_rb;
    +---------------------------+
    | rb_or_cardinality_agg(rb) |
    +---------------------------+
    |                         5 |
    +---------------------------+

Tutorial de perfilamento de usuários

Este tutorial percorre um fluxo completo de perfilamento de usuários: construção de uma tabela de tags a partir de dados brutos, conversão para formato bitmap visando operações de conjuntos eficientes e execução de análises multidimensionais.

Workflow overview: original label table converted to Roaring Bitmap label table for computations

Etapa 1: Preparar a tabela de tags de origem

  1. Crie a tabela de source users_base.

    CREATE TABLE users_base (
      uid  INT,
      tag1 STRING,  -- Valid values: x, y, z
      tag2 STRING,  -- Valid values: a, b
      tag3 INT      -- Valid values: 1 to 10
    );
  2. Gere 100 milhões de linhas de dados de teste aleatórios usando uma junção cruzada de dois intervalos de bitmap (10.000 × 10.000 = 100.000.000 linhas).

    SUBMIT JOB
    INSERT OVERWRITE users_base
    SELECT
      CAST(ROW_NUMBER() OVER (ORDER BY c1) AS INT) AS uid,
      SUBSTRING('xyz', FLOOR(RAND() * 3) + 1, 1) AS tag1,
      SUBSTRING('ab',  FLOOR(RAND() * 2) + 1, 1) AS tag2,
      CAST(FLOOR(RAND() * 10) + 1 AS INT)         AS tag3
    FROM (
      SELECT A.c1 FROM
        UNNEST(RB_BUILD_RANGE(0, 10000)) AS A(c1)
        JOIN (SELECT c1 FROM UNNEST(RB_BUILD_RANGE(0, 10000)) AS B(c1))
    );
  3. Verifique os dados.

    SELECT * FROM users_base LIMIT 10;
    +--------+------+------+------+
    | uid    | tag1 | tag2 | tag3 |
    +--------+------+------+------+
    |  74526 | y    | b    |    3 |
    |  75611 | z    | b    |   10 |
    |  80850 | x    | b    |    5 |
    |  81656 | z    | b    |    7 |
    | 163845 | x    | b    |    2 |
    | 167007 | y    | b    |    4 |
    | 170541 | y    | b    |    9 |
    | 213108 | x    | a    |   10 |
    |  66056 | y    | b    |    4 |
    |  67761 | z    | a    |    2 |
    +--------+------+------+------+

Etapa 2: Adicionar campos de agrupamento

As operações de bitmap em um mecanismo distribuído rodam em paralelo entre grupos. Adicione um campo user_group para particionar UIDs entre grupos e um campo offset para codificar a posição do UID dentro de cada grupo.

Este exemplo utiliza 16 grupos com a fórmula uid = 16 × offset + user_group:

  • user_group = uid % 16 — defina o grupo ao qual o UID pertence

  • offset = uid / 16 — indica a posição do UID dentro do grupo

Dimensionamento dos grupos: O bitmap de cada grupo deve conter menos de 100 milhões de entradas. Para um espaço de UID de 10 bilhões, utilize 100 grupos de 100 milhões cada. Ajuste a quantidade de grupos conforme as ACUs do seu cluster e o espaço total de UIDs.

Nota

A fórmula de agrupamento acima serve apenas para ilustração. Elabore sua própria função de agrupamento com base na distribuição dos seus dados.

  1. Crie a tabela users incluindo os campos de agrupamento.

    CREATE TABLE users (
      uid        INT,
      tag1       STRING,
      tag2       STRING,
      tag3       INT,
      user_group INT,  -- Grouping field: uid % 16
      offset     INT   -- Offset field: uid / 16
    );
  2. Preencha a tabela users usando dados de users_base.

    SUBMIT JOB INSERT OVERWRITE users
    SELECT
      uid, tag1, tag2, tag3,
      CAST(uid % 16 AS INT),
      CAST(FLOOR(uid / 16) AS INT)
    FROM users_base;
  3. Valide os dados inseridos.

    SELECT * FROM users LIMIT 10;
    +---------+------+------+------+------------+--------+
    | uid     | tag1 | tag2 | tag3 | user_group | offset |
    +---------+------+------+------+------------+--------+
    |  377194 | z    | b    |   10 |         10 |  23574 |
    |  309440 | x    | a    |    1 |          0 |  19340 |
    |  601745 | z    | a    |    7 |          1 |  37609 |
    |  753751 | z    | b    |    3 |          7 |  47109 |
    |  988186 | y    | a    |   10 |         10 |  61761 |
    |  883822 | x    | a    |    9 |         14 |  55238 |
    |  325065 | x    | b    |    6 |          9 |  20316 |
    | 1042875 | z    | a    |   10 |         11 |  65179 |
    |  928606 | y    | b    |    5 |         14 |  58037 |
    |  990858 | z    | a    |    8 |         10 |  61928 |
    +---------+------+------+------+------------+--------+

Etapa 3: Construir tabelas de tags bitmap

Para cada dimensão de tag, crie uma tabela de tags bitmap onde cada linha armazena um bitmap por par (tag_value, user_group). O bitmap codifica os offsets de todos os usuários correspondentes naquele grupo.

Tabela interna

  1. Crie e preencha a tabela de tags bitmap para tag1.

    CREATE TABLE `tag_tbl_1` (
      `tag1`       STRING,
      `rb`         ROARINGBITMAP,
      `user_group` INT
    );
    
    INSERT OVERWRITE tag_tbl_1
    SELECT tag1, RB_BUILD_AGG(offset), user_group
    FROM users
    GROUP BY tag1, user_group;
  2. Confira a tabela de tags.

    SELECT tag1, user_group, RB_CARDINALITY(rb) FROM tag_tbl_1;
    +------+------------+--------------------+
    | tag1 | user_group | rb_cardinality(rb) |
    +------+------------+--------------------+
    | y    |         13 |             563654 |
    | x    |         11 |             565013 |
    | z    |          2 |             564428 |
    | x    |          4 |             564377 |
    ...
    | z    |          5 |             564333 |
    | x    |          8 |             564808 |
    | x    |          0 |             564228 |
    | y    |          3 |             563325 |
    +------+------------+--------------------+
  3. Construa e popule a tabela de tags bitmap referente a tag2.

    CREATE TABLE `tag_tbl_2` (
      `tag2`       STRING,
      `rb`         ROARINGBITMAP,
      `user_group` INT
    );
    
    INSERT OVERWRITE tag_tbl_2
    SELECT tag2, RB_BUILD_AGG(offset), user_group
    FROM users
    GROUP BY tag2, user_group;
  4. Analise a tabela de tags gerada.

    SELECT tag2, user_group, RB_CARDINALITY(rb) FROM tag_tbl_2;
    +------+------------+--------------------+
    | tag2 | user_group | rb_cardinality(rb) |
    +------+------------+--------------------+
    | a    |          9 |            3123039 |
    | a    |          5 |            3123973 |
    | a    |         12 |            3122414 |
    | a    |          7 |            3127218 |
    | a    |         15 |            3125403 |
    ...
    | a    |         10 |            3122698 |
    | b    |          4 |            3126091 |
    | b    |          3 |            3124626 |
    | b    |          9 |            3126961 |
    | b    |         14 |            3125351 |
    +------+------------+--------------------+

Tabela externa

  1. Defina e carregue a tabela de tags bitmap para tag1 no OSS.

    CREATE TABLE `tag_tbl_1` (
      `tag1`       STRING,
      `rb`         ROARINGBITMAP,
      `user_group` INT
    ) engine = 'oss'
    TABLE_PROPERTIES = '{
      "endpoint":  "oss-cn-zhangjiakou.aliyuncs.com",
      "accessid":  "************",
      "accesskey": "************",
      "url":       "oss://testBucketName/roaringbitmap/tag_tbl_1/",
      "format":    "parquet"
    }';
    
    INSERT OVERWRITE tag_tbl_1
    SELECT tag1, RB_BUILD_AGG(offset), user_group
    FROM users
    GROUP BY tag1, user_group;
  2. Inspecione a tabela de tags.

    SELECT tag1, user_group, RB_CARDINALITY(rb) FROM tag_tbl_1;
    +------+------------+--------------------+
    | tag1 | user_group | rb_cardinality(rb) |
    +------+------------+--------------------+
    | z    |          7 |            2082608 |
    | x    |         10 |            2082953 |
    | y    |          7 |            2084730 |
    | x    |         14 |            2084856 |
    ...
    | z    |         15 |            2084535 |
    | z    |          5 |            2083204 |
    | x    |         11 |            2085239 |
    | z    |          1 |            2084879 |
    +------+------------+--------------------+
  3. Estruture e alimente a tabela de tags bitmap para tag2 no OSS.

    CREATE TABLE `tag_tbl_2` (
      `tag2`       STRING,
      `rb`         ROARINGBITMAP,
      `user_group` INT
    ) engine = 'oss'
    TABLE_PROPERTIES = '{
      "endpoint":  "oss-cn-zhangjiakou.aliyuncs.com",
      "accessid":  "************",
      "accesskey": "************",
      "url":       "oss://testBucketName/roaringbitmap/tag_tbl_2/",
      "format":    "parquet"
    }';
    
    INSERT OVERWRITE tag_tbl_2
    SELECT tag2, RB_BUILD_AGG(offset), user_group
    FROM users
    GROUP BY tag2, user_group;
  4. Revise a tabela de tags criada.

    SELECT tag2, user_group, RB_CARDINALITY(rb) FROM tag_tbl_2;
    +------+------------+--------------------+
    | tag2 | user_group | rb_cardinality(rb) |
    +------+------------+--------------------+
    | b    |         11 |            3121361 |
    | a    |          6 |            3124750 |
    | a    |          1 |            3125433 |
    ...
    | b    |          2 |            3126523 |
    | b    |         12 |            3123452 |
    | a    |          4 |            3126111 |
    | a    |         13 |            3123316 |
    | a    |          2 |            3123477 |
    +------+------------+--------------------+

Etapa 4: Analisar com tabelas de tags bitmap

Os cenários abaixo apresentam padrões comuns de análise utilizando as tabelas de tags bitmap construídas na Etapa 3.

Cenário 1: Filtrar e agrupar

Conte usuários onde tag1 IN ('x', 'y'), agrupando por tag2.

Todas as consultas seguem o mesmo padrão: junte as tabelas de tags bitmap por user_group, aplique operações de conjunto por grupo e depois agregue entre os grupos.

  1. Examine os resultados intermediários por grupo.

    SELECT
      tag2,
      t1.user_group AS user_group,
      RB_CARDINALITY(RB_AND(t2.rb, rb1)) AS rb
    FROM tag_tbl_2 AS t2
    JOIN (
      SELECT user_group, rb AS rb1
      FROM tag_tbl_1
      WHERE tag1 IN ('x', 'y')
    ) AS t1 ON t1.user_group = t2.user_group;
    +------+------------+---------+
    | tag2 | user_group | rb      |
    +------+------------+---------+
    | b    |          3 | 1041828 |
    | a    |         15 | 1039859 |
    | a    |          9 | 1039140 |
    | b    |          1 | 1041524 |
    | a    |          4 | 1041599 |
    | b    |          1 | 1041381 |
    | b    |         10 | 1041026 |
    | b    |          6 | 1042289 |
    +------+------------+---------+
  2. Some as contagens por grupo para obter os totais finais.

    SELECT tag2, SUM(cnt) FROM (
      SELECT
        tag2,
        t1.user_group AS user_group,
        RB_CARDINALITY(RB_AND(t2.rb, rb1)) AS cnt
      FROM tag_tbl_2 AS t2
      JOIN (
        SELECT user_group, rb AS rb1
        FROM tag_tbl_1
        WHERE tag1 IN ('x', 'y')
      ) AS t1 ON t1.user_group = t2.user_group
    ) GROUP BY tag2;
    +------+----------+
    | tag2 | sum(cnt) |
    +------+----------+
    | a    | 33327868 |
    | b    | 33335220 |
    +------+----------+

Cenário 2: Interseção entre duas tabelas de tags bitmap

Encontre usuários onde (tag1 = 'x' OR tag1 = 'y') AND tag2 = 'b'.

Ambas as entradas vêm de tabelas de tags bitmap. Primeiro faça a agregação OR dentro de cada tabela de tags e depois aplique AND nos resultados entre as duas.

SELECT user_group, RB_CARDINALITY(rb) FROM (
  SELECT
    t1.user_group AS user_group,
    RB_AND(rb1, rb2) AS rb
  FROM (
    SELECT user_group, RB_OR_AGG(rb) AS rb1
    FROM tag_tbl_1
    WHERE tag1 = 'x' OR tag1 = 'y'
    GROUP BY user_group
  ) AS t1
  JOIN (
    SELECT user_group, RB_OR_AGG(rb) AS rb2
    FROM tag_tbl_2
    WHERE tag2 = 'b'
    GROUP BY user_group
  ) AS t2 ON t1.user_group = t2.user_group
  GROUP BY user_group
);
+------------+--------------------+
| user_group | rb_cardinality(rb) |
+------------+--------------------+
|         10 |            2083679 |
|          3 |            2082370 |
|          9 |            2082847 |
|          2 |            2086511 |
...
|          1 |            2082291 |
|          4 |            2083290 |
|         14 |            2083581 |
|         15 |            2084110 |
+------------+--------------------+

Cenário 3: Interseção entre uma tabela de tags bitmap e a tabela de source

Localize usuários onde (tag1 = 'x' OR tag1 = 'y') AND tag2 = 'b', sendo que a segunda condição é filtrada diretamente da tabela bruta users em vez de uma tabela de tags bitmap pré-construída.

Utilize RB_BUILD_AGG para gerar um bitmap dinamicamente a partir da tabela users e então aplique AND com o bitmap pré-existente de tag_tbl_1.

SELECT user_group, RB_CARDINALITY(rb) FROM (
  SELECT
    t1.user_group AS user_group,
    RB_AND(rb1, rb2) AS rb
  FROM (
    SELECT user_group, RB_OR_AGG(rb) AS rb1
    FROM tag_tbl_1
    WHERE tag1 = 'x' OR tag1 = 'y'
    GROUP BY user_group
  ) AS t1
  JOIN (
    SELECT user_group, RB_BUILD_AGG(offset) AS rb2
    FROM users
    WHERE tag2 = 'b'
    GROUP BY user_group
  ) AS t2 ON t1.user_group = t2.user_group
  GROUP BY user_group
);
+------------+--------------------+
| user_group | rb_cardinality(rb) |
+------------+--------------------+
|          3 |            2082370 |
|          1 |            2082291 |
|          0 |            2082383 |
|          4 |            2083290 |
|         11 |            2081662 |
|         13 |            2085280 |
...
|         14 |            2083581 |
|         15 |            2084110 |
|          9 |            2082847 |
|          8 |            2084860 |
|          5 |            2083056 |
|          7 |            2083275 |
+------------+--------------------+

Cenário 4: Exportar resultados de bitmap para o OSS

Salve os resultados de bitmap do Cenário 2 em uma tabela externa do OSS para uso posterior.

  1. Crie a tabela de saída.

    CREATE TABLE `tag_tbl_3` (
      `user_group` INT,
      `rb`         ROARINGBITMAP
    ) engine = 'oss'
    TABLE_PROPERTIES = '{
      "endpoint":  "oss-cn-zhangjiakou.aliyuncs.com",
      "accessid":  "************",
      "accesskey": "************",
      "url":       "oss://testBucketName/roaringbitmap/tag_tbl_3/",
      "format":    "parquet"
    }';
  2. Grave os resultados do Cenário 2 em tag_tbl_3.

    INSERT OVERWRITE tag_tbl_3
    SELECT
      t1.user_group AS user_group,
      RB_AND(rb1, rb2) AS rb
    FROM (
      SELECT user_group, RB_OR_AGG(rb) AS rb1
      FROM tag_tbl_1
      WHERE tag1 = 'x' OR tag1 = 'y'
      GROUP BY user_group
    ) AS t1
    JOIN (
      SELECT user_group, RB_OR_AGG(rb) AS rb2
      FROM tag_tbl_2
      WHERE tag2 = 'b'
      GROUP BY user_group
    ) AS t2 ON t1.user_group = t2.user_group;

    Após a conclusão da consulta, o resultado fica armazenado em formato Parquet no caminho oss://testBucketName/roaringbitmap/tag_tbl_3/.

Cenário 5: Acelerar consultas com uma tabela de cache interna (para tabelas externas)

Importe dados de bitmap de uma tabela externa do OSS para uma tabela interna a fim de agilizar consultas repetidas. Como tabelas internas anteriores à versão V3.2.1.0 não suportam nativamente o tipo ROARINGBITMAP, armazene os bitmaps como VARBINARY e faça a conversão durante a consulta.

  1. Crie a tabela de cache interna com uma coluna VARBINARY para o bitmap.

    CREATE TABLE `tag_tbl_1_cstore` (
      `tag1`       VARCHAR,
      `rb`         VARBINARY,
      `user_group` INT
    );
  2. Importe da tabela do OSS, serializando cada bitmap para VARBINARY.

    INSERT INTO tag_tbl_1_cstore
    SELECT tag1, RB_TO_VARBINARY(rb), user_group
    FROM tag_tbl_1;
  3. Consulte a tabela de cache, desserializando VARBINARY de volta para bitmaps no momento da execução.

    SELECT
      tag1,
      user_group,
      RB_CARDINALITY(RB_OR_AGG(RB_BUILD_VARBINARY(rb)))
    FROM tag_tbl_1_cstore
    GROUP BY tag1, user_group;
    +------+------------+---------------------------------------------------+
    | tag1 | user_group | rb_cardinality(rb_or_agg(rb_build_varbinary(rb))) |
    +------+------------+---------------------------------------------------+
    | y    |          3 |                                           2082919 |
    | x    |          9 |                                           2083085 |
    | x    |          3 |                                           2082140 |
    | y    |         11 |                                           2082268 |
    | z    |          4 |                                           2082451 |
    ...
    | z    |          2 |                                           2081560 |
    | y    |          6 |                                           2082194 |
    | z    |          7 |                                           2082608 |
    +------+------------+---------------------------------------------------+