Tüm Ürünler
Search
Belge Merkezi

ApsaraDB for SelectDB:BITMAP ile Kesin Tekilleştirme

Son Güncelleme:Oct 08, 2026

Veri kümeniz yüz milyonlarca satıra ulaştığında, COUNT(DISTINCT ...) yavaşlar. Tüm farklı değerler, nihai birleştirme işlemi için her düğümden tek bir üst düzey düğüme aktarılır; bu durum, veri hacmi ve bitmap boyutuyla birlikte büyüyen bir darboğaz yaratır. ApsaraDB for SelectDB, bu sorunu ortogonal bitmap kullanarak çözer: Veriler paketlere ayrılır, böylece her düğüm kendi kesişimini veya birleşimini bağımsız olarak hesaplayabilir ve yalnızca azaltılmış sonuçlar üst düzey düğüme gider.

Ortogonal Bitmap Nasıl Çalışır?

Standart COUNT(DISTINCT ...) iki aşamada çalışır:

Scan (Node 1)              Scan (Node 2)
+---------+---------+      +---------+---------+
| user_id | tag     |      | user_id | tag     |
+---------+---------+      +---------+---------+
| 1       | A       |      | 3       | A       |
| 2       | B       |      | 4       | C       |
+---------+---------+      +---------+---------+
         |                          |
         +----------+  +-----------+
                    |  |
             Top-level node
         Receives ALL distinct values
         from every node, merges them
         (bottleneck: I/O + single-node compute)

Bir bitmap 1 GB'ı aştığında, bu son birleştirme adımı hem ağ G/Ç'sinde hem de tek düğüm hesaplama yükünde darboğaza neden olur.

ApsaraDB for SelectDB, bu darboğazı bir hid (hash ID) sütunu kullanarak önler. Tablo oluşturma sırasında, kullanıcı kimlikleri bir hash algoritması kullanılarak paketlere atanır. Farklı paketlerdeki bitmap değerleri ortogonaldir (örtüşmez), böylece her paket kendi sonucunu bağımsız olarak hesaplar:

Stage 1 (distributed): each bucket computes intersection/union locally
Stage 2 (merge): top-level node combines per-bucket results (small data only)

Bu yaklaşım, tek düğüm darboğazını ortadan kaldırır ve milyarlarca satıra kadar ölçeklendirilebilir.

Sınırlamalar

Başlamadan önce aşağıdaki kısıtlamaları dikkate alın:

  • Aggregate Key modeli gereklidir: Bitmap sütunu, Aggregate Key modelini kullanan bir tabloda bulunmalı ve toplama işlevi olarak BITMAP_UNION kullanılmalıdır.

  • Bölümlendirilmiş tablolar desteklenmez: Ortogonal bitmap işlevleri bölümlendirilmiş tablolarda kullanılamaz. Bölüm sınırları, paketler arasındaki ortogonallik garantisini bozar ve sonuçların güvenilirliğini zedeler.

  • hid kardinalite gereksinimi: Hash paketlemesinden sonra dengeli veri dağıtımı sağlamak için hid sütununun kardinalitesi, paket sayısının en az beş katı olmalıdır.

Bitmap Tekilleştirmeyi Ayarlama

1. Adım: Tabloyu Oluşturma

Bitmap Value alanı ve hash paketleme için bir hid sütunu içeren Aggregate Key modelini kullanarak bir tablo oluşturun.

CREATE TABLE `user_tag_bitmap` (
  `tag`     BIGINT(20)  NULL COMMENT "User tag",
  `hid`     SMALLINT(6) NULL COMMENT "Bucket ID",
  `user_id` BITMAP BITMAP_UNION NULL COMMENT "User bitmap"
) ENGINE=OLAP
AGGREGATE KEY(`tag`, `hid`)
COMMENT "OLAP"
DISTRIBUTED BY HASH(`hid`) BUCKETS 3;

hid sütunu, user_id aralığını gruplara böler ve her grubu tek bir pakete atar. Bu durum, paketler arasındaki bitmap değerlerinin ortogonal olmasını sağlar.

Not

hid kardinalitesini paket sayısının en az beş katına ayarlayın. Örneğin, 3 paket varsa hid en az 15 farklı değere sahip olmalıdır.

2. Adım: Verileri İçe Aktarma

Verileri yüklemek için bir LOAD LABEL deyimi kullanın. ceil(tmp_user_id/500) ifadesi, her satır için hid değerini hesaplar ve to_bitmap(tmp_user_id) ham tamsayıyı bir bitmap girişine dönüştürür.

LOAD LABEL user_tag_bitmap_test
(
    DATA INFILE('hdfs://abc')
    INTO TABLE user_tag_bitmap
    COLUMNS TERMINATED BY ','
    (tmp_tag, tmp_user_id)
    SET (
        tag     = tmp_tag,
        hid     = ceil(tmp_user_id/500),
        user_id = to_bitmap(tmp_user_id)
    )
)
Not

Bölen 500 sabit değildir. Beklenen kullanıcı kimliği aralığına ve hedeflediğiniz farklı hid değeri sayısına göre bunu ayarlayın.

Kaynak veri formatı, virgülle ayrılmış iki sütundan oluşur: etiket ve kullanıcı kimliği:

11111111,1
11111112,2
11111113,3
11111114,4

İçe aktarma sırasında, SelectDB [1, 5000000) aralığındaki kullanıcı kimliklerine aynı hid değerini atar ve bunları aynı pakete yerleştirir. Paketler arasındaki bitmap değerleri ortogonal kalır, bu da kesişim ve birleşim işlemlerinin hesaplama maliyetini azaltır.

3. Adım: Ortogonal Bitmap İşlevleriyle Sorgulama

Verileri içe aktardıktan sonra, sonraki bölümde açıklanan ortogonal bitmap işlevlerini kullanın. Standart bitmap işlevlerinin tam listesi için SQL referansı konusuna bakın.

Ortogonal Bitmap İşlevleri

Aşağıdaki beş işlev, ortogonal senaryolarda bitmap sorgularını destekler. Sayı döndüren işlevler, ilgili COUNT(DISTINCT ...) kalıplarının doğrudan yerine geçer ancak dağıtık şekilde çalışır.

İşlev Döndürür Ne zaman kullanılır
bitmap_orthogonal_intersect Bitmap Etiketler arasında kesişim bitmap'i hesaplarken
orthogonal_bitmap_intersect_count Sayı Birden çok etiketin kesişimindeki kullanıcıları sayarken
orthogonal_bitmap_union_count Sayı Etiketler genelindeki toplam farklı kullanıcıları sayarken
orthogonal_bitmap_expr_calculate Bitmap Karmaşık küme ifadelerini (AND, OR, NOT) değerlendirirken
orthogonal_bitmap_expr_calculate_count Sayı Karmaşık küme ifadelerinin sonuçlarını sayarken
Not

Ortogonal bitmap işlevleri bölümlendirilmiş tablolarda kullanılamaz. Bölümler birbirine ortogonal olduğundan, bölümler arasındaki verilerin ortogonal olması garanti edilmez ve sonuçlar güvenilir olmaz.

bitmap_orthogonal_intersect

Belirtilen filtre değerleri boyunca bitmap değerlerinin kesişimini hesaplar ve sonucu bitmap olarak döndürür.

Sözdizimi

bitmap_orthogonal_intersect(bitmap_column, column_to_filter, filter_values)

Parametreler

Parametre Açıklama
bitmap_column Toplanacak bitmap sütunu.
column_to_filter Filtreleme için kullanılan boyut sütunu.
filter_values Boyut sütununu filtrelemek için değişken uzunlukta bir değer listesi.

Örnek

SELECT BITMAP_COUNT(bitmap_orthogonal_intersect(user_id, tag, 13080800, 11110200))
FROM user_tag_bitmap
WHERE tag IN (13080800, 11110200);

Şuna eşdeğerdir:

-- Returns the count of users who appear in ALL specified tags
SELECT COUNT(DISTINCT user_id)
FROM user_tag_bitmap
WHERE tag IN (13080800, 11110200)
  AND <user_id appears in every tag>;

Çalışma sırasında, 1. Aşama satırları belirtilen etiketlere göre filtreler ve ardından her paket için eşleşen tüm etiketler arasında bitmap kesişimini hesaplar. 2. Aşama, paket bazındaki kesişim bitmap'lerini yinelemeli olarak birleştirerek nihai sonucu oluşturur.

orthogonal_bitmap_intersect_count

Bitmap değerlerinin kesişimini hesaplar ve sayıyı doğrudan döndürür. Anlamsal olarak intersect_count ile eşleşir, ancak çalışma paketler arasında dağıtılır.Sözdizimi intersect_count işleviyle aynıdır, ancak uygulama farklıdır.Sözdizimi bitmap_union_count işleviyle aynıdır, ancak uygulama farklıdır.

Sözdizimi

orthogonal_bitmap_intersect_count(bitmap_column, column_to_filter, filter_values)

Parametreler

Parametre Açıklama
bitmap_column Toplanacak bitmap sütunu.
column_to_filter Filtreleme için kullanılan boyut sütunu.
filter_values Boyut sütununu filtrelemek için değişken uzunlukta bir değer listesi.

Örnek

SELECT orthogonal_bitmap_intersect_count(user_id, tag, 1150000, 1150001, 390006)
FROM user_tag_bitmap
WHERE tag IN (1150000, 1150001, 390006);

Çalışma sırasında, 1. Aşama belirtilen etiketlere göre filtreleme yapar, eşleşen tüm etiketler arasında bitmap kesişimini hesaplar ve sonucu paket başına sayar. 2. Aşama, tüm paket bazındaki sayıları toplayarak nihai toplamı oluşturur.

orthogonal_bitmap_union_count

Bitmap değerlerinin birleşimini hesaplar ve sayıyı döndürür. Anlamsal olarak BITMAP_UNION_COUNT ile eşleşir, ancak çalışma paketler arasında dağıtılır.

Sözdizimi

orthogonal_bitmap_union_count(bitmap_column)

Parametreler

Parametre Açıklama
bitmap_column Değerleri birleştirilip sayılacak bitmap sütunu.

Örnek

SELECT orthogonal_bitmap_union_count(user_id)
FROM user_tag_bitmap
WHERE tag IN (1150000, 1150001, 390006);

Şuna eşdeğerdir:

SELECT COUNT(DISTINCT user_id)
FROM user_tag_bitmap
WHERE tag IN (1150000, 1150001, 390006);

Çalışma sırasında, 1. Aşama paket başına bitmap birleşimini hesaplar ve sonucu sayar. 2. Aşama, tüm paket bazındaki sayıları toplayarak nihai toplamı oluşturur.

orthogonal_bitmap_expr_calculate

Bitmap sütunları arasında bir küme ifadesini değerlendirir ve sonucu bitmap olarak döndürür. Yalnızca bir sayı değil, daha fazla işlem için bitmap'in kendisine ihtiyacınız olduğunda bu işlevi kullanın.

Sözdizimi

orthogonal_bitmap_expr_calculate(bitmap_column, filter_column, input_string)

Parametreler

Parametre Açıklama
bitmap_column Toplanacak bitmap sütunu.
filter_column Filtreleme için kullanılan boyut sütunu (hesaplama için anahtar sütun).
input_string Anahtar sütun değerleri üzerinde bir küme ifade dizesi.

input_string aşağıdaki operatörleri destekler:

Operatör İşlem
& Kesişim
| Birleşim
- Fark
^ Özel XOR
\ Kaçış karakteri

Örnek

SELECT orthogonal_bitmap_expr_calculate(
    user_id,
    tag,
    '(833736|999777)&(1308083|231207)&(1000|20000-30000)'
)
FROM user_tag_bitmap
WHERE tag IN (833736, 999777, 130808, 231207, 1000, 20000, 30000);

Çalışma sırasında, 1. Aşama etiket filtresini belirlemek için input_string değerini ayrıştırır, verileri filtreler ve filtrelenen satırlara paket başına bitmap ifadesini uygular. 2. Aşama, tüm paket bazındaki bitmap sonuçlarının birleşimini hesaplar ve nihai bitmap'i döndürür.

orthogonal_bitmap_expr_calculate_count

Bitmap sütunları arasında bir küme ifadesini değerlendirir ve sayıyı döndürür. Sözdizimi ve parametreler orthogonal_bitmap_expr_calculate ile aynıdır.

Sözdizimi

orthogonal_bitmap_expr_calculate_count(bitmap_column, filter_column, input_string)

Parametreler

Parametre Açıklama
bitmap_column Toplanacak bitmap sütunu.
filter_column Filtreleme için kullanılan boyut sütunu (hesaplama için anahtar sütun).
input_string Anahtar sütun değerleri üzerinde bir küme ifade dizesi. &, |, -, ^ ve \ operatörlerini destekler.

Örnek

SELECT orthogonal_bitmap_expr_calculate_count(
    user_id,
    tag,
    '(833736|999777)&(1308083|231207)&(1000|20000-30000)'
)
FROM user_tag_bitmap
WHERE tag IN (833736, 999777, 130808, 231207, 1000, 20000, 30000);

Çalışma sırasında, 1. Aşama input_string değerini ayrıştırır, verileri filtreler, bitmap ifadesini uygular ve sonucu paket başına sayar. 2. Aşama, tüm paket bazındaki bitmap sonuçlarının birleşimini hesaplar ve nihai sayıyı döndürür.

Sonraki Adımlar

  • SQL referansı — Bitmap işlevleri bölümündeki bitmap işlevlerinin tam listesi