You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何高效获取GridDB列中唯一值的数量?

GridDB 高效统计字符串列唯一值数量的优化方案

针对你使用GridDB C API统计大量字符串列唯一值的性能问题,以下是几个GridDB专属的优化方案:

1. 使用原生聚合API替代SQL查询

GridDB的C API提供了跳过SQL解析环节的原生聚合接口,直接在存储层执行去重计数,比COUNT(DISTINCT) SQL语句更高效。核心使用gsAggregation系列函数:

#include <griddb/griddb.h>

// 假设已获取GridDB实例gs及容器引用
GSContainer *container;
GSResult ret = gsGetContainer(gs, "myContainer", &container);
if (ret != GS_RESULT_OK) {
    // 错误处理逻辑
}

// 创建DISTINCT COUNT聚合查询
GSQuery *query;
// 最后一个参数GS_TRUE表示启用DISTINCT
ret = gsAggregation(container, "myColumn", GS_AGGREGATION_COUNT, &query, GS_TRUE);
if (ret != GS_RESULT_OK) {
    // 错误处理逻辑
}

// 执行聚合并获取结果
GSRowSet *rowSet;
ret = gsQueryFetch(query, &rowSet);
if (ret == GS_RESULT_OK) {
    GSRow *row;
    if (gsRowSetGetNextRow(rowSet, &row) == GS_RESULT_OK) {
        int64_t distinctCount;
        gsRowGetLong(row, 0, &distinctCount);
        printf("唯一值数量:%lld\n", distinctCount);
        gsRowClose(&row);
    }
    gsRowSetClose(&rowSet);
}

// 资源释放
gsQueryClose(&query);
gsContainerClose(&container);

2. 用物化视图预计算结果

若业务对统计结果的实时性要求不高,可创建物化视图定期预计算唯一值计数,查询时直接读取视图结果,避免重复全量扫描:

创建物化视图(可通过SQL或C API执行)

CREATE MATERIALIZED VIEW mv_myColumn_distinct AS
SELECT COUNT(DISTINCT myColumn) AS distinct_count
FROM myContainer
REFRESH EVERY 1 HOUR; -- 根据业务需求调整刷新间隔

C API查询物化视图

GSContainer *mvContainer;
GSResult ret = gsGetContainer(gs, "mv_myColumn_distinct", &mvContainer);
// 后续逻辑与查询普通容器一致,直接读取distinct_count字段即可

3. 优化容器与集群配置

  • 调整分区策略:如果myColumn的哈希分布均匀,可将容器分区键设置为该列,让每个节点仅处理自身分区内的数据,减少跨节点传输开销。创建容器时配置:
    GSContainerInfo info = GS_CONTAINER_INFO_INITIALIZER;
    info.type = GS_CONTAINER_COLLECTION;
    // 设置列定义...
    info.rowPartitioning = GS_TRUE;
    info.partitionKey = "myColumn";
    info.partitionCount = 32; // 根据集群节点数调整
    gsCreateContainer(gs, "myContainer", &info, NULL);
    
  • 内存配置优化:增加GridDB节点的storeMemoryLimit参数,让更多数据缓存到内存,减少磁盘IO操作。可修改集群配置文件或通过C API动态调整。

4. 客户端批量扫描与本地去重(极端大数据场景)

当服务器端聚合仍有瓶颈时,可通过批量扫描数据,在客户端用哈希表本地去重计数,分散计算压力:

#include <griddb/griddb.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <glib.h> // 示例使用glib哈希表,也可自行实现

int main() {
    // 省略GridDB连接、容器获取逻辑
    GSContainer *container;
    // ...

    GHashTable *distinctValues = g_hash_table_new(g_str_hash, g_str_equal);
    GSQuery *scanQuery;
    gsScan(container, &scanQuery); // 全表扫描

    GSRowSet *rowSet;
    gsQueryFetch(scanQuery, &rowSet);

    GSRow *row;
    while (gsRowSetGetNextRow(rowSet, &row) == GS_RESULT_OK) {
        const char *value;
        gsRowGetString(row, "myColumn", &value);
        g_hash_table_add(distinctValues, g_strdup(value));
        gsRowClose(&row);
    }

    printf("唯一值数量:%zu\n", g_hash_table_size(distinctValues));

    // 资源释放
    g_hash_table_destroy(distinctValues);
    gsRowSetClose(&rowSet);
    gsQueryClose(&scanQuery);
    gsContainerClose(&container);
    return 0;
}

注:此方法需关注客户端内存容量,数据量极大时可分批次扫描逐步去重。


内容的提问来源于stack exchange,提问作者Razedul Raj

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.19 04:42:35