TDengine C/C++ 连接器入门指南

TDengine C/C++ 连接器入门指南

概述

TDengine C/C++ 连接器是 TDengine 提供的官方客户端驱动程序,允许 C/C++ 开发人员连接 TDengine 集群并进行数据存储、查询等操作。本指南将帮助您快速上手 C/C++ 连接器的使用。

前置条件

在开始之前,请确保:

  1. 已安装 TDengine :需要安装 TDengine 客户端或服务端
  2. 开发环境:支持 C/C++ 开发的编译器(GCC、Clang、MSVC 等)
  3. 操作系统:Linux、Windows 或 macOS

第一步:安装和配置

1.1 安装 TDengine 客户端

根据您的操作系统,安装相应的 TDengine 客户端:

Linux (Ubuntu/Debian)

bash 复制代码
wget https://www.taosdata.com/assets-download/3.0/TDengine-client-3.x.x.x-Linux-x64.tar.gz
tar -xzvf TDengine-client-3.x.x.x-Linux-x64.tar.gz
cd TDengine-client-3.x.x.x && sudo ./install_client.sh

Windows

  • 下载并运行 TDengine 客户端安装程序
  • 默认安装路径:C:\TDengine

macOS

  • 下载并运行 TDengine 客户端安装程序
  • 默认安装路径:/usr/local/Cellar/tdengine (Cellar 名称随不同系统版本会变化)

1.2 验证安装

安装完成后,验证头文件和动态库的位置:

操作系统 头文件路径 动态库路径
Linux /usr/local/taos/include /usr/local/taos/driver/libtaos.so
Windows C:\TDengine\include C:\TDengine\driver\taos.dll
macOS /usr/local/include /usr/local/lib/libtaos.dylib

第二步:选择连接方式

TDengine 支持两种连接方式:

2.1 WebSocket 连接(推荐)

优点:

  • 客户端和服务端版本无需完全匹配
  • 性能接近原生连接
  • 支持云服务和远程连接

使用场景:适合大多数应用场景,特别是云环境和跨版本场景

2.2 原生连接

优点:

  • 功能最完整
  • 直接通信,延迟略低

限制:

  • 客户端和服务端版本需要严格匹配(强烈建议版本一致)

使用场景:局域网环境且版本可控时

第三步:编写第一个程序

3.1 创建项目目录

bash 复制代码
mkdir tdengine_demo
cd tdengine_demo

3.2 编写代码(WebSocket 连接)

创建文件 demo.c:

c 复制代码
#include <stdio.h>
#include <stdlib.h>
#include "taos.h"

int main() {
    // 1. 初始化环境(可选,taos_connect 会自动调用)
    taos_init();
    
    // 2. 设置连接方式为 WebSocket(必须在程序开始时调用一次)
    taos_options(TSDB_OPTION_DRIVER, "websocket");
    
    // 3. 连接到 TDengine
    TAOS *taos = taos_connect(
        "localhost",    // 主机地址
        "root",         // 用户名
        "taosdata",     // 密码
        NULL,           // 数据库名(可选)
        0               // 端口,0 表示使用默认端口(WebSocket 为 6041)
    );
    
    // 4. 检查连接是否成功
    if (taos == NULL) {
        printf("连接失败:%s\n", taos_errstr(NULL));
        return -1;
    }
    
    printf("连接成功!\n");
    printf("客户端版本:%s\n", taos_get_client_info());
    printf("服务端版本:%s\n", taos_get_server_info(taos));
    
    // 5. 创建数据库
    TAOS_RES *res = taos_query(taos, "CREATE DATABASE IF NOT EXISTS test");
    if (taos_errno(res) != 0) {
        printf("创建数据库失败:%s\n", taos_errstr(res));
        taos_free_result(res);
        taos_close(taos);
        return -1;
    }
    printf("数据库创建成功!\n");
    taos_free_result(res);
    
    // 6. 使用数据库
    res = taos_query(taos, "USE test");
    if (taos_errno(res) != 0) {
        printf("使用数据库失败:%s\n", taos_errstr(res));
        taos_free_result(res);
        taos_close(taos);
        return -1;
    }
    taos_free_result(res);
    
    // 7. 创建超级表
    res = taos_query(taos, 
        "CREATE STABLE IF NOT EXISTS meters "
        "(ts TIMESTAMP, current FLOAT, voltage INT, phase FLOAT) "
        "TAGS (location BINARY(64), groupId INT)"
    );
    if (taos_errno(res) != 0) {
        printf("创建超级表失败:%s\n", taos_errstr(res));
        taos_free_result(res);
        taos_close(taos);
        return -1;
    }
    printf("超级表创建成功!\n");
    taos_free_result(res);
    
    // 8. 插入数据
    res = taos_query(taos,
        "INSERT INTO d1001 USING meters TAGS('Beijing.Chaoyang', 1) "
        "VALUES (NOW, 10.2, 219, 0.32)"
    );
    if (taos_errno(res) != 0) {
        printf("插入数据失败:%s\n", taos_errstr(res));
    } else {
        printf("成功插入 %d 行数据\n", taos_affected_rows(res));
    }
    taos_free_result(res);
    
    // 9. 查询数据
    res = taos_query(taos, "SELECT * FROM meters");
    if (taos_errno(res) != 0) {
        printf("查询失败:%s\n", taos_errstr(res));
        taos_free_result(res);
        taos_close(taos);
        return -1;
    }
    
    // 10. 获取字段信息
    int num_fields = taos_num_fields(res);
    TAOS_FIELD *fields = taos_fetch_fields(res);
    
    // 打印表头
    for (int i = 0; i < num_fields; i++) {
        printf("%s\t", fields[i].name);
    }
    printf("\n");
    
    // 11. 逐行获取查询结果
    TAOS_ROW row;
    while ((row = taos_fetch_row(res))) {
        int *lengths = taos_fetch_lengths(res);
        for (int i = 0; i < num_fields; i++) {
            if (row[i] == NULL) {
                printf("NULL\t");
            } else {
                // 根据字段类型打印数据
                switch (fields[i].type) {
                    case TSDB_DATA_TYPE_TIMESTAMP:
                        printf("%lld\t", *(int64_t *)row[i]);
                        break;
                    case TSDB_DATA_TYPE_INT:
                        printf("%d\t", *(int *)row[i]);
                        break;
                    case TSDB_DATA_TYPE_FLOAT:
                        printf("%.2f\t", *(float *)row[i]);
                        break;
                    case TSDB_DATA_TYPE_BINARY:
                    case TSDB_DATA_TYPE_NCHAR:
                        printf("%.*s\t", lengths[i], (char *)row[i]);
                        break;
                    default:
                        break;
                }
            }
        }
        printf("\n");
    }
    
    // 12. 释放结果集
    taos_free_result(res);
    
    // 13. 关闭连接
    taos_close(taos);
    
    // 14. 清理环境
    taos_cleanup();
    
    printf("程序执行完毕!\n");
    return 0;
}

3.3 编写代码(原生连接)

如果您要使用原生连接,只需将 WebSocket 版本的第 2 步注释掉即可:

c 复制代码
// 使用原生连接,不需要设置驱动类型
// taos_options(TSDB_OPTION_DRIVER, "websocket");  // 注释或删除此行

// 连接到 TDengine(使用默认原生端口 6030)
TAOS *taos = taos_connect(
    "localhost",
    "root",
    "taosdata",
    NULL,
    0  // 0 表示使用默认端口(原生连接为 6030)
);

3.4 编译程序

Linux/macOS

bash 复制代码
gcc demo.c -o demo -ltaos -I/usr/local/taos/include -L/usr/local/taos/driver

Windows (使用 MSVC)

cmd 复制代码
cl demo.c /I C:\TDengine\include /link C:\TDengine\driver\taos.lib

Windows (使用 MinGW)

bash 复制代码
gcc demo.c -o demo.exe -I C:/TDengine/include -L C:/TDengine/driver -ltaos

3.5 运行程序

Linux/macOS

bash 复制代码
# 如果提示找不到动态库,需要设置 LD_LIBRARY_PATH
export LD_LIBRARY_PATH=/usr/local/taos/driver:$LD_LIBRARY_PATH
./demo

Windows

cmd 复制代码
demo.exe

预期输出

复制代码
连接成功!
客户端版本:3.3.x.x
服务端版本:3.3.x.x
数据库创建成功!
超级表创建成功!
成功插入 1 行数据
ts              current voltage phase   location        groupId
1704528000000   10.20   219     0.32    Beijing.Chaoyang        1
程序执行完毕!

第四步:核心概念理解

4.1 连接对象 (TAOS)

  • TAOS 是数据库连接句柄,所有操作都基于此句柄
  • 通过 taos_connect() 创建,使用完毕后必须调用 taos_close() 释放

4.2 结果集 (TAOS_RES)

  • TAOS_RES 是执行 SQL 后返回的结果集
  • 无论是查询、插入还是 DDL 操作,都会返回结果集
  • 使用完毕后必须调用 taos_free_result() 释放

4.3 错误处理

TDengine 使用错误码机制:

c 复制代码
TAOS_RES *res = taos_query(taos, sql);

// 检查是否出错
if (taos_errno(res) != 0) {
    printf("错误码:%d\n", taos_errno(res));
    printf("错误信息:%s\n", taos_errstr(res));
    taos_free_result(res);
    return -1;
}

重要 :不能通过 taos_query() 返回 NULL 来判断失败,必须使用 taos_errno() 检查错误码。

4.4 数据类型映射

TDengine 类型 C 类型 说明
TIMESTAMP int64_t Unix 时间戳(毫秒/微秒/纳秒)
INT int32_t 32位整数
BIGINT int64_t 64位整数
FLOAT float 单精度浮点数
DOUBLE double 双精度浮点数
BINARY char\[\] 二进制字符串
NCHAR char\[\] (UTF-8) Unicode 字符串
BOOL int8_t 布尔值(0 或 1)
TINYINT int8_t 8位整数
SMALLINT int16_t 16位整数

第五步:常见操作示例

5.1 批量插入数据

c 复制代码
// 方式 1:多行 SQL 插入
const char *sql = 
    "INSERT INTO "
    "d1001 USING meters TAGS('Beijing.Chaoyang', 1) VALUES (NOW, 10.2, 219, 0.32) "
    "d1002 USING meters TAGS('Beijing.Haidian', 2) VALUES (NOW, 11.5, 220, 0.28) "
    "d1003 USING meters TAGS('Shanghai.Pudong', 3) VALUES (NOW, 12.1, 221, 0.35)";

TAOS_RES *res = taos_query(taos, sql);
if (taos_errno(res) == 0) {
    printf("成功插入 %d 行数据\n", taos_affected_rows(res));
}
taos_free_result(res);

5.2 聚合查询

c 复制代码
const char *sql = 
    "SELECT location, AVG(current), MAX(voltage), MIN(phase) "
    "FROM meters "
    "WHERE ts >= NOW - 1h "
    "GROUP BY location";

TAOS_RES *res = taos_query(taos, sql);
if (taos_errno(res) != 0) {
    printf("查询失败:%s\n", taos_errstr(res));
    taos_free_result(res);
    return -1;
}

TAOS_ROW row;
while ((row = taos_fetch_row(res))) {
    printf("位置:%s, 平均电流:%.2f, 最大电压:%d, 最小相位:%.2f\n",
           (char *)row[0],
           *(double *)row[1],
           *(int *)row[2],
           *(double *)row[3]);
}

taos_free_result(res);

5.3 数据订阅(流式处理)

c 复制代码
#include "taos.h"
#include <stdio.h>

int main() {
    taos_options(TSDB_OPTION_DRIVER, "websocket");
    TAOS *taos = taos_connect("localhost", "root", "taosdata", "test", 0);
    
    // 创建 topic
    TAOS_RES *res = taos_query(taos, 
        "CREATE TOPIC IF NOT EXISTS topic_meters AS SELECT * FROM meters");
    taos_free_result(res);
    
    // 创建消费者
    tmq_conf_t *conf = tmq_conf_new();
    tmq_conf_set(conf, "group.id", "group1");
    tmq_conf_set(conf, "td.connect.user", "root");
    tmq_conf_set(conf, "td.connect.pass", "taosdata");
    tmq_conf_set(conf, "auto.offset.reset", "earliest");
    
    tmq_t *tmq = tmq_consumer_new(conf, NULL, 0);
    tmq_conf_destroy(conf);
    
    // 订阅 topic
    tmq_list_t *topic_list = tmq_list_new();
    tmq_list_append(topic_list, "topic_meters");
    tmq_subscribe(tmq, topic_list);
    tmq_list_destroy(topic_list);
    
    // 消费数据
    while (1) {
        TAOS_RES *message = tmq_consumer_poll(tmq, 1000);
        if (message) {
            TAOS_ROW row;
            while ((row = taos_fetch_row(message))) {
                printf("收到新数据\n");
                // 处理数据...
            }
            taos_free_result(message);
        }
    }
    
    // 取消订阅并关闭
    tmq_unsubscribe(tmq);
    tmq_consumer_close(tmq);
    taos_close(taos);
    return 0;
}

第六步:最佳实践

6.1 连接管理

c 复制代码
// 使用连接池(简单示例)
#define MAX_CONNECTIONS 10
TAOS *pool[MAX_CONNECTIONS];

void init_pool() {
    for (int i = 0; i < MAX_CONNECTIONS; i++) {
        pool[i] = taos_connect("localhost", "root", "taosdata", "test", 0);
    }
}

void destroy_pool() {
    for (int i = 0; i < MAX_CONNECTIONS; i++) {
        if (pool[i]) taos_close(pool[i]);
    }
}

6.2 错误处理模式

c 复制代码
int execute_sql(TAOS *taos, const char *sql) {
    TAOS_RES *res = taos_query(taos, sql);
    int code = taos_errno(res);
    
    if (code != 0) {
        fprintf(stderr, "SQL 执行失败:%s\nSQL:%s\n", 
                taos_errstr(res), sql);
        taos_free_result(res);
        return -1;
    }
    
    int affected = taos_affected_rows(res);
    taos_free_result(res);
    return affected;
}

6.3 资源管理

必须释放的资源:

  1. 结果集:taos_free_result(res)
  2. 连接:taos_close(taos)
  3. 语句:taos_stmt_close(stmt)

推荐使用 RAII 模式(C++):

cpp 复制代码
class TaosConnection {
private:
    TAOS *taos;
    
public:
    TaosConnection(const char *host, const char *user, 
                   const char *pass, const char *db) {
        taos = taos_connect(host, user, pass, db, 0);
        if (!taos) throw std::runtime_error(taos_errstr(NULL));
    }
    
    ~TaosConnection() {
        if (taos) taos_close(taos);
    }
    
    TAOS* get() { return taos; }
};

6.4 性能优化

  1. 批量操作:一次插入多行数据,而不是逐行插入
  2. 使用参数绑定:避免 SQL 拼接,提高性能和安全性
  3. 合理设置缓冲区 :使用 taos_fetch_block() 批量获取数据
  4. 连接复用:避免频繁创建和销毁连接
c 复制代码
// 使用 taos_fetch_block 批量获取
TAOS_RES *res = taos_query(taos, "SELECT * FROM meters");
TAOS_ROW *rows;
int num_rows;

while ((num_rows = taos_fetch_block(res, &rows)) > 0) {
    for (int i = 0; i < num_rows; i++) {
        // 处理 rows[i]
    }
}

taos_free_result(res);

第七步:调试和故障排查

7.1 启用日志

c 复制代码
// 设置日志级别
taos_options(TSDB_OPTION_DEBUGFLAG, "135");  // 135 = DEBUG 级别

7.2 常见问题

问题 1:找不到动态库

bash 复制代码
# Linux/macOS
export LD_LIBRARY_PATH=/usr/local/taos/driver:$LD_LIBRARY_PATH

# Windows:将 C:\TDengine\driver 添加到系统 PATH

问题 2:连接失败

  • 检查服务是否启动:systemctl status taosd(Linux)
  • 检查端口是否开放:WebSocket 6041,原生连接 6030
  • 检查防火墙设置

问题 3:版本不匹配(原生连接)

  • 确保客户端和服务端版本一致
  • 或改用 WebSocket 连接方式

问题 4:字符编码问题

c 复制代码
// 设置字符集为 UTF-8
taos_options(TSDB_OPTION_CHARSET, "UTF-8");

7.3 性能分析

c 复制代码
#include <time.h>

clock_t start = clock();
TAOS_RES *res = taos_query(taos, sql);
clock_t end = clock();

double elapsed = (double)(end - start) / CLOCKS_PER_SEC;
printf("SQL 执行耗时:%.3f 秒\n", elapsed);

taos_free_result(res);

第八步:进阶主题

8.1 使用 CMake 构建项目

创建 CMakeLists.txt:

cmake 复制代码
cmake_minimum_required(VERSION 3.10)
project(TDengineDemo C)

set(CMAKE_C_STANDARD 11)

# 查找 TDengine 库
find_library(TAOS_LIBRARY taos
    PATHS /usr/local/taos/driver /usr/local/lib
)

if(NOT TAOS_LIBRARY)
    message(FATAL_ERROR "TDengine library not found")
endif()

# 设置头文件路径
include_directories(/usr/local/taos/include)

# 添加可执行文件
add_executable(demo demo.c)

# 链接 TDengine 库
target_link_libraries(demo ${TAOS_LIBRARY})

构建:

bash 复制代码
mkdir build && cd build
cmake ..
make
./demo

8.2 多线程使用

c 复制代码
#include <pthread.h>

void *worker_thread(void *arg) {
    // 每个线程使用独立的连接
    TAOS *taos = taos_connect("localhost", "root", "taosdata", "test", 0);
    
    // 执行操作...
    
    taos_close(taos);
    return NULL;
}

int main() {
    taos_init();
    taos_options(TSDB_OPTION_DRIVER, "websocket");
    
    pthread_t threads[10];
    for (int i = 0; i < 10; i++) {
        pthread_create(&threads[i], NULL, worker_thread, NULL);
    }
    
    for (int i = 0; i < 10; i++) {
        pthread_join(threads[i], NULL);
    }
    
    taos_cleanup();
    return 0;
}

注意 :TAOS 连接对象不是线程安全的,每个线程应使用独立的连接。

8.3 异步查询

c 复制代码
void async_callback(void *param, TAOS_RES *res, int code) {
    if (code == 0) {
        printf("异步查询成功\n");
        TAOS_ROW row;
        while ((row = taos_fetch_row(res))) {
            // 处理数据
        }
    } else {
        printf("异步查询失败:%s\n", taos_errstr(res));
    }
    taos_free_result(res);
}

int main() {
    taos_options(TSDB_OPTION_DRIVER, "websocket");
    TAOS *taos = taos_connect("localhost", "root", "taosdata", "test", 0);
    
    // 发起异步查询
    taos_query_a(taos, "SELECT * FROM meters", async_callback, NULL);
    
    // 主线程继续执行其他任务
    sleep(1);  // 等待异步操作完成
    
    taos_close(taos);
    return 0;
}

第九步:完整示例项目

创建一个完整的监控数据采集程序:

项目结构:

复制代码
tdengine_monitor/
├── CMakeLists.txt
├── include/
│   └── monitor.h
├── src/
│   ├── main.c
│   ├── database.c
│   └── collector.c
└── README.md

monitor.h:

c 复制代码
#ifndef MONITOR_H
#define MONITOR_H

#include "taos.h"

// 初始化数据库
int init_database(TAOS *taos);

// 采集数据
int collect_metrics(TAOS *taos);

// 查询统计
int query_statistics(TAOS *taos);

#endif

database.c:

c 复制代码
#include "monitor.h"
#include <stdio.h>

int init_database(TAOS *taos) {
    const char *sqls[] = {
        "CREATE DATABASE IF NOT EXISTS monitor",
        "USE monitor",
        "CREATE STABLE IF NOT EXISTS metrics "
        "(ts TIMESTAMP, cpu_usage FLOAT, mem_usage FLOAT, disk_io INT) "
        "TAGS (hostname BINARY(64), region BINARY(32))"
    };
    
    for (int i = 0; i < 3; i++) {
        TAOS_RES *res = taos_query(taos, sqls[i]);
        if (taos_errno(res) != 0) {
            fprintf(stderr, "执行失败:%s\n", taos_errstr(res));
            taos_free_result(res);
            return -1;
        }
        taos_free_result(res);
    }
    
    printf("数据库初始化成功\n");
    return 0;
}

collector.c:

c 复制代码
#include "monitor.h"
#include <stdio.h>
#include <stdlib.h>
#include <time.h>

int collect_metrics(TAOS *taos) {
    // 模拟采集数据
    float cpu = (float)(rand() % 100);
    float mem = (float)(rand() % 100);
    int disk_io = rand() % 10000;
    
    char sql[1024];
    snprintf(sql, sizeof(sql),
        "INSERT INTO server01 USING metrics TAGS('server01', 'beijing') "
        "VALUES (NOW, %.2f, %.2f, %d)",
        cpu, mem, disk_io);
    
    TAOS_RES *res = taos_query(taos, sql);
    int code = taos_errno(res);
    taos_free_result(res);
    
    if (code == 0) {
        printf("数据采集成功:CPU=%.2f%%, MEM=%.2f%%, DiskIO=%d\n", 
               cpu, mem, disk_io);
        return 0;
    }
    
    return -1;
}

int query_statistics(TAOS *taos) {
    const char *sql = 
        "SELECT hostname, AVG(cpu_usage), AVG(mem_usage), MAX(disk_io) "
        "FROM metrics "
        "WHERE ts >= NOW - 1h "
        "GROUP BY hostname";
    
    TAOS_RES *res = taos_query(taos, sql);
    if (taos_errno(res) != 0) {
        fprintf(stderr, "查询失败:%s\n", taos_errstr(res));
        taos_free_result(res);
        return -1;
    }
    
    printf("\n=== 最近 1 小时统计 ===\n");
    TAOS_ROW row;
    while ((row = taos_fetch_row(res))) {
        printf("主机:%s, 平均CPU:%.2f%%, 平均内存:%.2f%%, 最大磁盘IO:%d\n",
               (char *)row[0],
               *(double *)row[1],
               *(double *)row[2],
               *(int *)row[3]);
    }
    
    taos_free_result(res);
    return 0;
}

main.c:

c 复制代码
#include "monitor.h"
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>

int main(int argc, char *argv[]) {
    // 初始化
    taos_init();
    taos_options(TSDB_OPTION_DRIVER, "websocket");
    
    // 连接数据库
    TAOS *taos = taos_connect("localhost", "root", "taosdata", NULL, 0);
    if (taos == NULL) {
        fprintf(stderr, "连接失败:%s\n", taos_errstr(NULL));
        return -1;
    }
    
    printf("已连接到 TDengine\n");
    
    // 初始化数据库
    if (init_database(taos) != 0) {
        taos_close(taos);
        return -1;
    }
    
    // 持续采集数据(演示 10 次)
    for (int i = 0; i < 10; i++) {
        collect_metrics(taos);
        sleep(1);
    }
    
    // 查询统计
    query_statistics(taos);
    
    // 清理
    taos_close(taos);
    taos_cleanup();
    
    printf("程序结束\n");
    return 0;
}

编译运行:

bash 复制代码
mkdir build && cd build
cmake ..
make
./tdengine_monitor

总结

本指南涵盖了 TDengine C/C++ 连接器的核心概念和常用操作:

  1. 安装配置:安装客户端并验证环境
  2. 连接方式:WebSocket(推荐)和原生连接
  3. 基础操作:连接、查询、插入、关闭
  4. 高级特性:参数绑定、批量操作、数据订阅
  5. 最佳实践:错误处理、资源管理、性能优化
  6. 实战项目:完整的监控数据采集示例

获取帮助


关于 TDengine

TDengine 专为物联网IoT平台、工业大数据平台设计。其中,TDengine TSDB 是一款高性能、分布式的时序数据库(Time Series Database),同时它还带有内建的缓存、流式计算、数据订阅等系统功能;TDengine IDMP 是一款AI原生工业数据管理平台,它通过树状层次结构建立数据目录,对数据进行标准化、情景化,并通过 AI 提供实时分析、可视化、事件管理与报警等功能。

相关推荐
不是万能的豆学长2 小时前
filetidy 文件整理助手:一键归类 + 规范重命名(Python 零依赖单文件工具)
大数据·开发语言·python·技术美术
catoop8 小时前
API Key 设计与安全生成方案:结构拆解、数据库设计与 Java 实现
java·数据库·安全
Web极客码8 小时前
我用 Claude 分析 Redis 哨兵日志,实现跨机房数据不一致自动对齐
数据库·redis·php
库库的数据库笔记8 小时前
国产信创数据库的MySQL兼容性深度对比解析
大数据·数据库·mysql·oceanbase·政务
microrain8 小时前
SagooIoT 的缓存换后端只改一行配置,文件后端连 Redis 都不需要
物联网·缓存·golang·sagooiot
姚远Oracle ACE9 小时前
为什么无法连接到 PostgreSQL?
数据库·postgresql
ss2739 小时前
AI时代首先数据库-PostgreSQL实战笔记 | 22 PostgreSQL实例与集群
数据库·笔记·postgresql
ss2739 小时前
AI时代首先数据库-PostgreSQL实战笔记 | 21 PostgreSQL进程与内存架构介绍
数据库·笔记·postgresql
Elastic 中国社区官方博客9 小时前
我们如何通过 70 多个拉取请求,将 OpenTelemetry Java agent 迁移到 invokedynamic
java·大数据·开发语言·elasticsearch·搜索引擎·全文检索·es