提交 aee95ae1 编写于 作者: S Shuduo Sang

Merge branch 'develop' into hotfix/sangshuduo/2.0doc-emq-insert

......@@ -190,7 +190,7 @@ matrix:
script:
- cmake .. > /dev/null
- make > /dev/null
- make > /dev/null
- os: linux
arch: arm64
......
CMAKE_MINIMUM_REQUIRED(VERSION 2.8)
PROJECT(TDengine)
IF (CMAKE_VERSION VERSION_LESS 3.0)
PROJECT(TDengine CXX)
SET(PROJECT_VERSION_MAJOR "${LIB_MAJOR_VERSION}")
SET(PROJECT_VERSION_MINOR "${LIB_MINOR_VERSION}")
SET(PROJECT_VERSION_PATCH"${LIB_PATCH_VERSION}")
SET(PROJECT_VERSION "${LIB_VERSION_STRING}")
ELSE ()
CMAKE_POLICY(SET CMP0048 NEW)
PROJECT(TDengine VERSION "${LIB_VERSION_STRING}" LANGUAGES CXX)
ENDIF ()
SET(TD_ACCOUNT FALSE)
SET(TD_ADMIN FALSE)
......
......@@ -53,14 +53,18 @@ IF (TD_LINUX_64)
ADD_DEFINITIONS(-D_M_X64)
ADD_DEFINITIONS(-D_TD_LINUX_64)
IF (NOT TD_ARM)
IF (${CMAKE_CXX_COMPILER_ID} MATCHES "Clang")
SET(COMMON_FLAGS "-std=gnu99 -Wall -Werror -Wno-missing-braces -fPIC -g3 -gdwarf-2 -msse4.2 -D_FILE_OFFSET_BITS=64 -D_LARGE_FILE")
ELSE ()
SET(COMMON_FLAGS "-std=gnu99 -Wall -Werror -fPIC -malign-double -g3 -gdwarf-2 -malign-stringops -msse4.2 -D_FILE_OFFSET_BITS=64 -D_LARGE_FILE")
ENDIF ()
#IF ((${CMAKE_CXX_COMPILER_ID} MATCHES "Clang") OR (${CMAKE_CXX_COMPILER_ID} MATCHES "clang"))
# SET(COMMON_FLAGS "-std=gnu99 -Wall -Werror -Wno-missing-braces -fPIC -g3 -gdwarf-2 -msse4.2 -D_FILE_OFFSET_BITS=64 -D_LARGE_FILE")
#ELSE ()
# SET(COMMON_FLAGS "-std=gnu99 -Wall -Werror -fPIC -malign-double -g3 -gdwarf-2 -malign-stringops -msse4.2 -D_FILE_OFFSET_BITS=64 -D_LARGE_FILE")
#ENDIF ()
SET(COMMON_FLAGS "-std=gnu99 -Wall -Werror -fPIC -g3 -gdwarf-2 -msse4.2 -D_FILE_OFFSET_BITS=64 -D_LARGE_FILE")
ELSE ()
SET(COMMON_FLAGS "-std=gnu99 -Wall -Werror -fPIC -g -fsigned-char -fpack-struct=8 -D_FILE_OFFSET_BITS=64 -D_LARGE_FILE")
ENDIF ()
MESSAGE(STATUS "CMAKE_CXX_COMPILER_ID: " ${CMAKE_CXX_COMPILER_ID})
MESSAGE(STATUS "COMMON_FLAGS: " ${COMMON_FLAGS})
FIND_PATH(ICONV_INCLUDE_EXIST iconv.h /usr/include/ /usr/local/include/)
IF (ICONV_INCLUDE_EXIST)
ADD_DEFINITIONS(-DUSE_LIBICONV)
......
......@@ -52,14 +52,16 @@ ELSE ()
MESSAGE(STATUS "input cpuType unknown " ${CPUTYPE})
ENDIF ()
#
# Get OS information and store in variable TD_OS_INFO.
#
execute_process(COMMAND chmod 777 ${TD_COMMUNITY_DIR}/packaging/tools/get_os.sh)
execute_process(COMMAND ${TD_COMMUNITY_DIR}/packaging/tools/get_os.sh "" OUTPUT_VARIABLE TD_OS_INFO)
MESSAGE(STATUS "The current os is " ${TD_OS_INFO})
IF (${CMAKE_SYSTEM_NAME} MATCHES "Linux")
#
# Get OS information and store in variable TD_OS_INFO.
#
execute_process(COMMAND chmod 777 ${TD_COMMUNITY_DIR}/packaging/tools/get_os.sh)
execute_process(COMMAND ${TD_COMMUNITY_DIR}/packaging/tools/get_os.sh "" OUTPUT_VARIABLE TD_OS_INFO)
MESSAGE(STATUS "The current os is " ${TD_OS_INFO})
SET(TD_LINUX TRUE)
IF (${CMAKE_SIZEOF_VOID_P} MATCHES 8)
SET(TD_LINUX_64 TRUE)
......
......@@ -917,15 +917,16 @@ TDengine 同时也提供了node.js 的连接器。用户可以通过[npm](https:
首先,通过[npm](https://www.npmjs.com/)安装node.js 连接器.
```cmd
npm install td-connector
npm install td2.0-connector
```
我们建议用户使用npm 安装node.js连接器。如果您没有安装npm, 可以将*src/connector/nodejs/*拷贝到您的nodejs 项目目录下
我们使用[node-gyp](https://github.com/nodejs/node-gyp)和TDengine服务端进行交互。安装node.js 连接器之前,还需安装以下软件:
### Unix
### Linux
- `python` (建议`v2.7` , `v3.x.x` 目前还不支持)
- `node` 必须采用v8.x版本,之后的版本存在兼容性的问题。
- `make`
- c语言编译器比如[GCC](https://gcc.gnu.org)
......@@ -980,10 +981,10 @@ npm install td-connector
#### 连接
使用node.js连接器时,必须先<em>require</em> ```td-connector```,然后使用 ```taos.connect``` 函数。```taos.connect``` 函数必须提供的参数是```host```,其它参数在没有提供的情况下会使用如下的默认值。最后需要初始化```cursor``` 来和TDengine服务端通信
使用node.js连接器时,必须先<em>require</em> ```td2.0-connector```,然后使用 ```taos.connect``` 函数。```taos.connect``` 函数必须提供的参数是```host```,其它参数在没有提供的情况下会使用如下的默认值。最后需要初始化```cursor``` 来和TDengine服务端通信
```javascript
const taos = require('td-connector');
const taos = require('td2.0-connector');
var conn = taos.connect({host:"127.0.0.1", user:"root", password:"taosdata", config:"/etc/taos",port:0})
var cursor = conn.cursor(); // Initializing a new cursor
```
......
#TDengine文档
TDengine是一个高效的存储、查询、分析时序大数据的平台,专为物联网、车联网、工业互联网、运维监测等优化而设计。您可以像使用关系型数据库MySQL一样来使用它,但建议您在使用前仔细阅读一遍下面的文档,特别是[数据模型](data-model-and-architecture)与数据建模一节。除本文档之外,欢迎[下载产品白皮书](https://www.taosdata.com/downloads/TDengine%20White%20Paper.pdf)
##TDengine 介绍
- TDengine 简介及特色
- TDengine 适用场景
- TDengine 性能指标介绍和验证方法
##立即开始
- 快捷安装:可通过源码、安装包或docker安装,三秒钟搞定
- 轻松启动:使用systemctl 启停TDengine
- 命令行程序TAOS:访问TDengine的简便方式
- [极速体验](https://www.taosdata.com/cn/getting-started/#TDengine-极速体验):运行示例程序,快速体验高效的数据插入、查询
##数据模型和整体架构
- 数据模型:关系型数据库模型,但要求每个采集点单独建表
- 集群与基本逻辑单元:吸取NoSQL优点,支持水平扩展,支持高可靠
- 存储模型与数据分区:标签数据与时序数据完全分离,按vnode和时间两个维度对数据切分
- 数据写入与复制流程:先写入WAL、之后写入缓存,再给应用确认,支持多副本
- 缓存与持久化:最新数据缓存在内存中,但落盘时采用列式存储、超高压缩比
- 高效查询:支持各种函数、时间轴聚合、插值、多表聚合
##数据建模
- 创建库:为具有相似数据特征的数据采集点创建一个库
- 创建超级表:为同一类型的数据采集点创建一个超级表
- 创建表:使用超级表做模板,为每一个具体的数据采集点单独建表
##高效写入数据
- SQL写入:使用SQL insert命令向一张或多张表写入单条或多条记录
- Telegraf 写入:配置Telegraf, 不用任何代码,将采集数据直接写入
- Prometheus写入:配置Prometheus, 不用任何代码,将数据直接写入
- EMQ X Broker:配置EMQ X,不用任何代码,就可将MQTT数据直接写入
##高效查询数据
- 主要查询功能:支持各种标准函数,设置过滤条件,时间段查询
- 多表聚合查询:使用超级表,设置标签过滤条件,进行高效聚合查询
- 降采样查询:按时间段分段聚合,支持插值
##高级功能
- 连续查询(Continuous Query):基于滑动窗口,定时自动的对数据流进行查询计算
- 数据订阅(Publisher/Subscriber):象典型的消息队列,应用可订阅接收到的最新数据
- [缓存 (Cache)](https://www.taosdata.com/cn/documentation/advanced-features/#缓存-(Cache)):每个设备最新的数据都会缓存在内存中,可快速获取
- [报警监测(Alarm monitoring)](https://www.taosdata.com/blog/2020/04/14/1438.html/):根据配置规则,自动监测超限行为数据,并主动推送
##连接器
- C/C++ Connector:通过libtaos客户端的库,连接TDengine服务器的主要方法
- Java Connector(JDBC):通过标准的JDBC API,给Java应用提供到TDengine的连接
- Python Connector:给Python应用提供一个连接TDengine服务器的驱动
- RESTful Connector:提供一最简单的连接TDengine服务器的方式
- Go Connector:给Go应用提供一个连接TDengine服务器的驱动
- Node.js Connector:给node应用提供一个链接TDengine服务器的驱动
##与其他工具的连接
- Grafana:获取并可视化保存在TDengine的数据
- Matlab:通过配置Matlab的JDBC数据源访问保存在TDengine的数据
- R:通过配置R的JDBC数据源访问保存在TDengine的数据
## TDengine集群的安装、管理
- 安装:与单节点的安装一样,但要设好配置文件里的参数first
- 节点管理:增加、删除、查看集群的节点
- mnode的管理:系统自动创建、无需任何人工干预
- 负载均衡:一旦节点个数或负载有变化,自动进行
- 节点离线处理:节点离线超过一定时长,将从集群中剔除
- Arbitrator:对于偶数个副本的情形,使用它可以防止split brain。
##TDengine的运营和维护
- 容量规划:根据场景,估算硬件资源
- 容错和灾备:设置正确的WAL和数据副本数
- 系统配置:端口,缓存大小,文件块大小和其他系统配置
- 用户管理:添加、删除TDengine用户,修改用户密码
- 数据导入:可按脚本文件导入,也可按数据文件导入
- 数据导出:从shell按表导出,也可用taosdump工具做各种导出
- 系统监控:检查系统现有的连接、查询、流式计算,日志和事件等
- 文件目录结构:TDengine数据文件、配置文件等所在目录 Hui Li
##TAOS SQL
- 支持的数据类型:支持时间戳、整型、浮点型、布尔型、字符型等多种数据类型
- 数据库管理:添加、删除、查看数据库
- 表管理:添加、删除、查看、修改表
- 超级表管理:添加、删除、查看、修改超级表
- 标签管理:增加、删除、修改标签
- 数据写入:支持单表单条、多条、多表多条写入,支持历史数据写入
- 数据查询:支持时间段、值过滤、排序、查询结果手动分页等
- SQL函数:支持各种聚合函数、选择函数、计算函数,如avg, min, diff等
- 时间维度聚合:将表中数据按照时间段进行切割后聚合,降维处理
##TDengine的技术设计
- 系统模块:taosd的功能和模块划分
- 技术博客:更多的技术分析和架构设计文章
## 常用工具
- [TDengine样例数据导入工具](https://www.taosdata.com/cn/documentation/blog/2020/01/18/如何快速验证性能和主要功能?tdengine样例数据导入工/)
- [TDengine性能对比测试工具](https://www.taosdata.com/cn/documentation/blog/2020/01/13/用influxdb开源的性能测试工具对比influxdb和tdengine/)
##TDengine与其他数据库的对比测试
- [用InfluxDB开源的性能测试工具对比InfluxDB和TDengine](https://www.taosdata.com/cn/documentation/blog/2020/01/13/用influxdb开源的性能测试工具对比influxdb和tdengine/)
- [TDengine与OpenTSDB对比测试](https://www.taosdata.com/cn/documentation/blog/2019/08/21/tdengine与opentsdb对比测试/)
- [TDengine与Cassandra对比测试](https://www.taosdata.com/cn/documentation/blog/2019/08/14/tdengine与cassandra对比测试/)
- [TDengine与InfluxDB对比测试](https://www.taosdata.com/cn/documentation/blog/2019/07/19/tdengine与influxdb对比测试/)
- [TDengine与InfluxDB、OpenTSDB、Cassandra、MySQL、ClickHouse等数据库的对比测试报告](https://www.taosdata.com/downloads/TDengine_Testing_Report_cn.pdf)
##物联网大数据
- [物联网、工业互联网大数据的特点](https://www.taosdata.com/blog/2019/07/09/物联网、工业互联网大数据的特点/)
- [物联网大数据平台应具备的功能和特点](https://www.taosdata.com/blog/2019/07/29/物联网大数据平台应具备的功能和特点/)
- [通用大数据架构为什么不适合处理物联网数据?](https://www.taosdata.com/blog/2019/07/09/通用互联网大数据处理架构为什么不适合处理物联/)
- [物联网、车联网、工业互联网大数据平台,为什么推荐使用TDengine?](https://www.taosdata.com/blog/2019/07/09/物联网、车联网、工业互联网大数据平台,为什么/)
##培训和FAQ
- <a href='https://www.taosdata.com/en/faq'>FAQ</a>:常见问题与答案
- <a href='https://www.taosdata.com/en/blog/?categories=4'>应用案列</a>:一些使用实例来解释如何使用TDengine
\ No newline at end of file
# TDengine文档
TDengine是一个高效的存储、查询、分析时序大数据的平台,专为物联网、车联网、工业互联网、运维监测等优化而设计。您可以像使用关系型数据库MySQL一样来使用它,但建议您在使用前仔细阅读一遍下面的文档,特别是[数据模型](https://www.taosdata.com/cn/documentation20/data-model-and-architecture)[数据建模](https://www.taosdata.com/cn/documentation20/model)一节。除本文档之外,欢迎[下载产品白皮书](https://www.taosdata.com/downloads/TDengine White Paper.pdf)。如需查阅TDengine 1.6 文档,请点击[这里](https://www.taosdata.com/cn/documentation16/)访问。
## TDengine介绍
- TDengine 简介及特色
- TDengine 适用场景
## [立即开始](https://www.taosdata.com/cn/getting-started)
- [快捷安装](https://www.taosdata.com/cn/documentation20/getting-started/#快捷安装):可通过源码、安装包或docker安装,三秒钟搞定
- [轻松启动](https://www.taosdata.com/cn/documentation20/getting-started/#轻松启动):使用systemctl 启停TDengine
- [命令行程序TAOS](https://www.taosdata.com/cn/documentation20/getting-started/#TDengine命令行程序):访问TDengine的简便方式
- [极速体验](https://www.taosdata.com/cn/documentation20/getting-started/#TDengine-极速体验):运行示例程序,快速体验高效的数据插入、查询
## [数据模型和整体架构](https://www.taosdata.com/cn/documentation20/architecture)
- [数据模型](https://www.taosdata.com/cn/documentation20/architecture/#数据模型):关系型数据库模型,但要求每个采集点单独建表
- [集群与基本逻辑单元](https://www.taosdata.com/cn/documentation20/architecture/#集群与基本逻辑单元):吸取NoSQL优点,支持水平扩展,支持高可靠
- [存储模型与数据分区、分片](https://www.taosdata.com/cn/documentation20/architecture/#存储模型与数据分区、分片):标签数据与时序数据完全分离,按vnode和时间两个维度对数据切分
- [数据写入与复制流程](https://www.taosdata.com/cn/documentation20/architecture/#数据写入与复制流程):先写入WAL、之后写入缓存,再给应用确认,支持多副本
- [缓存与持久化](https://www.taosdata.com/cn/documentation20/architecture/#缓存与持久化):最新数据缓存在内存中,但落盘时采用列式存储、超高压缩比
- [数据查询](https://www.taosdata.com/cn/documentation20/architecture/#数据查询):支持各种函数、时间轴聚合、插值、多表聚合
## [数据建模](https://www.taosdata.com/cn/documentation20/model)
- [创建库](https://www.taosdata.com/cn/documentation20/model/#创建库):为具有相似数据特征的数据采集点创建一个库
- [创建超级表](https://www.taosdata.com/cn/documentation20/model/#创建超级表):为同一类型的数据采集点创建一个超级表
- [创建表](https://www.taosdata.com/cn/documentation20/model/#创建表):使用超级表做模板,为每一个具体的数据采集点单独建表
## [高效写入数据](https://www.taosdata.com/cn/documentation20/insert)
- [SQL写入](https://www.taosdata.com/cn/documentation20/insert/#SQL写入):使用SQL insert命令向一张或多张表写入单条或多条记录
- [Telegraf写入](https://www.taosdata.com/cn/documentation20/insert/#Telegraf直接写入):配置Telegraf, 不用任何代码,将采集数据直接写入
- [Prometheus写入](https://www.taosdata.com/cn/documentation20/insert/#Prometheus直接写入):配置Prometheus, 不用任何代码,将数据直接写入
- [EMQ X Broker](https://www.taosdata.com/cn/documentation20/insert/#EMQ-X-Broker直接写入):配置EMQ X,不用任何代码,就可将MQTT数据直接写入
## [高效查询数据](https://www.taosdata.com/cn/documentation20/queries)
- [主要查询功能](https://www.taosdata.com/cn/documentation20/queries/#主要查询功能):支持各种标准函数,设置过滤条件,时间段查询
- [多表聚合查询](https://www.taosdata.com/cn/documentation20/queries/#多表聚合查询):使用超级表,设置标签过滤条件,进行高效聚合查询
- [降采样查询值](https://www.taosdata.com/cn/documentation20/queries/#降采样查询、插值):按时间段分段聚合,支持插值
## [高级功能](https://www.taosdata.com/cn/documentation20/advanced-features)
- [连续查询(Continuous Query)](https://www.taosdata.com/cn/documentation20/advanced-features/#连续查询(Continuous-Query)):基于滑动窗口,定时自动的对数据流进行查询计算
- [数据订阅(Publisher/Subscriber)](https://www.taosdata.com/cn/documentation20/advanced-features/#数据订阅(Publisher/Subscriber)):象典型的消息队列,应用可订阅接收到的最新数据
- [缓存(Cache)](https://www.taosdata.com/cn/documentation20/advanced-features/#缓存(Cache)):每个设备最新的数据都会缓存在内存中,可快速获取
- [报警监测](https://www.taosdata.com/cn/documentation20/advanced-features/#报警监测(Alert)):根据配置规则,自动监测超限行为数据,并主动推送
## [连接器](https://www.taosdata.com/cn/documentation20/connector)
- [C/C++ Connector](https://www.taosdata.com/cn/documentation20/connector/#C/C++-Connector):通过libtaos客户端的库,连接TDengine服务器的主要方法
- [Java Connector(JDBC)](https://www.taosdata.com/cn/documentation20/connector/#Java-Connector):通过标准的JDBC API,给Java应用提供到TDengine的连接
- [Python Connector](https://www.taosdata.com/cn/documentation20/connector/#Python-Connector):给Python应用提供一个连接TDengine服务器的驱动
- [RESTful Connector](https://www.taosdata.com/cn/documentation20/connector/#RESTful-Connector):提供一最简单的连接TDengine服务器的方式
- [Go Connector](https://www.taosdata.com/cn/documentation20/connector/#Go-Connector):给Go应用提供一个连接TDengine服务器的驱动
- [Node.js Connector](https://www.taosdata.com/cn/documentation20/connector/#Node.js-Connector):给node应用提供一个链接TDengine服务器的驱动
## [与其他工具的连接](https://www.taosdata.com/cn/documentation20/connections-with-other-tools)
- [Grafana](https://www.taosdata.com/cn/documentation20/connections-with-other-tools/#Grafana):获取并可视化保存在TDengine的数据
- [Matlab](https://www.taosdata.com/cn/documentation20/connections-with-other-tools/#Matlab):通过配置Matlab的JDBC数据源访问保存在TDengine的数据
- [R](https://www.taosdata.com/cn/documentation20/connections-with-other-tools/#R):通过配置R的JDBC数据源访问保存在TDengine的数据
## [TDengine集群的安装、管理](https://www.taosdata.com/cn/documentation20/cluster)
- [安装](https://www.taosdata.com/cn/documentation20/cluster/#创建第一个节点):与单节点的安装一样,但要设好配置文件里的参数first
- [节点管理](https://www.taosdata.com/cn/documentation20/cluster/#节点管理):增加、删除、查看集群的节点
- [mnode的管理](https://www.taosdata.com/cn/documentation20/cluster/#Mnode的高可用):系统自动创建、无需任何人工干预
- [负载均衡](https://www.taosdata.com/cn/documentation20/cluster/#负载均衡):一旦节点个数或负载有变化,自动进行
- [节点离线处理](https://www.taosdata.com/cn/documentation20/cluster/#节点离线处理):节点离线超过一定时长,将从集群中剔除
- [Arbitrator](https://www.taosdata.com/cn/documentation20/cluster/#Arbitrator的使用):对于偶数个副本的情形,使用它可以防止split brain
## [TDengine的运营和维护](https://www.taosdata.com/cn/documentation20/administrator)
- [容量规划](https://www.taosdata.com/cn/documentation20/administrator/#容量规划):根据场景,估算硬件资源
- [容错和灾备](https://www.taosdata.com/cn/documentation20/administrator/#容错和灾备):设置正确的WAL和数据副本数
- [系统配置](https://www.taosdata.com/cn/documentation20/administrator/#服务端配置):端口,缓存大小,文件块大小和其他系统配置
- [用户管理](https://www.taosdata.com/cn/documentation20/administrator/#用户管理):添加、删除TDengine用户,修改用户密码
- [数据导入](https://www.taosdata.com/cn/documentation20/administrator/#数据导入):可按脚本文件导入,也可按数据文件导入
- [数据导出](https://www.taosdata.com/cn/documentation20/administrator/#数据导出):从shell按表导出,也可用taosdump工具做各种导出
- [系统监控](https://www.taosdata.com/cn/documentation20/administrator/#系统监控):检查系统现有的连接、查询、流式计算,日志和事件等
- [文件目录结构](https://www.taosdata.com/cn/documentation20/administrator/#文件目录结构):TDengine数据文件、配置文件等所在目录
## [TAOS SQL](https://www.taosdata.com/cn/documentation20/taos-sql)
- [支持的数据类型](https://www.taosdata.com/cn/documentation20/taos-sql/#支持的数据类型):支持时间戳、整型、浮点型、布尔型、字符型等多种数据类型
- [数据库管理](https://www.taosdata.com/cn/documentation20/taos-sql/#数据库管理):添加、删除、查看数据库
- [表管理](https://www.taosdata.com/cn/documentation20/taos-sql/#表管理):添加、删除、查看、修改表
- [超级表管理](https://www.taosdata.com/cn/documentation20/taos-sql/#超级表STable管理):添加、删除、查看、修改超级表
- [标签管理](https://www.taosdata.com/cn/documentation20/taos-sql/#超级表-STable-中-TAG-管理):增加、删除、修改标签
- [数据写入](https://www.taosdata.com/cn/documentation20/taos-sql/#数据写入):支持单表单条、多条、多表多条写入,支持历史数据写入
- [数据查询](https://www.taosdata.com/cn/documentation20/taos-sql/#数据查询):支持时间段、值过滤、排序、查询结果手动分页等
- [SQL函数](https://www.taosdata.com/cn/documentation20/taos-sql/#SQL函数):支持各种聚合函数、选择函数、计算函数,如avg, min, diff等
- [时间维度聚合](https://www.taosdata.com/cn/documentation20/taos-sql/#时间维度聚合):将表中数据按照时间段进行切割后聚合,降维处理
## TDengine的技术设计
- 系统模块:taosd的功能和模块划分
- 数据复制:支持实时同步、异步复制,保证系统的High Availibility
- [技术博客](https://www.taosdata.com/cn/blog/?categories=3):更多的技术分析和架构设计文章
## 常用工具
- [TDengine样例导入工具](https://www.taosdata.com/blog/2020/01/18/1166.html)
- [TDengine性能对比测试工具](https://www.taosdata.com/blog/2020/01/18/1166.html)
## TDengine与其他数据库的对比测试
- [用InfluxDB开源的性能测试工具对比InfluxDB和TDengine](https://www.taosdata.com/blog/2020/01/13/1105.html)
- [TDengine与OpenTSDB对比测试](https://www.taosdata.com/blog/2019/08/21/621.html)
- [TDengine与Cassandra对比测试](https://www.taosdata.com/blog/2019/08/14/573.html)
- [TDengine与InfluxDB对比测试](https://www.taosdata.com/blog/2019/07/19/419.html)
- [TDengine与InfluxDB、OpenTSDB、Cassandra、MySQL、ClickHouse等数据库的对比测试报告](https://www.taosdata.com/downloads/TDengine_Testing_Report_cn.pdf)
##物联网大数据
- [物联网、工业互联网大数据的特点](https://www.taosdata.com/blog/2019/07/09/105.html)
- [物联网大数据平台应具备的功能和特点](https://www.taosdata.com/blog/2019/07/29/542.html)
- [通用大数据架构为什么不适合处理物联网数据?](https://www.taosdata.com/blog/2019/07/09/107.html)
- [物联网、车联网、工业互联网大数据平台,为什么推荐使用TDengine?](https://www.taosdata.com/blog/2019/07/09/109.html)
## [培训和FAQ](https://www.taosdata.com/cn/faq)
- [FAQ](https://www.taosdata.com/cn/documentation20/faq):常见问题与答案
- [应用案列](https://www.taosdata.com/cn/blog/?categories=4):一些使用实例来解释如何使用TDengine
\ No newline at end of file
# TDengine 适用场景介绍(草案)
# TDengine 介绍
## TDengine 简介
<!-- 本节内容来源于白皮书 -->
TDengine是涛思数据面对高速增长的物联网大数据市场和技术挑战推出的创新性的大数据处理产品,它不依赖任何第三方软件,也不是优化或包装了一个开源的数据库或流式计算产品,而是在吸取众多传统关系型数据库、NoSQL数据库、流式计算引擎、消息队列等软件的优点之后自主开发的产品,在时序空间大数据处理上,有着自己独到的优势。
TDengine的模块之一是时序数据库。但除此之外,为减少研发的复杂度、系统维护的难度,TDengine还提供缓存、消息队列、订阅、流式计算等功能,为物联网、工业互联网大数据的处理提供全栈的技术方案,是一个高效易用的物联网大数据平台。与Hadoop等典型的大数据平台相比,它具有如下鲜明的特点:
* __10倍以上的性能提升__:定义了创新的数据存储结构,单核每秒就能处理至少2万次请求,插入数百万个数据点,读出一千万以上数据点,比现有通用数据库快了十倍以上。
* __硬件或云服务成本降至1/5__:由于超强性能,计算资源不到通用大数据方案的1/5;通过列式存储和先进的压缩算法,存储空间不到通用数据库的1/10
* __全栈时序数据处理引擎__:将数据库、消息队列、缓存、流式计算等功能融合一起,应用无需再集成Kafka/Redis/HBase/Spark/HDFS等软件,大幅降低应用开发和维护的复杂度成本。
......@@ -13,52 +13,48 @@ TDengine是涛思数据面对高速增长的物联网大数据市场和技术挑
* __与第三方工具无缝连接__:不用一行代码,即可与Telegraf, Grafana, EMQ, Prometheus, Matlab, R等集成。后续将支持OPC, Hadoop, Spark等, BI工具也将无缝连接。
* __零运维成本、零学习成本__:安装、集群一秒搞定,无需分库分表,实时备份。标准SQL,支持JDBC, RESTful, 支持Python/Java/C/C++/Go, 与MySQL相似,零学习成本。
<!--sdASF -->
采用TDengine,可将典型的物联网、车联网、工业互联网大数据平台的总拥有成本大幅降低。但需要指出的是,因充分利用了物联网时序数据的特点,它无法用来处理网络爬虫、微博、微信、电商、ERP、CRM等通用型数据。
## TDengine 总体适用场景
作为一个IOT大数据平台,TDengine的典型适用场景是在IOT范畴,而且用户有一定的数据量。本文后续的介绍主要针对这个范畴里面的系统。范畴之外的系统,比如CRM,ERP等,不在本文讨论范围内。
## 数据源特点和需求
### 数据源特点和需求
从数据源角度,设计人员可以从已经角度分析TDengine在目标应用系统里面的适用性。
|数据源特点和需求|不适用|可能适用|非常适用|简单说明|
|---|---|---|---|---|
|总体数据量巨大| | | ✅ |TDengine在容量方面提供出色的水平扩展功能,并且具备匹配高压缩的存储结构,达到业界最优的存储效率。|
|数据输入速度偶尔或者持续巨大| | | ✅ | TDengine的性能大大超过同类产品,可以在同样的硬件环境下持续处理大量的输入数据,并且提供很容易在用户环境里面运行的性能评估工具。|
|数据源数目巨大| | | ✅ |TDengine设计中包含专门针对大量数据源的优化,包括数据的写入和查询,尤其适合高效处理海量(千万或者更多量级)的数据源。|
|总体数据量巨大| | | √ |TDengine在容量方面提供出色的水平扩展功能,并且具备匹配高压缩的存储结构,达到业界最优的存储效率。|
|数据输入速度偶尔或者持续巨大| | | √ | TDengine的性能大大超过同类产品,可以在同样的硬件环境下持续处理大量的输入数据,并且提供很容易在用户环境里面运行的性能评估工具。|
|数据源数目巨大| | | √ |TDengine设计中包含专门针对大量数据源的优化,包括数据的写入和查询,尤其适合高效处理海量(千万或者更多量级)的数据源。|
## 系统架构要求
### 系统架构要求
|系统架构要求|不适用|可能适用|非常适用|简单说明|
|---|---|---|---|---|
|要求简单可靠的系统架构| | | |TDengine的系统架构非常简单可靠,自带消息队列,缓存,流式计算,监控等功能,无需集成额外的第三方产品。|
|要求容错和高可靠| | | |TDengine的集群功能,自动提供容错灾备等高可靠功能|
|标准化规范| | | |TDengine使用标准的SQL语言提供主要功能,遵守标准化规范|
|要求简单可靠的系统架构| | | |TDengine的系统架构非常简单可靠,自带消息队列,缓存,流式计算,监控等功能,无需集成额外的第三方产品。|
|要求容错和高可靠| | | |TDengine的集群功能,自动提供容错灾备等高可靠功能|
|标准化规范| | | |TDengine使用标准的SQL语言提供主要功能,遵守标准化规范|
## 系统功能需求
### 系统功能需求
|系统功能需求|不适用|可能适用|非常适用|简单说明|
|---|---|---|---|---|
|要求完整的内置数据处理算法| | ✅ | |TDengine的实现了通用的数据处理算法,但是还没有做到妥善处理各行各业的所有要求,因此特殊类型的处理还需要应用层面处理。|
|需要大量的交叉查询处理| | ✅ | |这种类型的处理更多应该用关系型数据系统处理,或者应该考虑TDengine和关系型数据系统配合实现系统功能|
|要求完整的内置数据处理算法| | √ | |TDengine的实现了通用的数据处理算法,但是还没有做到妥善处理各行各业的所有要求,因此特殊类型的处理还需要应用层面处理。|
|需要大量的交叉查询处理| | √ | |这种类型的处理更多应该用关系型数据系统处理,或者应该考虑TDengine和关系型数据系统配合实现系统功能|
## 系统性能需求
### 系统性能需求
|系统性能需求|不适用|可能适用|非常适用|简单说明|
|---|---|---|---|---|
|要求较大的总体处理能力| | | |TDengine的集群功能可以轻松地让多服务器配合达成处理能力的提升。|
|要求高速处理数据 | | | |TDengine的专门为IOT优化的存储和数据处理的设计,一般可以让系统得到超出同类产品多倍数的处理速度提升。|
|要求快速处理小粒度数据| | | |这方面TDengine性能可以完全对标关系型和NoSQL型数据处理系统。|
|要求较大的总体处理能力| | | |TDengine的集群功能可以轻松地让多服务器配合达成处理能力的提升。|
|要求高速处理数据 | | | |TDengine的专门为IOT优化的存储和数据处理的设计,一般可以让系统得到超出同类产品多倍数的处理速度提升。|
|要求快速处理小粒度数据| | | |这方面TDengine性能可以完全对标关系型和NoSQL型数据处理系统。|
## 系统维护需求
### 系统维护需求
|系统维护需求|不适用|可能适用|非常适用|简单说明|
|---|---|---|---|---|
|要求系统可靠运行| | | ✅ |TDengine的系统架构非常稳定可靠,日常维护也简单便捷,对维护人员的要求简洁明了,最大程度上杜绝人为错误和事故。|
|要求运维学习成本可控| | | ✅ |同上|
|要求市场有大量人才储备| ✅ | | |TDengine作为新一代产品,目前人才市场里面有经验的人员还有限。但是学习成本低,我们作为厂家也提供运维的培训和辅助服务|
|要求系统可靠运行| | | √ |TDengine的系统架构非常稳定可靠,日常维护也简单便捷,对维护人员的要求简洁明了,最大程度上杜绝人为错误和事故。|
|要求运维学习成本可控| | | √ |同上|
|要求市场有大量人才储备| √ | | |TDengine作为新一代产品,目前人才市场里面有经验的人员还有限。但是学习成本低,我们作为厂家也提供运维的培训和辅助服务|
## TDengine 性能指标介绍和验证方法
......@@ -38,7 +38,7 @@ which systemd
如果系统中不存在`systemd`命令,请考虑[通过源码安装](#通过源码安装)TDengine。
具体的安装过程,请参见[`TDengine多种安装包的安装和卸载`](https://www.taosdata.com/blog/2019/08/09/566.html)
具体的安装过程,请参见<a href="https://www.taosdata.com/blog/2019/08/09/566.html">TDengine多种安装包的安装和卸载</a>
## 轻松启动
......
......@@ -4,14 +4,14 @@
TDengine采用关系型数据模型,需要建库、建表。因此对于一个具体的应用场景,需要考虑库的设计,超级表和普通表的设计。本节不讨论细致的语法规则,只介绍概念。
##创建库
## 创建库
不同类型的数据采集点往往具有不同的数据特征,包括数据采集频率的高低,数据保留时间的长短,副本的数目,数据块的大小等等。为让各种场景下TDengine都能最大效率的工作,TDengine建议将不同数据特征的表创建在不同的库里,因为每个库可以配置不同的存储策略。创建一个库时,除SQL标准的选项外,应用还可以指定保留时长、副本数、内存块个数、时间精度、文件块里最大最小记录条数、是否压缩、一个数据文件覆盖的天数等多种参数。比如:
```cmd
CREATE DATABASE power KEEP 365 DAYS 10 REPLICA 3 BLOCKS 4;
```
上述语句将创建一个名为power的库,这个库的数据将保留365天(超过365天将被自动删除),每10天一个数据文件,副本数为3, 内存块数为4。详细的语法及参数请见TAOS SQL。
上述语句将创建一个名为power的库,这个库的数据将保留365天(超过365天将被自动删除),每10天一个数据文件,副本数为3, 内存块数为4。详细的语法及参数请见<a href="https://www.taosdata.com/cn/documentation20/taos-sql/">TAOS SQL </a>
注意:任何一张表或超级表是属于一个库的,在创建表之前,必须先创建库。
......@@ -20,7 +20,7 @@ CREATE DATABASE power KEEP 365 DAYS 10 REPLICA 3 BLOCKS 4;
```cmd
CREATE TABLE meters (ts timestamp, current float, voltage int, phase float) TAGS (location binary(64), groupdId int);
```
与创建普通表一样,创建表时,需要提供表名(示例中为meters),表结构Schema,即数据列的定义,为采集的物理量(示例中为ts, current, voltage, phase),数据类型可以为整型、浮点型、字符串等。除此之外,还需要提供标签的schema (示例中为location, groupId),标签的数据类型可以为整型、浮点型、字符串等。采集点的静态属性往往可以作为标签,比如采集点的地理位置、设备型号、设备组ID、管理员ID等等。标签的schema可以事后增加、删除、修改。具体定义以及细节请见 TAOS SQL一节。
与创建普通表一样,创建表时,需要提供表名(示例中为meters),表结构Schema,即数据列的定义,为采集的物理量(示例中为ts, current, voltage, phase),数据类型可以为整型、浮点型、字符串等。除此之外,还需要提供标签的schema (示例中为location, groupId),标签的数据类型可以为整型、浮点型、字符串等。采集点的静态属性往往可以作为标签,比如采集点的地理位置、设备型号、设备组ID、管理员ID等等。标签的schema可以事后增加、删除、修改。具体定义以及细节请见 <a href="https://www.taosdata.com/cn/documentation20/taos-sql/">TAOS SQL </a>一节。
每一种类型的数据采集点需要建立一个超级表,因此一个物联网系统,往往会有多个超级表。一个系统可以有多个DB,一个DB里可以有一到多个超级表。
......@@ -31,7 +31,7 @@ CREATE TABLE d1001 USING meters TAGS ("Beijing.Chaoyang", 2);
```
其中d1001是表名,meters是超级表的表名,后面紧跟标签Location的具体标签值”Beijing.Chaoyang",标签groupId的具体标签值2。虽然在创建表时,需要指定标签值,但可以事后修改。详细细则请见 TAOS SQL。
TDengine建议将数据采集点的全局唯一ID作为表名。但对于有的场景,并没有唯一的ID,可以将多个ID组合成一个唯一的ID。不建议将具有唯一性的ID作为标签值。
TDengine建议将数据采集点的全局唯一ID作为表名(比如设备序列号)。但对于有的场景,并没有唯一的ID,可以将多个ID组合成一个唯一的ID。不建议将具有唯一性的ID作为标签值。
**自动建表**:在某些特殊场景中,用户在写数据时并不确定某个数据采集点的表是否存在,此时可在写入数据时使用自动建表语法来创建不存在的表,若该表已存在则不会建立新表。比如:
......@@ -40,4 +40,5 @@ INSERT INTO d1001 USING METERS TAGS ("Beijng.Chaoyang", 2) VALUES (now, 10.2, 21
```
上述SQL语句将记录(now, 10.2, 219, 0.32) 插入进表d1001。如果表d1001还未创建,则使用超级表meters做模板自动创建,同时打上标签值“Beijing.Chaoyang", 2。
**多列模型**:TDengine支持多列模型,只要这些物理量是同时采集的,这些量就可以作为不同列放在同一张表里。有的数据采集点有多组采集量,每一组的数据采集时间是不一样的,这时需要对同一个采集点建多张表。但还有一种极限的设计,单列模型,无论是否同时采集,每个采集的物理量单独建表。TDengine建议,只要采集时间一致,就采用多列模型,因为插入效率以及存储效率更高。
\ No newline at end of file
**多列模型**:TDengine支持多列模型,只要这些物理量是同时采集的,这些量就可以作为不同列放在同一张表里。有的数据采集点有多组采集量,每一组的数据采集时间是不一样的,这时需要对同一个采集点建多张表。但还有一种极限的设计,单列模型,无论是否同时采集,每个采集的物理量单独建表。TDengine建议,只要采集时间一致,就采用多列模型,因为插入效率以及存储效率更高。
......@@ -6,17 +6,16 @@
## 主要查询功能
TDengine采用SQL作为查询语言,应用程序可以通过C/C++, JDBC, GO, Python连接器发送SQL查询语句,用户还可以通过TAOS Shell直接手动执行SQL即席查询,十分方便。支持如下查询功能:
TDengine 采用 SQL 作为查询语言。应用程序可以通过 C/C++, Java, Go, Python 连接器发送 SQL 语句,用户可以通过 TDengine 提供的命令行(Command Line Interface, CLI)工具 TAOS Shell 手动执行 SQL 即席查询(Ad-Hoc Query)。TDengine 支持如下查询功能:
- 查询单列、或多列查询
- 支持值过滤条件:\>, \<, =, \<> 大于,小于,等于,不等于等等
- 支持对标签的模糊匹配
- 支持Group by, Order by, Limit, Offset
- 支持列之间的四则运算
- 支持时间戳对齐的JOIN操作
- 支持多种函数: count, max, min, avg, sum, twa, stddev, leastsquares, top, bottom, first, last, percentile, apercentile, last_row, spread, diff
- 单列、多列数据查询
- 标签和数值的多种过滤条件:\>, \<, =, \<>, like 等
- 聚合结果的分组(Group by)、排序(Order by)、约束输出(Limit/Offset)
- 数值列及聚合结果的四则运算
- 时间戳对齐的连接查询(Join Query)操作
- 多种聚合/计算函数: count, max, min, avg, sum, twa, stddev, leastsquares, top, bottom, first, last, percentile, apercentile, last_row, spread, diff等
例如:在TAOS Shell中,从表d1001中查询出vlotage >215的记录,按时间降序排列,仅仅输出2条。
例如:在TAOS Shell中,从表d1001中查询出vlotage > 215的记录,按时间降序排列,仅仅输出2条。
```mysql
taos> select * from d1001 where voltage > 215 order by ts desc limit 2;
ts | current | voltage | phase |
......@@ -27,11 +26,11 @@ Query OK, 2 row(s) in set (0.001100s)
```
为满足物联网场景的需求,TDengine支持几个特殊的函数,比如twa(时间加权平均),spread (最大值与最小值的差),last_row(最后一条记录)等,更多与物联网场景相关的函数将添加进来。TDengine还支持连续查询。
具体的查询语法请看TAOS SQL
具体的查询语法请看<a href="https://www.taosdata.com/cn/documentation20/taos-sql/">TAOS SQL </a>
## 多表聚合查询
TDengine对每个数据采集点单独建表,但应用经常需要对数据点之间进行聚合。为高效的进行聚合操作,TDengine引入超级表(STable)的概念。超级表用来代表一特定类型的数据采集点,它是表的集合,包含多张表。这集合里每张表的Schema是一样的,但每张表都带有自己的静态标签,标签可以多个,可以随时增加、删除和修改。
TDengine对每个数据采集点单独建表,但在实际应用中经常需要对不同的采集点数据进行聚合。为高效的进行聚合操作,TDengine引入超级表(STable)的概念。超级表用来代表一特定类型的数据采集点,它是包含多张表的表集合,集合里每张表的模式(schema)完全一致,但每张表都带有自己的静态标签,标签可以多个,可以随时增加、删除和修改。
应用可通过指定标签的过滤条件,对一个STable下的全部或部分表进行聚合或统计操作,这样大大简化应用的开发。其具体流程如下图所示:
......@@ -39,16 +38,16 @@ TDengine对每个数据采集点单独建表,但应用经常需要对数据点
<center> 多表聚合查询原理图 </center>
1:应用将一个查询条件发往系统;2: taosc将超级表的名字发往Meta Node(管理节点);3:管理节点将超级表所拥有的vnode列表发回taosc;4:taosc将计算的请求连同标签过滤条件发往这些vnode对应的多个数据节点;5:每个vnode先在内存里查找出自己节点里符合标签过滤条件的表的集合,然后扫描存储的时序数据,完成相应的聚合计算,将结果返回给taosc;6:taosc将多个数据节点返回的结果做最后的聚合,将其返回给应用。
1:应用将一个查询条件发往系统;2: taosc将超级表的名字发往 Meta Node(管理节点);3:管理节点将超级表所拥有的 vnode 列表发回 taosc;4:taosc将计算的请求连同标签过滤条件发往这些vnode对应的多个数据节点;5:每个vnode先在内存里查找出自己节点里符合标签过滤条件的表的集合,然后扫描存储的时序数据,完成相应的聚合计算,将结果返回给taosc;6:taosc将多个数据节点返回的结果做最后的聚合,将其返回给应用。
由于TDengine在vnode内将标签数据与时序数据分离存储,通过先在内存里过滤标签数据,将需要扫描的数据集大幅减少,大幅提升聚合计算速度。同时,由于数据分布在多个vnode/dnode,聚合计算操作在多个vnode里并发进行,又进一步提升了聚合的速度。
由于TDengine在vnode内将标签数据与时序数据分离存储,通过先在内存里过滤标签数据,将需要扫描的数据集大幅减少,大幅提升聚合计算速度。同时,由于数据分布在多个vnode/dnode,聚合计算操作在多个vnode里并发进行,又进一步提升了聚合的速度。
对普通表的聚合函数以及绝大部分操作都适用于超级表,语法完全一样,细节请看TAOS SQL。
对普通表的聚合函数以及绝大部分操作都适用于超级表,语法完全一样,细节请看 TAOS SQL。
比如:在TAOS Shell,查找所有智能电表采集的电压平均值,并按照location分组
```mysql
taos> select avg(voltage) from meters group by location;
taos> SELECT AVG(voltage) FROM meters GROUP BY location;
avg(voltage) | location |
=============================================================
222.000000000 | Beijing.Haidian |
......@@ -58,18 +57,18 @@ Query OK, 2 row(s) in set (0.002136s)
## 降采样查询、插值
物联网场景里,经常需要做down sampling,需要将采集的数据按时间段进行聚合。TDengine提供了一个简便的关键词interval让操作变得极为简单。比如:将智能电表d1001采集的电流值每10秒钟求和
物联网场景里,经常需要通过降采样(down sampling)将采集的数据按时间段进行聚合。TDengine 提供了一个简便的关键词 interval 让按照时间窗口的查询操作变得极为简单。比如,将智能电表 d1001 采集的电流值每10秒钟求和
```mysql
taos> SELECT sum(current) FROM d1001 interval(10s) ;
taos> SELECT sum(current) FROM d1001 INTERVAL(10s) ;
ts | sum(current) |
======================================================
2018-10-03 14:38:00.000 | 10.300000191 |
2018-10-03 14:38:10.000 | 24.900000572 |
Query OK, 2 row(s) in set (0.000883s)
```
降采样操作适用于超级表,比如:将所有智能电表采集的电流值每秒钟求和
降采样操作适用于超级表,比如:将所有智能电表采集的电流值每秒钟求和
```mysql
taos> SELECT sum(current) FROM meters interval(1s) ;
taos> SELECT SUM(current) FROM meters INTERVAL(1s) ;
ts | sum(current) |
======================================================
2018-10-03 14:38:04.000 | 10.199999809 |
......@@ -82,5 +81,5 @@ Query OK, 5 row(s) in set (0.001538s)
物联网场景里,每个数据采集点采集数据的时间是难同步的,但很多分析算法(比如FFT)需要把采集的数据严格按照时间等间隔的对齐,在很多系统里,需要应用自己写程序来处理,但使用TDengine的降采样操作就轻松解决。如果一个时间间隔里,没有采集的数据,TDengine还提供插值计算的功能。
语法规则细节请见TAOS SQL
语法规则细节请见<a href="https://www.taosdata.com/cn/documentation20/taos-sql/">TAOS SQL </a>
......@@ -947,7 +947,7 @@ SELECT function_list FROM stb_name
2. 在时间维度聚合中,返回的结果中时间序列严格单调递增。
3. 如果查询对象是超级表,则聚合函数会作用于该超级表下满足值过滤条件的所有表的数据。如果查询中没有使用group by语句,则返回的结果按照时间序列严格单调递增;如果查询中使用了group by语句分组,则返回结果中每个group内不按照时间序列严格单调递增。
**示例:**智能电表的建表语句如下:
**示例:** 智能电表的建表语句如下:
```mysql
CREATE TABLE meters (ts timestamp, current float, voltage int, phase float) TAGS (location binary(64), groupId int);
......@@ -963,7 +963,7 @@ SELECT AVG(current),MAX(current),LEASTSQUARES(current, start_val, step_val), PER
FILL(PREV);
```
##TAOS SQL 边界限制
## TAOS SQL 边界限制
- 数据库名最大长度为33
- 表名最大长度为193,每行数据最大长度16k个字符
- 列名最大长度为65,最多允许1024列,最少需要2列,第一列必须是时间戳
......
#系统管理
# TDengine的运营与维护
## 容量规划
系统的处理能力是有限的,但通过对TDengine配置参数的调整,可以在性能与容量上进行平衡
使用TDengine来搭建一个物联网大数据平台,计算资源、存储资源需要根据业务场景进行规划。下面分别讨论系统运行所需要的内存、CPU以及硬盘空间
**内存需求**
### 内存需求
每个Database可以创建固定数目的Vnode,默认与CPU核数相同,可通过maxVgroupsPerDb配置;每个vnode会占用固定大小的内存,与参数blocks和cache有关;每个Table会占用与Tag总大小有关的内存;此外,系统会有一些固定的内存开销。因此,每个Database需要的系统内存可通过如下公式计算:
每个DB可以创建固定数目的vnode,默认与CPU核数相同,可通过maxVgroupsPerDb配置;每个vnode会占用固定大小的内存(大小与数据库的配置参数blocks和cache有关);每个Table会占用与标签总长度有关的内存;此外,系统会有一些固定的内存开销。因此,每个DB需要的系统内存可通过如下公式计算:
```
Memory Size = maxVgroupsPerDb * (blocks * cache + 10Mb) + numOfTables * (tagSizePerTable + 0.5Kb)
```
**CPU需求**
示例:假设是4核机器,cache是缺省大小16M, blocks是缺省值6,假设有10万张表,标签总长度是256字节,则总的内存需求为:4\*(16\*6+10) + 100000*(0.25+0.5)/1000 = 499M。
每个Vnode可以容纳的最大数据表数,可以通过参数maxTablesPerVnode设置,但每个Vnode的数据表数在1万以下性能最佳。系统总的Vnode数目最好不要超过CPU核数的两倍
实际运行的系统往往会根据数据特点的不同,将数据存放在不同的DB里。因此做规划时,也需要考虑
**存储需求**
如果内存充裕,可以加大Blocks的配置,这样更多数据将保存在内存里,提高查询速度。
在绝大多数场景下,TDengine的压缩比不会低于5倍。压缩前的原始数据大小可通过如下方式计算:
### CPU需求
CPU的需求取决于如下两方面:
* __数据插入__ TDengine单核每秒能至少处理一万个插入请求。每个插入请求可以带多条记录,一次插入一条记录与插入10条记录,消耗的计算资源差别很小。因此每次插入,条数越大,插入效率越高。如果一个插入请求带200条以上记录,单核就能达到每秒插入100万条记录的速度。但对前端数据采集的要求越高,因为需要缓存记录,然后一批插入。
* __查询需求__ TDengine提供高效的查询,但是每个场景的查询差异很大,查询频次变化也很大,难以给出客观数字。需要用户针对自己的场景,写一些查询语句,才能确定。
因此仅对数据插入而言,CPU是可以估算出来的,但查询所耗的计算资源无法估算。在实际运营过程中,不建议CPU使用率超过50%,超过后,需要增加新的节点,以获得更多计算资源。
### 存储需求
TDengine相对于通用数据库,有超高的压缩比,在绝大多数场景下,TDengine的压缩比不会低于5倍,有的场合,压缩比可达到10倍以上,取决于实际场景的数据特征。压缩前的原始数据大小可通过如下方式计算:
```
Raw DataSize = numOfTables * rowSizePerTable * rowsPerTable
```
用户可以通过参数keep,设置数据在磁盘中的最大保存时长。
示例:1000万台智能电表,每台电表每15分钟采集一次数据,每次采集的数据128字节,那么一年的原始数据量是:10000000\*128\*24\*60/15*365 = 44851T。TDengine大概需要消耗44851/5=8970T, 8.9P空间。
用户可以通过参数keep,设置数据在磁盘中的最大保存时长。为进一步减少存储成本,TDengine还提供多级存储,最冷的数据可以存放在最廉价的存储介质上,应用的访问不用做任何调整,只是读取速度降低了。
为提高速度,可以配置多快硬盘,这样可以并发写入或读取数据。
### 物理机或虚拟机台数
根据上面的内存、CPU、存储的预估,就可以知道整个系统需要多少核、多少内存、多少存储空间。如果数据副本数不为1,总需求量需要再乘以副本数。
因为TDengine具有很好的水平扩展能力,根据总量,再根据单个物理机或虚拟机的资源,就可以轻松决定需要购置多少台物理机或虚拟机了。
## 容错和灾备
**容错**
### 容错
TDengine支持**WAL**(Write Ahead Log)机制,实现数据的容错能力,保证数据的高可用。
TDengine接收到应用的请求数据包时,先将请求的原始数据包写入数据库日志文件,等数据成功写入数据库数据文件后,再删除相应的WAL。这样保证了TDengine能够在断电等因素导致的服务重启时从数据库日志文件中恢复数据,避免数据的丢失。
涉及的系统配置参数有两个.
涉及的系统配置参数有两个
walLevel:WAL级别,1:写wal, 但不执行fsync; 2:写wal, 而且执行fsync。
- walLevel:WAL级别,0:不写wal; 1:写wal, 但不执行fsync; 2:写wal, 而且执行fsync。
- fsync:当walLevel设置为2时,执行fsync的周期。设置为0,表示每次写入,立即执行fsync。
fsync:当walLevel设置为2时,执行fsync的周期。设置为0,表示每次写入,立即执行fsync
如果要100%的保证数据不丢失,需要将walLevel设置为2,fsync设置为0。这时写入速度将会下降。但如果应用侧启动的写数据的线程数达到一定的数量(超过50),那么写入数据的性能也会很不错,只会比fsync设置为3000毫秒下降30%左右
**灾备**
### 灾备
TDengine的集群通过多个副本的机制,来提供系统的高可性,实现灾备能力。
TDengine的集群通过多个副本的机制,来提供系统的高可性,实现灾备能力。
TDengine集群是由mnode负责管理的,为保证mnode的高可靠,可以配置多个mnode副本,副本数由系统配置参数numOfMnodes决定,为了支持高可靠,需要设置大于1。为保证元数据的强一致性,mnode副本之间通过同步方式进行数据复制,保证了元数据的强一致性。
......@@ -50,33 +72,7 @@ TDengine集群中的时序数据的副本数是与数据库关联的,一个集
TDengine集群的节点数必须大于等于副本数,否则创建表时将报错。
当TDengine集群中的节点部署在不同的物理机上(比如不同的机架、或不同的IDC),并设置多个副本数时,就实现了异地容灾,从而提供系统的高可靠性,无需再使用其他软件或工具。
## 文件目录结构
安装TDengine后,默认会在操作系统中生成下列目录或文件:
| 目录/文件 | 说明 |
| ---------------------- | :------------------------------------------------|
| /usr/local/taos/bin | TDengine可执行文件目录。其中的执行文件都会软链接到/usr/bin目录下。 |
| /usr/local/taos/connector | TDengine各种连接器目录。 |
| /usr/local/taos/driver | TDengine动态链接库目录。会软链接到/usr/lib目录下。 |
| /usr/local/taos/examples | TDengine各种语言应用示例目录。 |
| /usr/local/taos/include | TDengine对外提供的C语言接口的头文件。 |
| /etc/taos/taos.cfg | TDengine默认[配置文件] |
| /var/lib/taos | TDengine默认数据文件目录,可通过[配置文件]修改位置. |
| /var/log/taos | TDengine默认日志文件目录,可通过[配置文件]修改位置 |
**可执行文件**
TDengine的所有可执行文件默认存放在 _/usr/local/taos/bin_ 目录下。其中包括:
- _taosd_:TDengine服务端可执行文件
- _taos_: TDengine Shell可执行文件
- _taosdump_:数据导入导出工具
- remove.sh:卸载TDengine的脚本, 请谨慎执行,链接到/usr/bin目录下的rmtaos命令。会删除TDengine的安装目录/usr/local/taos,但会保留/etc/taos、/var/lib/taos、/var/log/taos。
您可以通过修改系统配置文件taos.cfg来配置不同的数据目录和日志目录。
当TDengine集群中的节点部署在不同的物理机上,并设置多个副本数时,就实现了系统的高可靠性,无需再使用其他软件或工具。TDengine企业版还可以将副本部署在不同机房,从而实现异地容灾。
## 服务端配置
......@@ -84,8 +80,8 @@ TDengine系统后台服务由taosd提供,可以在配置文件taos.cfg里修
下面仅仅列出一些重要的配置参数,更多的参数请看配置文件里的说明。各个参数的详细介绍及作用请看前述章节。**注意:配置修改后,需要重启*taosd*服务才能生效。**
- first: taosd启动时,主动连接的集群中第一个dnode的end point, 缺省值为 localhost:6030。
- second: taosd启动时,如果first连接不上,尝试连接集群中第二个dnode的end point, 缺省值为空。
- firstEp: taosd启动时,主动连接的集群中第一个dnode的end point, 缺省值为 localhost:6030。
- secondEp: taosd启动时,如果first连接不上,尝试连接集群中第二个dnode的end point, 缺省值为空。
- fqdn:数据节点的FQDN。如果为空,将自动获取操作系统配置的第一个, 缺省值为空。
- serverPort:taosd启动后,对外服务的端口号,默认值为6030。
- httpPort: RESTful服务使用的端口号,所有的HTTP请求(TCP)都需要向该接口发起查询/写入请求。
......@@ -129,7 +125,7 @@ TDengine集群中加入一个新的dnode时,涉及集群相关的一些参数
- statusInterval: dnode向mnode报告状态时长。单位为秒,默认值:1。
- maxTablesPerVnode: 每个vnode中能够创建的最大表个数。默认值:1000000。
- maxVgroupsPerDb: 每个数据库中能够使用的最大vnode个数。
- arbitrator: 系统中裁决器的end point
- arbitrator: 系统中裁决器的end point,缺省为空
- timezone:时区。从系统中动态获取当前的时区设置。
- locale:系统区位信息及编码格式。系统中动态获取,如果自动获取失败,需要用户在配置文件设置或通过API设置。
- charset:字符集编码。系统中动态获取,如果自动获取失败,需要用户在配置文件设置或通过API设置。
......@@ -140,8 +136,8 @@ TDengine系统的前台交互客户端应用程序为taos,它与taosd共享同
客户端配置参数列表及解释
- first: taos启动时,主动连接的集群中第一个taosd实例的end point, 缺省值为 localhost:6030。
- second: taos启动时,如果first连接不上,尝试连接集群中第二个taosd实例的end point, 缺省值为空。
- firstEp: taos启动时,主动连接的集群中第一个taosd实例的end point, 缺省值为 localhost:6030。
- secondEp: taos启动时,如果first连接不上,尝试连接集群中第二个taosd实例的end point, 缺省值为空。
- charset:字符集编码。系统中动态获取,如果自动获取失败,需要用户在配置文件设置或通过API设置。
- locale:系统区位信息及编码格式。系统中动态获取,如果自动获取失败,需要用户在配置文件设置或通过API设置。
......@@ -230,9 +226,7 @@ Query OK, 9 row(s) affected (0.004763s)
**taosdump工具导入**
TDengine提供了方便的数据库导入导出工具taosdump。用户可以将taosdump从一个系统导出的数据,导入到其他系统中。具体使用方法,请参见博客:
[TDengine DUMP工具使用指南]: https://www.taosdata.com/blog/2020/03/09/1334.html
TDengine提供了方便的数据库导入导出工具taosdump。用户可以将taosdump从一个系统导出的数据,导入到其他系统中。具体使用方法,请参见博客:<a href='https://www.taosdata.com/blog/2020/03/09/1334.html'>TDengine DUMP工具使用指南</a>
## 数据导出
......@@ -250,9 +244,7 @@ select * from <tb_name> >> data.csv
**用taosdump导出数据**
TDengine提供了方便的数据库导出工具taosdump。用户可以根据需要选择导出所有数据库、一个数据库或者数据库中的一张表,所有数据或一时间段的数据,甚至仅仅表的定义。具体使用方法,请参见博客:
[TDengine DUMP工具使用指南]: https://www.taosdata.com/blog/2020/03/09/1334.html
TDengine提供了方便的数据库导出工具taosdump。用户可以根据需要选择导出所有数据库、一个数据库或者数据库中的一张表,所有数据或一时间段的数据,甚至仅仅表的定义。具体使用方法,请参见博客:<a href='https://www.taosdata.com/blog/2020/03/09/1334.html'>TDengine DUMP工具使用指南</a>
## 系统连接、任务查询管理
......@@ -298,4 +290,33 @@ KILL STREAM <stream-id>
TDengine启动后,会自动创建一个监测数据库SYS,并自动将服务器的CPU、内存、硬盘空间、带宽、请求数、磁盘读写速度、慢查询等信息定时写入该数据库。TDengine还将重要的系统操作(比如登录、创建、删除数据库等)日志以及各种错误报警信息记录下来存放在SYS库里。系统管理员可以从CLI直接查看这个数据库,也可以在WEB通过图形化界面查看这些监测信息。
这些监测信息的采集缺省是打开的,但可以修改配置文件里的选项enableMonitor将其关闭或打开。
\ No newline at end of file
这些监测信息的采集缺省是打开的,但可以修改配置文件里的选项enableMonitor将其关闭或打开。
## 文件目录结构
安装TDengine后,默认会在操作系统中生成下列目录或文件:
| 目录/文件 | 说明 |
| ------------------------- | :----------------------------------------------------------- |
| /usr/local/taos/bin | TDengine可执行文件目录。其中的执行文件都会软链接到/usr/bin目录下。 |
| /usr/local/taos/connector | TDengine各种连接器目录。 |
| /usr/local/taos/driver | TDengine动态链接库目录。会软链接到/usr/lib目录下。 |
| /usr/local/taos/examples | TDengine各种语言应用示例目录。 |
| /usr/local/taos/include | TDengine对外提供的C语言接口的头文件。 |
| /etc/taos/taos.cfg | TDengine默认[配置文件] |
| /var/lib/taos | TDengine默认数据文件目录,可通过[配置文件]修改位置. |
| /var/log/taos | TDengine默认日志文件目录,可通过[配置文件]修改位置 |
**可执行文件**
TDengine的所有可执行文件默认存放在 _/usr/local/taos/bin_ 目录下。其中包括:
- _taosd_:TDengine服务端可执行文件
- _taos_: TDengine Shell可执行文件
- _taosdump_:数据导入导出工具
- remove.sh:卸载TDengine的脚本, 请谨慎执行,链接到/usr/bin目录下的rmtaos命令。会删除TDengine的安装目录/usr/local/taos,但会保留/etc/taos、/var/lib/taos、/var/log/taos。
您可以通过修改系统配置文件taos.cfg来配置不同的数据目录和日志目录。
......@@ -119,9 +119,9 @@ taos_consume
taos_unsubscribe
```
这些API的文档请见 [C/C++ 数据订阅接口](TODO: update link),
这些API的文档请见 [C/C++ 数据订阅接口](connector/#C/C++-Connector)
下面仍以智能电表场景为例介绍一下它们的具体用法(超级表和子表结构请参考上一节“连续查询”),
完整的示例代码可以在[这里](TODO: update link)找到。
完整的示例代码可以在 [这里](https://github.com/taosdata/TDengine/blob/master/tests/examples/c/subscribe.c) 找到。
如果我们希望当某个电表的电流超过一定限制(比如10A)后能得到通知并进行一些处理, 有两种方法:
一是分别对每张子表进行查询,每次查询后记录最后一条数据的时间戳,后续只查询这个时间戳之后的数据:
......@@ -296,7 +296,8 @@ $ taos
您可以继续插入一些数据观察示例程序的输出。
## 缓存 (Cache)
## 缓存(Cache)
TDengine采用时间驱动缓存管理策略(First-In-First-Out,FIFO),又称为写驱动的缓存管理机制。这种策略有别于读驱动的数据缓存模式(Least-Recent-Use,LRU),直接将最近写入的数据保存在系统的缓存中。当缓存达到临界值的时候,将最早的数据批量写入磁盘。一般意义上来说,对于物联网数据的使用,用户最为关心最近产生的数据,即当前状态。TDengine充分利用了这一特性,将最近到达的(当前状态)数据保存在缓存中。
TDengine通过查询函数向用户提供毫秒级的数据获取能力。直接将最近到达的数据保存在缓存中,可以更加快速地响应用户针对最近一条或一批数据的查询分析,整体上提供更快的数据库查询响应能力。从这个意义上来说,可通过设置合适的配置参数将TDengine作为数据缓存来使用,而不需要再部署额外的缓存系统,可有效地简化系统架构,降低运维的成本。需要注意的是,TDengine重启以后系统的缓存将被清空,之前缓存的数据均会被批量写入磁盘,缓存的数据将不会像专门的Key-value缓存系统再将之前缓存的数据重新加载到缓存中。
......@@ -308,7 +309,14 @@ TDengine将内存池按块划分进行管理,数据在内存块里按照列式
你可以通过函数last_row快速获取一张表或一张超级表的最后一条记录,这样很便于在大屏显示各设备的实时状态或采集值。例如:
```mysql
select last_row(degree) from thermometer where location='beijing';
select last_row(voltage) from meters where location='Beijing.Chaoyang';
```
该SQL语句将获取所有位于北京的传感器最后记录的温度值。
该SQL语句将获取所有位于北京朝阳区的电表最后记录的电压值。
## 报警监测(Alert)
在 TDengine 的应用场景中,报警监测是一个常见需求,从概念上说,它要求程序从最近一段时间的数据中筛选出符合一定条件的数据,并基于这些数据根据定义好的公式计算出一个结果,当这个结果符合某个条件且持续一定时间后,以某种形式通知用户。
为了满足用户对报警监测的需求,TDengine 以独立模块的形式提供了这一功能,有关它的安装使用方法,请参考博客 [使用 TDengine 进行报警监测](https://www.taosdata.com/blog/2020/04/14/1438.html)
#TDengine 集群安装、管理
多个taosd的运行实例可以组成一个集群,以保证TDengine的高可靠运行,并提供水平扩展能力。要了解TDengine 2.0的集群管理,需要对集群的基本概念有所了解,请看TDengine 2.0整体架构一章。
集群的每个节点是由End Point来唯一标识的,End Point是由FQDN(Fully Qualified Domain Name)外加Port组成,比如 h1.taosdata.com:6030。一般FQDN就是服务器的hostname,可通过Linux命令“hostname"获取。端口是这个节点对外服务的端口号,缺省是6030,但可以通过taos.cfg里配置参数serverPort进行修改。
TDengine的集群管理极其简单,除添加和删除节点需要人工干预之外,其他全部是自动完成,最大程度的降低了运维的工作量。本章对集群管理的操作做详细的描述。
##安装、创建第一个节点
集群是由一个一个dnode组成的,是从一个dnode的创建开始的。创建第一个节点很简单,就按照["立即开始“](https://www.taosdata.com/cn/getting-started/)一章的方法进行安装、启动即可。
启动后,请执行taos, 启动taos shell,从shell里执行命令"show dnodes;",如下所示:
```
Welcome to the TDengine shell from Linux, Client Version:2.0.0.0
Copyright (c) 2017 by TAOS Data, Inc. All rights reserved.
taos> show dnodes;
id | end_point | vnodes | cores | status | role | create_time |
=====================================================================================
1 | h1.taos.com:6030 | 0 | 2 | ready | any | 2020-07-31 03:49:29.202 |
Query OK, 1 row(s) in set (0.006385s)
taos>
```
上述命令里,可以看到这个刚启动的这个节点的End Point是:h1.taos.com:6030
## 安装、创建后续节点
将新的节点添加到现有集群,具体有以下几步:
1. 按照["立即开始“](https://www.taosdata.com/cn/getting-started/)一章的方法进行安装,**但不要启动taosd**
2. 如果是使用涛思数据的官方安装包进行安装,在安装结束时,会询问集群的End Port, 输入第一个节点的End Point即可。如果是源码安装,请编辑配置文件taos.cfg(缺省是在/etc/taos/目录),增加一行:
```
firstEp h1.taos.com:6030
```
请注意将示例的“h1.taos.com:6030" 替换为你自己第一个节点的End Point
3. 按照["立即开始“](https://www.taosdata.com/cn/getting-started/)一章的方法启动taosd
4. 在Linux shell里执行命令"hostname"找出本机的FQDN, 假设为h2.taos.com。如果无法找到,可以查看taosd日志文件taosdlog.0里前面几行日志(一般在/var/log/taos目录),fqdn以及port都会打印出来。
5. 在第一个节点,使用CLI程序taos, 登录进TDengine系统, 使用命令:
```
CREATE DNODE "h2.taos.com:6030";
```
将新节点的End Point添加进集群的EP列表。**"fqdn:port"需要用双引号引起来**,否则出错。请注意将示例的“h2.taos.com:6030" 替换为你自己第一个节点的End Point
6. 使用命令
```
SHOW DNODES;
```
查看新节点是否被成功加入。
按照上述步骤可以源源不断的将新的节点加入到集群。
**提示:**
- firstEp, secondEp这两个参数仅仅在该节点第一次加入集群时有作用,加入集群后,该节点会保存最新的mnode的End Point列表,不再依赖这两个参数。
- 两个没有配置firstEp, secondEp参数的dnode启动后,会独立运行起来。这个时候,无法将其中一个节点加入到另外一个节点,形成集群。**无法将两个独立的集群合并成为新的集群**
##节点管理
###添加节点
执行CLI程序taos, 使用root账号登录进系统, 执行:
```
CREATE DNODE "fqdn:port";
```
将新节点的End Point添加进集群的EP列表。**"fqdn:port"需要用双引号引起来**,否则出错。一个节点对外服务的fqdn和port可以通过配置文件taos.cfg进行配置,缺省是自动获取。
###删除节点
执行CLI程序taos, 使用root账号登录进TDengine系统,执行:
```
DROP DNODE "fqdn:port";
```
其中fqdn是被删除的节点的FQDN,port是其对外服务器的端口号
###查看节点
执行CLI程序taos,使用root账号登录进TDengine系统,执行:
```
SHOW DNODES;
```
它将列出集群中所有的dnode,每个dnode的fqdn:port, 状态(ready, offline等),vnode数目,还未使用的vnode数目等信息。在添加或删除一个节点后,可以使用该命令查看。
###查看虚拟节点组
为充分利用多核技术,并提供scalability,数据需要分片处理。因此TDengine会将一个DB的数据切分成多份,存放在多个vnode里。这些vnode可能分布在多个dnode里,这样就实现了水平扩展。一个vnode仅仅属于一个DB,但一个DB可以有多个vnode。vnode的是mnode根据当前系统资源的情况,自动进行分配的,无需任何人工干预。
执行CLI程序taos,使用root账号登录进TDengine系统,执行:
```
SHOW VGROUPS;
```
##高可用性
TDengine通过多副本的机制来提供系统的高可用性。副本数是与DB关联的,一个集群里可以有多个DB,根据运营的需求,每个DB可以配置不同的副本数。创建数据库时,通过参数replica 指定副本数(缺省为1)。如果副本数为1,系统的可靠性无法保证,只要数据所在的节点宕机,就将无法提供服务。集群的节点数必须大于等于副本数,否则创建表时将返回错误“more dnodes are needed"。比如下面的命令将创建副本数为3的数据库demo:
```
CREATE DATABASE demo replica 3;
```
一个DB里的数据会被切片分到多个vnode group,vnode group里的vnode数目就是DB的副本数,同一个vnode group里各vnode的数据是完全一致的。为保证高可用性,vnode group里的vnode一定要分布在不同的dnode里(实际部署时,需要在不同的物理机上),只要一个vgroup里超过半数的vnode处于工作状态,这个vgroup就能正常的对外服务。
一个dnode里可能有多个DB的数据,因此一个dnode离线时,可能会影响到多个DB。如果一个vnode group里的一半或一半以上的vnode不工作,那么该vnode group就无法对外服务,无法插入或读取数据,这样会影响到它所属的DB的一部分表的d读写操作。
因为vnode的引入,无法简单的给出结论:“集群中过半dnode工作,集群就应该工作”。但是对于简单的情形,很好下结论。比如副本数为3,只有三个dnode,那如果仅有一个节点不工作,整个集群还是可以正常工作的,但如果有两个节点不工作,那整个集群就无法正常工作了。
##Mnode的高可用
TDengine集群是由mnode (taosd的一个模块,逻辑节点) 负责管理的,为保证mnode的高可用,可以配置多个mnode副本,副本数由系统配置参数numOfMnodes决定,有效范围为1-3。为保证元数据的强一致性,mnode副本之间是通过同步的方式进行数据复制的。
一个集群有多个dnode, 但一个dnode至多运行一个mnode实例。多个dnode情况下,哪个dnode可以作为mnode呢?这是完全由系统根据整个系统资源情况,自动指定的。用户可通过CLI程序taos,在TDengine的console里,执行如下命令:
```
SHOW MNODES;
```
来查看mnode列表,该列表将列出mnode所处的dnode的End Point和角色(master, slave, unsynced 或offline)。
当集群中第一个节点启动时,该节点一定会运行一个mnode实例,否则该dnode无法正常工作,因为一个系统是必须有至少一个mnode的。如果numOfMnodes配置为2,启动第二个dnode时,该dnode也将运行一个mnode实例。
为保证mnode服务的高可用性,numOfMnodes必须设置为2或更大。因为mnode保存的元数据必须是强一致的,如果numOfMnodes大于2,复制参数quorum自动设为2,也就是说,至少要保证有两个副本写入数据成功,才通知客户端应用写入成功。
##负载均衡
有三种情况,将触发负载均衡,而且都无需人工干预。
- 当一个新节点添加进集群时,系统将自动触发负载均衡,一些节点上的数据将被自动转移到新节点上,无需任何人工干预。
- 当一个节点从集群中移除时,系统将自动把该节点上的数据转移到其他节点,无需任何人工干预。
- 如果一个节点过热(数据量过大),系统将自动进行负载均衡,将该节点的一些vnode自动挪到其他节点。
当上述三种情况发生时,系统将启动一各个节点的负载计算,从而决定如何挪动。
##节点离线处理
如果一个节点离线,TDengine集群将自动检测到。有如下两种情况:
- 改节点离线超过一定时间(taos.cfg里配置参数offlineThreshold控制时长),系统将自动把该节点删除,产生系统报警信息,触发负载均衡流程。如果该被删除的节点重现上线时,它将无法加入集群,需要系统管理员重新将其添加进集群才会开始工作。
- 离线后,在offlineThreshold的时长内重新上线,系统将自动启动数据恢复流程,等数据完全恢复后,该节点将开始正常工作。
**注意:**如果一个虚拟节点组(包括mnode组)里每个节点都处于离线或unsynced状态,必须等该虚拟节点组里的所有节点都上线、都能交换状态信息后,才能选出Master,该虚拟节点组才能对外提供服务。比如整个集群有3个节点,副本数为3,如果3个节点都宕机,然后2个节点重启,是无法工作的,只有等3个节点都重启成功,才能对外服务。
##Arbitrator的使用
如果副本数为偶数,当一个vnode group里一半或超过一半的vnode不工作时,是无法从中选出master的。同理,一半或超过一半的mnode不工作时,是无法选出mnode的master的,因为存在“split brain”问题。为解决这个问题,TDengine引入了arbitrator的概念。Arbitrator模拟一个vnode或mnode在工作,但只简单的负责网络连接,不处理任何数据插入或访问。只要包含arbitrator在内,超过半数的vnode或mnode工作,那么该vnode group或mnode组就可以正常的提供数据插入或查询服务。比如对于副本数为2的情形,如果一个节点A离线,但另外一个节点B正常,而且能连接到arbitrator, 那么节点B就能正常工作。
TDengine安装包里带有一个执行程序tarbitrator, 找任何一台Linux服务器运行它即可。该程序对系统资源几乎没有要求,只需要保证有网络连接即可。该应用的命令行参数`-p`可以指定其对外服务的端口号,缺省是6030。配置每个taosd实例时,可以在配置文件taos.cfg里将参数arbitrator设置为arbitrator的End Point。如果该参数配置了,当副本数为偶数数,系统将自动连接配置的arbitrator。
#集群管理
#集群安装、管理
多个taosd的运行实例可以组成一个集群,以保证TDengine的高可靠运行,并提供水平扩展能力。要了解TDengine 2.0的集群管理,需要对集群的基本概念有所了解,请看TDengine 2.0整体架构一章。
集群的每个节点是由End Point来唯一标识的,End Point是由FQDN(Fully Qualified Domain Name)外加Port组成,比如 h1.taosdata.com:6030。一般FQDN就是服务器的hostname,可通过Linux命令“hostname"获取。端口是这个节点对外服务的端口号,缺省是6030,但可以通过taos.cfg里配置参数serverPort进行修改。
TDengine的集群管理极其简单,除添加和删除节点需要人工干预之外,其他全部是自动完成,最大程度的降低了运维的工作量。本章对集群管理的操作做详细的描述。
##创建第一个节点
集群是由一个一个dnode组成的,是从一个dnode的创建开始的。创建第一个节点很简单,确保系统配置文件taos.cfg里的参数first与second没有进行设置后,简单的运行taosd即可。配置文件taos.cfg里参数first与second缺省都是设置为空,因此无需特殊操作。如果为了统一配置,可以将参数first配置为第一个dnode的End Point。
##安装、创建第一个节点
这个节点创建后,它是集群中的第一个节点。如果该节点收到一个新节点加入集群的请求,它将检查这个新节点的End Point是否在集群的EP列表中,如果在,就容许其加入。如果不在列表中,就拒绝其加入
集群是由一个一个dnode组成的,是从一个dnode的创建开始的。创建第一个节点很简单,就按照["立即开始“](https://www.taosdata.com/cn/getting-started/)一章的方法进行安装、启动即可
##节点管理
###添加节点
具体有以下几个步骤:
1. 修改新节点配置文件taos.cfg, 将其中参数first与second设置为现有集群中运行节点的End Point, 然后启动taosd。second可以不用设置,目的是为集群规模较大时,first无法访问时,该节点将尝试访问second节点。
2. 使用CLI程序taos, 登录进系统, 使用命令:
启动后,请执行taos, 启动taos shell,从shell里执行命令"show dnodes;",如下所示:
```
CREATE DNODE "fqdn:port";
Welcome to the TDengine shell from Linux, Client Version:2.0.0.0
Copyright (c) 2017 by TAOS Data, Inc. All rights reserved.
taos> show dnodes;
id | end_point | vnodes | cores | status | role | create_time |
=====================================================================================
1 | h1.taos.com:6030 | 0 | 2 | ready | any | 2020-07-31 03:49:29.202 |
Query OK, 1 row(s) in set (0.006385s)
taos>
```
将新节点的End Point添加进集群的EP列表。**"fqdn:port"需要用双引号引起来**,否则出错。一个节点对外服务的fqdn和port可以通过配置文件taos.cfg进行配置。
3. 使用命令
上述命令里,可以看到这个刚启动的这个节点的End Point是:h1.taos.com:6030
## 安装、创建后续节点
将新的节点添加到现有集群,具体有以下几步:
1. 按照["立即开始“](https://www.taosdata.com/cn/getting-started/)一章的方法进行安装,但不要启动taosd
2. 如果是使用涛思数据的官方安装包进行安装,在安装结束时,会询问集群的End Port, 输入第一个节点的End Point即可。如果是源码安装,请编辑配置文件taos.cfg(缺省是在/etc/taos/目录),增加一行:
```
SHOW DNODES
firstEp h1.taos.com:6030
```
查看新节点是否被成功加入。`
**示例:**假设有两个节点,其EP分别为 host1:6030, host2:6050. 可以按照以下步骤创建集群
请注意将示例的“h1.taos.com:6030" 替换为你自己第一个节点的End Point
3. 按照["立即开始“](https://www.taosdata.com/cn/getting-started/)一章的方法启动taosd
4. 在Linux shell里执行命令"hostname"找出本机的FQDN, 假设为h2.taos.com。如果无法找到,可以查看taosd日志文件taosdlog.0里前面几行日志(一般在/var/log/taos目录),fqdn以及port都会打印出来。
5. 在第一个节点,使用CLI程序taos, 登录进TDengine系统, 使用命令:
1. 在host1, 启动taosd;
2. 修改host2:6050的配置文件taos.cfg, 将参数first设置为host1:6030,然后启动host2:6050这个taosd实例;
3. 执行“taos -h host1" 链接到host1, 在TDengine console里执行命令:
```
CREATE DNODE "host2:6050";
CREATE DNODE "h2.taos.com:6030";
```
4. 在TDengine console里执行`"show dnodes"`查看节点是否加入成功.
5. 按照上述第2到第5步,逐步把其他节点添加到集群中。
将新节点的End Point添加进集群的EP列表。**"fqdn:port"需要用双引号引起来**,否则出错。请注意将示例的“h2.taos.com:6030" 替换为你自己第一个节点的End Point
6. 使用命令
```
SHOW DNODES;
```
查看新节点是否被成功加入。
按照上述步骤可以源源不断的将新的节点加入到集群。
**提示:**
- first, second这两个参数仅仅在该节点第一次加入集群时有作用,加入集群后,该节点会保存最新的mnode的End Point列表,不再依赖这两个参数。
- firstEp, secondEp这两个参数仅仅在该节点第一次加入集群时有作用,加入集群后,该节点会保存最新的mnode的End Point列表,不再依赖这两个参数。
- 两个没有配置first, second参数的dnode启动后,会独立运行起来。这个时候,无法将其中一个节点加入到另外一个节点,形成集群。**无法将两个独立的集群合并成为新的集群**
##节点管理
###添加节点
执行CLI程序taos, 使用root账号登录进系统, 执行:
```
CREATE DNODE "fqdn:port";
```
将新节点的End Point添加进集群的EP列表。**"fqdn:port"需要用双引号引起来**,否则出错。一个节点对外服务的fqdn和port可以通过配置文件taos.cfg进行配置,缺省是自动获取。
###删除节点
执行CLI程序taos, 使用root账号登录进TDengine系统,执行:
```
......
......@@ -45,11 +45,11 @@ C/C++的API类似于MySQL的C API。应用程序使用时,需要包含TDengine
创建数据库连接,初始化连接上下文。其中需要用户提供的参数包含:
* ip:TDengine管理主节点的IP地址
* user:用户名
* pass:密码
* db:数据库名字,如果用户没有提供,也可以正常连接,用户可以通过该连接创建新的数据库,如果用户提供了数据库名字,则说明该数据库用户已经创建好,缺省使用该数据库
* port:端口号
- ip:TDengine管理主节点的IP地址
- user:用户名
- pass:密码
- db:数据库名字,如果用户没有提供,也可以正常连接,用户可以通过该连接创建新的数据库,如果用户提供了数据库名字,则说明该数据库用户已经创建好,缺省使用该数据库
- port:端口号
返回值为空表示失败。应用程序需要保存返回的参数,以便后续API调用。
......
......@@ -5,19 +5,19 @@
2.0版本在之前版本的基础上,进行了完全的重构,配置文件和数据文件是不兼容的。在升级之前务必进行如下操作:
1. 删除配置文件,执行 <code> sudo rm -rf /etc/taos/taos.cfg </code>
2. 删除日志文件,执行 <code> sudo rm -rf /var/log/taos/ </code>
3. 确保数据已经不再需要的前提下,删除数据文件,执行 <code> sudo rm -rf /var/lib/taos/ </code>
4. 安装最新稳定版本的TDengine
5. 如果数据需要迁移数据或者数据文件损坏,请联系涛思数据官方技术支持团队,进行协助解决
5. 如果数据需要迁移数据或者数据文件损坏,请联系涛思数据官方技术支持团队,进行协助解决
#### 2. <a href='blog/2019/12/03/jdbcdriver找不到动态链接库/'>Windows平台下JDBCDriver找不到动态链接库</a>
#### 2. Windows平台下JDBCDriver找不到动态链接库,怎么办?
请看为此问题撰写的<a href='blog/2019/12/03/jdbcdriver找不到动态链接库/'>技术博客 </a>
#### 3. <a href='blog/2019/12/03/创建数据表时提示more-dnodes-are-needed/'>创建数据表时提示more dnodes are needed</a>
#### 3. 创建数据表时提示more dnodes are needed
请看为此问题撰写的<a href='blog/2019/12/03/创建数据表时提示more-dnodes-are-needed/'>技术博客</a>
#### 4. <a href='blog/2019/12/06/tdengine-crash时生成core文件的方法/'>TDengine crash时生成core文件的方法</a>
#### 4. 如何让TDengine crash时生成core文件?
请看为此问题撰写的<a href='blog/2019/12/06/tdengine-crash时生成core文件的方法/'>技术博客</a>
#### 5. 遇到错误"failed to connect to server", 我怎么办?
......@@ -68,7 +68,8 @@ windows下插入nchar类的数据中如果有中文,请先确认系统的地
​ Connection = DriverManager.getConnection(url, properties);
#### 12. <a href='blog/2020/01/06/tdengine-go-windows驱动的编译/'>TDengine GO windows驱动的编译</a>
#### 12.TDengine GO windows驱动的如何编译?
请看为此问题撰写的<a href='blog/2020/01/06/tdengine-go-windows驱动的编译/'>技术博客
......@@ -18,14 +18,17 @@ TDengine也支持一次向多个表写入数据,比如下面这条命令就向
INSERT INTO d1001 VALUES (1538548685000, 10.3, 219, 0.31) (1538548695000, 12.6, 218, 0.33) d1002 VALUES (1538548696800, 12.3, 221, 0.31);
```
**Tips:** 要提高写入效率,需要批量写入。一批写入的记录条数越多,插入效率就越高。但一条记录不能超过16K,一条SQL语句总长度不能超过64K(可通过参数maxSQLLength配置)。
详细的SQL INSERT语法规则请见<a href="https://www.taosdata.com/cn/documentation20/taos-sql/">TAOS SQL </a>
详细的SQL INSERT语法规则请见TAOS SQL
**Tips:**
##Prometheus直接写入
- 要提高写入效率,需要批量写入。一批写入的记录条数越多,插入效率就越高。但一条记录不能超过16K,一条SQL语句总长度不能超过64K(可通过参数maxSQLLength配置)。
- TDengine支持多线程同时写入,要进一步提高写入速度,一个客户端需要打开20个以上的线程同时写。但线程数达到一定数量后,无法再提高,甚至还会下降,因为线程切频繁切换,带来额外开销。
## Prometheus直接写入
[Prometheus](https://www.prometheus.io/)作为Cloud Native Computing Fundation毕业的项目,在性能监控以及K8S性能监控领域有着非常广泛的应用。TDengine提供一个小工具[Bailongma](https://github.com/taosdata/Bailongma),只需在Prometheus做简单配置,无需任何代码,就可将Prometheus采集的数据直接写入TDengine,并按规则在TDengine自动创建库和相关表项。博文[用Docker容器快速搭建一个Devops监控Demo](https://www.taosdata.com/blog/2020/02/03/1189.html)即是采用bailongma将Prometheus和Telegraf的数据写入TDengine中的示例,可以参考。
###从源代码编译blm_prometheus
### 从源代码编译blm_prometheus
用户需要从github下载[Bailongma](https://github.com/taosdata/Bailongma)的源码,使用Golang语言编译器编译生成可执行文件。在开始编译前,需要准备好以下条件:
- Linux操作系统的服务器
- 安装好Golang, 1.10版本以上
......@@ -39,7 +42,7 @@ go build
一切正常的情况下,就会在对应的目录下生成一个blm_prometheus的可执行程序。
###安装Prometheus
### 安装Prometheus
通过Prometheus的官网下载安装。[下载地址](https://prometheus.io/download/)
### 配置Prometheus
......@@ -70,7 +73,7 @@ blm_prometheus会将收到的prometheus的数据拼装成TDengine的写入请求
blm_prometheus对prometheus提供服务的端口号。
```
###启动示例
### 启动示例
通过以下命令启动一个blm_prometheus的API服务
```
......@@ -82,7 +85,7 @@ remote_write:
- url: "http://10.1.2.3:8088/receive"
```
###查询prometheus写入数据
### 查询prometheus写入数据
prometheus产生的数据格式如下:
```
Timestamp: 1576466279341,
......@@ -104,10 +107,10 @@ use prometheus;
select * from apiserver_request_latencies_bucket;
```
##Telegraf直接写入
## Telegraf直接写入
[Telegraf](https://www.influxdata.com/time-series-platform/telegraf/)是一流行的IT运维数据采集开源工具,TDengine提供一个小工具[Bailongma](https://github.com/taosdata/Bailongma),只需在Telegraf做简单配置,无需任何代码,就可将Telegraf采集的数据直接写入TDengine,并按规则在TDengine自动创建库和相关表项。博文[用Docker容器快速搭建一个Devops监控Demo](https://www.taosdata.com/blog/2020/02/03/1189.html)即是采用bailongma将Prometheus和Telegraf的数据写入TDengine中的示例,可以参考。
###从源代码编译blm_telegraf
### 从源代码编译blm_telegraf
用户需要从github下载[Bailongma](https://github.com/taosdata/Bailongma)的源码,使用Golang语言编译器编译生成可执行文件。在开始编译前,需要准备好以下条件:
- Linux操作系统的服务器
......@@ -123,7 +126,7 @@ go build
一切正常的情况下,就会在对应的目录下生成一个blm_telegraf的可执行程序。
###安装Telegraf
### 安装Telegraf
目前TDengine支持Telegraf 1.7.4以上的版本。用户可以根据当前的操作系统,到Telegraf官网下载安装包,并执行安装。下载地址如下:https://portal.influxdata.com/downloads
### 配置Telegraf
......@@ -142,7 +145,7 @@ go build
关于如何使用Telegraf采集数据以及更多有关使用Telegraf的信息,请参考Telegraf官方的[文档](https://docs.influxdata.com/telegraf/v1.11/)
###启动blm_telegraf程序
### 启动blm_telegraf程序
blm_telegraf程序有以下选项,在启动blm_telegraf程序时可以通过设定这些选项来设定blm_telegraf的配置。
```sh
......@@ -165,7 +168,7 @@ blm_telegraf会将收到的telegraf的数据拼装成TDengine的写入请求,
blm_telegraf对telegraf提供服务的端口号。
```
###启动示例
### 启动示例
通过以下命令启动一个blm_telegraf的API服务
```
./blm_telegraf -host 127.0.0.1 -port 8089
......@@ -177,7 +180,7 @@ blm_telegraf对telegraf提供服务的端口号。
url = "http://10.1.2.3:8089/telegraf"
```
###查询telegraf写入数据
### 查询telegraf写入数据
telegraf产生的数据格式如下:
```
{
......@@ -210,7 +213,7 @@ use telegraf;
select * from cpu;
```
## EMQ X MQTT Broker直接写入
## EMQ X Broker直接写入
MQTT是一流行的物联网数据传输协议,[EMQ](https://github.com/emqx/emqx)是一开源的MQTT Broker软件,无需任何代码,只需要在EMQ Dashboard里使用“规则”做简单配置,即可将MQTT的数据直接写入TDengine。EMQ X 支持通过 发送到 Web 服务 的方式保存数据到 TDEngine,也在企业版上提供原生的 TDEngine 驱动实现直接保存。详细使用方法请参考 [EMQ 官方文档](https://docs.emqx.io/broker/latest/cn/rule/rule-example.html#%E4%BF%9D%E5%AD%98%E6%95%B0%E6%8D%AE%E5%88%B0-tdengine)
此差异已折叠。
# TDengine 2.0 执行代码taosd的设计
逻辑上,TDengine系统包含dnode, taosc和App,dnode是服务器侧执行代码taosd的一个运行实例,因此taosd是TDengine的核心,本文对taosd的设计做一简单的介绍,模块内的实现细节请见其他文档。
## 系统模块图
taosd包含rpc, dnode, vnode, tsdb, query, cq, sync, wal, mnode, http, monitor等模块,具体如下图:
<center> <img src="../assets/modules.png"> </center>
taosd的启动入口是dnode模块,dnode然后启动其他模块,包括可选配置的http, monitor模块。taosc或dnode之间交互的消息都是通过rpc模块进行,dnode模块根据接收到的消息类型,将消息分发到vnode或mnode的消息队列,或由dnode模块自己消费。dnode的工作线程(worker)消费消息队列里的消息,交给mnode或vnode进行处理。下面对各个模块做简要说明。
## RPC模块
该模块负责taosd与taosc, 以及其他数据节点之间的通讯。TDengine没有采取标准的HTTP或gRPC等第三方工具,而是实现了自己的通讯模块RPC。
考虑到物联网场景下,数据写入的包一般不大,因此除支持TCP链接之外,RPC还支持UDP链接。当数据包小于15K时,RPC将采用UDP方式进行链接,否则将采用TCP链接。对于查询类的消息,RPC不管包的大小,总是采取TCP链接。对于UDP链接,RPC实现了自己的超时、重传、顺序检查等机制,以保证数据可靠传输。
RPC模块还提供数据压缩功能,如果数据包的字节数超过系统配置参数compressMsgSize, RPC在传输中将自动压缩数据,以节省带宽。
为保证数据的安全和数据的integrity, RPC模块采用MD5做数字签名,对数据的真实性和完整性进行认证。
## DNODE模块
该模块是整个taosd的入口,它具体负责如下任务:
- 系统的初始化,包括
- 从文件taos.cfg读取系统配置参数,从文件dnodeCfg.json读取数据节点的配置参数;
- 启动RPC模块,并建立起与taosc通讯的server链接,与其他数据节点通讯的server链接;
- 启动并初始化dnode的内部管理, 该模块将扫描该数据节点已有的vnode,并打开它们;
- 初始化可配置的模块,如mnode, http, monitor等。
- 数据节点的管理,包括
- 定时的向mnode发送status消息,报告自己的状态;
- 根据mnode的指示,创建、改变、删除vnode;
- 根据mnode的指示,修改自己的配置参数;
- 消息的分发、消费,包括
- 为每一个vnode和mnode的创建并维护一个读队列、一个写队列;
- 将从taosc或其他数据节点来的消息,根据消息类型,将其直接分发到不同的消息队列,或由自己的管理模块直接消费;
- 维护一个读的线程池,消费读队列的消息,交给vnode或mnode处理。为支持高并发,一个读线程(Worker)可以消费多个队列的消息,一个读队列可以由多个worker消费;
- 维护一个写的线程池,消费写队列的消息,交给vnode或mnode处理。为保证写操作的序列化,一个写队列只能由一个写线程负责,但一个写线程可以负责多个写队列。
taosd的消息消费由dnode通过读写线程池进行控制,是系统的中枢。该模块内的结构体图如下:
<center> <img src="../assets/dnode.png"> </center>
## VNODE模块
vnode是一独立的数据存储查询逻辑单元,但因为一个vnode只能容许一个DB,因此vnode内部没有account, DB, user等概念。为实现更好的模块化、封装以及未来的扩展,它有很多子模块,包括负责存储的TSDB,负责查询的Query, 负责数据复制的sync,负责数据库日志的的wal, 负责连续查询的cq(continuous query), 负责事件触发的流计算的event等模块,这些子模块只与vnode模块发生关系,与其他模块没有任何调用关系。模块图如下:
<center> <img src="../assets/vnode.png"> </center>
vnode模块向下,与dnodeVRead,dnodeVWrite发生互动,向上,与子模块发生互动。它主要的功能有:
- 协调各个子模块的互动。各个子模块之间都不直接调用,都需要通过vnode模块进行;
- 对于来自taosc或mnode的写操作,vnode模块将其分解为写日志(wal), 转发(sync), 本地存储(tsdb)子模块的操作;
- 对于查询操作,分发到query模块进行。
一个数据节点里有多个vnode, 因此vnode模块是有多个运行实例的。每个运行实例是完全独立的。
vnode与其子模块是通过API直接调用,而不是通过消息队列传递。而且各个子模块只与vnode模块有交互,不与dnode, rpc等模块发生任何直接关联。
## MNODE模块
mnode是整个系统的大脑,负责整个系统的资源调度,负责meta data的管理与存储。
一个运行的系统里,只有一个mnode,但它有多个副本(由系统配置参数numOfMpeers控制)。这些副本分布在不同的dnode里,目的是保证系统的高可靠运行。副本之间的数据复制是采用同步而非异步的方式,以确保数据的一致性,确保数据不会丢失。这些副本会自动选举一个Master,其他副本是slave。所有数据更新类的操作,都只能在master上进行,而查询类的可以在slave节点上进行。代码实现上,同步模块与vnode共享,但mnode被分配一个特殊的vgroup ID: 1,而且quorum大于1。整个集群系统是由多个dnode组成的,运行的mnode的副本数不可能超过dnode的个数,但不会超过配置的副本数。如果某个mnode副本宕机一段时间,只要超过半数的mnode副本仍在运行,运行的mnode会自动根据整个系统的资源情况,在其他dnode里再启动一个mnode, 以保证运行的副本数。
各个dnode通过信息交换,保存有mnode各个副本的End Point列表,并向其中的master节点定时(间隔由系统配置参数statusInterval控制)发送status消息,消息体里包含该dnode的CPU、内存、剩余存储空间、vnode个数,以及各个vnode的状态(存储空间、原始数据大小、记录条数、角色等)。这样mnode就了解整个系统的资源情况,如果用户创建新的表,就可以决定需要在哪个dnode创建;如果增加或删除dnode, 或者监测到某dnode数据过热、或离线太长,就可以决定需要挪动那些vnode,以实现负载均衡。
mnode里还负责account, user, DB, stable, table, vgroup, dnode的创建、删除与更新。mnode不仅把这些entity的meta data保存在内存,还做持久化存储。但为节省内存,各个表的标签值不保存在mnode(保存在vnode),而且子表不维护自己的schema, 而是与stable共享。为减小mnode的查询压力,taosc会缓存table、stable的schema。对于查询类的操作,各个slave mnode也可以提供,以减轻master压力。
## TSDB模块
TSDB模块是VNODE中的负责快速高并发地存储和读取属于该VNODE的表的元数据及采集的时序数据的引擎。除此之外,TSDB还提供了表结构的修改、表标签值的修改等功能。TSDB提供API供VNODE和Query等模块调用。TSDB中存储了两类数据,1:元数据信息;2:时序数据
### 元数据信息
TSDB中存储的元数据包含属于其所在的VNODE中表的类型,schema的定义等。对于超级表和超级表下的子表而言,又包含了tag的schema定义以及子表的tag值等。对于元数据信息而言,TSDB就相当于一个全内存的KV型数据库,属于该VNODE的表对象全部在内存中,方便快速查询表的信息。除此之外,TSDB还对其中的子表,按照tag的第一列取值做了全内存的索引,大大加快了对于标签的过滤查询。TSDB中的元数据的最新状态在落盘时,会以追加(append-only)的形式,写入到meta文件中。meta文件只进行追加操作,即便是元数据的删除,也会以一条记录的形式写入到文件末尾。TSDB也提供了对于元数据的修改操作,如表schema的修改,tag schema的修改以及tag值的修改等。
### 时序数据
每个TSDB在创建时,都会事先分配一定量的内存缓冲区,且内存缓冲区的大小可配可修改。表采集的时序数据,在写入TSDB时,首先以追加的方式写入到分配的内存缓冲区中,同时建立基于时间戳的内存索引,方便快速查询。当内存缓冲区的数据积累到一定的程度时(达到内存缓冲区总大小的1/3),则会触发落盘操作,将缓冲区中的数据持久化到硬盘文件上。时序数据在内存缓冲区中是以行(row)的形式存储的。
而时序数据在写入到TSDB的数据文件时,是以列(column)的形式存储的。TSDB中的数据文件包含多个数据文件组,每个数据文件组中又包含.head、.data和.last三个文件,如(v2f1801.head、v2f1801.data、v2f1801.last)数据文件组。TSDB中的数据文件组是按照时间跨度进行分片的,默认是10天一个文件组,且可通过配置文件及建库选项进行配置。分片的数据文件组又按照编号递增排列,方便快速定位某一时间段的时序数据,高效定位数据文件组。时序数据在TSDB的数据文件中是以块的形式进行列式存储的,每个块中只包含一张表的数据,且数据在一个块中是按照时间顺序递增排列的。在一个数据文件组中,.head文件负责存储数据块的索引及统计信息,如每个块的位置,压缩算法,时间戳范围等。存储在.head文件中一张表的索引信息是按照数据块中存储的数据的时间递增排列的,方便进行折半查找等工作。.head和.last文件是存储真实数据块的文件,若数据块中的数据累计到一定程度,则会写入.data文件中,否则,会写入.last文件中,等待下次落盘时合并数据写入.data文件中,从而大大减少文件中块的个数,避免数据的过度碎片化。
## Query模块
该模块负责整体系统的查询处理。客户端调用该该模块进行SQL语法解析,并将查询或写入请求发送到vnode,同时负责针对超级表的查询进行二阶段的聚合操作。在Vnode端,该模块调用TSDB模块读取系统中存储的数据进行查询处理。Query模块还定义了系统能够支持的全部查询函数,查询函数的实现机制与查询框架无耦合,可以在不修改查询流程的情况下动态增加查询函数。详细的设计请参见《TDengine 2.0查询模块设计》。
## SYNC模块
该模块实现数据的多副本复制,包括vnode与mnode的数据复制,支持异步和同步两种复制方式,以满足meta data与时序数据不同复制的需求。因为它为mnode与vnode共享,系统为mnode副本预留了一个特殊的vgroup ID:1。因此vnode group的ID是从2开始的。
每个vnode/mnode模块实例会有一对应的sync模块实例,他们是一一对应的。详细设计请见<a href="https://www.taosdata.com/cn/documentation20/replica/">TDengine 2.0 数据复制模块设计</a>
## WAL模块
该模块负责将新插入的数据写入write ahead log(WAL), 为vnode, mnode共享。以保证服务器crash或其他故障,能从WAL中恢复数据。
每个vnode/mnode模块实例会有一对应的wal模块实例,是完全一一对应的。WAL的落盘操作由两个参数walLevel, fsync控制。看具体场景,如果要100%保证数据不会丢失,需要将walLevel配置为2,fsync设置为0,每条数据插入请求,都会实时落盘后,才会给应用确认
## HTTP模块
该模块负责处理系统对外的RESTful接口,可以通过配置,由dnode启动或停止。
该模块将接收到的RESTful请求,做了各种合法性检查后,将其变成标准的SQL语句,通过taosc的异步接口,将请求发往整个系统中的任一dnode。收到处理后的结果后,再翻译成HTTP协议,返回给应用。
如果HTTP模块启动,就意味着启动了一个taosc的实例。任一一个dnode都可以启动该模块,以实现对RESTful请求的分布式处理。
## Monitor模块
该模块负责检测一个dnode的运行状态,可以通过配置,由dnode启动或停止。原则上,每个dnode都应该启动一个monitor实例。
Monitor采集TDengine里的关键操作,比如创建、删除、更新账号、表、库等,而且周期性的收集CPU、内存、网络等资源的使用情况(采集周期由系统配置参数monitorInterval控制)。获得这些数据后,monitor模块将采集的数据写入系统的日志库(DB名字由系统配置参数monitorDbName控制)。
Monitor模块使用taosc来将采集的数据写入系统,因此每个monitor实例,都有一个taosc运行实例。
......@@ -31,7 +31,7 @@ install_main_dir="/usr/local/taos"
bin_dir="/usr/local/taos/bin"
# v1.5 jar dir
v15_java_app_dir="/usr/local/lib/taos"
#v15_java_app_dir="/usr/local/lib/taos"
service_config_dir="/etc/systemd/system"
nginx_port=6060
......@@ -79,19 +79,19 @@ osinfo=$(cat /etc/os-release | grep "NAME" | cut -d '"' -f2)
#echo "osinfo: ${osinfo}"
os_type=0
if echo $osinfo | grep -qwi "ubuntu" ; then
echo "This is ubuntu system"
# echo "This is ubuntu system"
os_type=1
elif echo $osinfo | grep -qwi "debian" ; then
echo "This is debian system"
# echo "This is debian system"
os_type=1
elif echo $osinfo | grep -qwi "Kylin" ; then
echo "This is Kylin system"
# echo "This is Kylin system"
os_type=1
elif echo $osinfo | grep -qwi "centos" ; then
echo "This is centos system"
# echo "This is centos system"
os_type=2
elif echo $osinfo | grep -qwi "fedora" ; then
echo "This is fedora system"
# echo "This is fedora system"
os_type=2
else
echo "${osinfo}: This is an officially unverified linux system, If there are any problems with the installation and operation, "
......@@ -135,7 +135,7 @@ do
esac
done
echo "verType=${verType} interactiveFqdn=${interactiveFqdn}"
#echo "verType=${verType} interactiveFqdn=${interactiveFqdn}"
function kill_taosd() {
pid=$(ps -ef | grep "taosd" | grep -v "grep" | awk '{print $2}')
......@@ -189,19 +189,19 @@ function install_bin() {
function install_lib() {
# Remove links
${csudo} rm -f ${lib_link_dir}/libtaos.* || :
${csudo} rm -rf ${v15_java_app_dir} || :
#${csudo} rm -rf ${v15_java_app_dir} || :
${csudo} cp -rf ${script_dir}/driver/* ${install_main_dir}/driver && ${csudo} chmod 777 ${install_main_dir}/driver/*
${csudo} ln -s ${install_main_dir}/driver/libtaos.* ${lib_link_dir}/libtaos.so.1
${csudo} ln -s ${lib_link_dir}/libtaos.so.1 ${lib_link_dir}/libtaos.so
if [ "$verMode" == "cluster" ]; then
# Compatible with version 1.5
${csudo} mkdir -p ${v15_java_app_dir}
${csudo} ln -s ${install_main_dir}/connector/taos-jdbcdriver-1.0.2-dist.jar ${v15_java_app_dir}/JDBCDriver-1.0.2-dist.jar
${csudo} chmod 777 ${v15_java_app_dir} || :
fi
#if [ "$verMode" == "cluster" ]; then
# # Compatible with version 1.5
# ${csudo} mkdir -p ${v15_java_app_dir}
# ${csudo} ln -s ${install_main_dir}/connector/taos-jdbcdriver-1.0.2-dist.jar ${v15_java_app_dir}/JDBCDriver-1.0.2-dist.jar
# ${csudo} chmod 777 ${v15_java_app_dir} || :
#fi
}
function install_header() {
......@@ -223,42 +223,41 @@ function install_config() {
${csudo} cp -f ${script_dir}/cfg/taos.cfg ${install_main_dir}/cfg/taos.cfg.org
${csudo} ln -s ${cfg_install_dir}/taos.cfg ${install_main_dir}/cfg
if [ "$verMode" == "cluster" ]; then
[ ! -z $1 ] && return 0 || : # only install client
[ ! -z $1 ] && return 0 || : # only install client
if ((${update_flag}==1)); then
return 0
fi
if [ "$interactiveFqdn" == "no" ]; then
return 0
fi
#FQDN_FORMAT="(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)"
#FQDN_FORMAT="(:[1-6][0-9][0-9][0-9][0-9]$)"
#PORT_FORMAT="(/[1-6][0-9][0-9][0-9][0-9]?/)"
#FQDN_PATTERN=":[0-9]{1,5}$"
if ((${update_flag}==1)); then
return 0
fi
if [ "$interactiveFqdn" == "no" ]; then
return 0
fi
# first full-qualified domain name (FQDN) for TDengine cluster system
echo
echo -e -n "${GREEN}Enter FQDN:port (like h1.taosdata.com:6030) of an existing TDengine cluster node to join OR leave it blank to build one${NC} :"
read firstEp
while true; do
if [ ! -z "$firstEp" ]; then
# check the format of the firstEp
#if [[ $firstEp == $FQDN_PATTERN ]]; then
# Write the first FQDN to configuration file
${csudo} sed -i -r "s/#*\s*(firstEp\s*).*/\1$firstEp/" ${cfg_install_dir}/taos.cfg
break
#else
# read -p "Please enter the correct FQDN:port: " firstEp
#fi
else
#FQDN_FORMAT="(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)"
#FQDN_FORMAT="(:[1-6][0-9][0-9][0-9][0-9]$)"
#PORT_FORMAT="(/[1-6][0-9][0-9][0-9][0-9]?/)"
#FQDN_PATTERN=":[0-9]{1,5}$"
# first full-qualified domain name (FQDN) for TDengine cluster system
echo
echo -e -n "${GREEN}Enter FQDN:port (like h1.taosdata.com:6030) of an existing TDengine cluster node to join${NC}"
echo
echo -e -n "${GREEN}OR leave it blank to build one${NC}:"
read firstEp
while true; do
if [ ! -z "$firstEp" ]; then
# check the format of the firstEp
#if [[ $firstEp == $FQDN_PATTERN ]]; then
# Write the first FQDN to configuration file
${csudo} sed -i -r "s/#*\s*(firstEp\s*).*/\1$firstEp/" ${cfg_install_dir}/taos.cfg
break
fi
done
fi
#else
# read -p "Please enter the correct FQDN:port: " firstEp
#fi
else
break
fi
done
}
......@@ -563,12 +562,11 @@ function update_TDengine() {
if [ -z $1 ]; then
install_bin
install_service
install_config
install_config
openresty_work=false
if [ "$verMode" == "cluster" ]; then
# Check if openresty is installed
openresty_work=false
# Check if nginx is installed successfully
if type curl &> /dev/null; then
if curl -sSf http://127.0.0.1:${nginx_port} &> /dev/null; then
......@@ -580,8 +578,8 @@ function update_TDengine() {
fi
fi
echo
echo -e "\033[44;32;1mTDengine is updated successfully!${NC}"
#echo
#echo -e "\033[44;32;1mTDengine is updated successfully!${NC}"
echo
echo -e "${GREEN_DARK}To configure TDengine ${NC}: edit /etc/taos/taos.cfg"
if ((${service_mod}==0)); then
......@@ -592,15 +590,12 @@ function update_TDengine() {
echo -e "${GREEN_DARK}To start TDengine ${NC}: ./taosd${NC}"
fi
if [ "$verMode" == "cluster" ]; then
if [ ${openresty_work} = 'true' ]; then
echo -e "${GREEN_DARK}To access TDengine ${NC}: use ${GREEN_UNDERLINE}taos${NC} in shell OR from ${GREEN_UNDERLINE}http://127.0.0.1:${nginx_port}${NC}"
else
echo -e "${GREEN_DARK}To access TDengine ${NC}: use ${GREEN_UNDERLINE}taos${NC} in shell${NC}"
fi
if [ ${openresty_work} = 'true' ]; then
echo -e "${GREEN_DARK}To access TDengine ${NC}: use ${GREEN_UNDERLINE}taos${NC} in shell OR from ${GREEN_UNDERLINE}http://127.0.0.1:${nginx_port}${NC}"
else
echo -e "${GREEN_DARK}To access TDengine ${NC}: use ${GREEN_UNDERLINE}taos${NC} in shell${NC}"
echo -e "${GREEN_DARK}To access TDengine ${NC}: use ${GREEN_UNDERLINE}taos${NC} in shell${NC}"
fi
echo
echo -e "\033[44;32;1mTDengine is updated successfully!${NC}"
else
......@@ -643,8 +638,8 @@ function install_TDengine() {
install_bin
install_service
if [ "$verMode" == "cluster" ]; then
openresty_work=false
openresty_work=false
if [ "$verMode" == "cluster" ]; then
# Check if nginx is installed successfully
if type curl &> /dev/null; then
if curl -sSf http://127.0.0.1:${nginx_port} &> /dev/null; then
......@@ -669,21 +664,20 @@ function install_TDengine() {
echo -e "${GREEN_DARK}To start TDengine ${NC}: ${csudo} service taosd start${NC}"
else
echo -e "${GREEN_DARK}To start TDengine ${NC}: taosd${NC}"
fi
if [ ${openresty_work} = 'true' ]; then
echo -e "${GREEN_DARK}To access TDengine ${NC}: use ${GREEN_UNDERLINE}taos${NC} in shell OR from ${GREEN_UNDERLINE}http://127.0.0.1:${nginx_port}${NC}"
else
echo -e "${GREEN_DARK}To access TDengine ${NC}: use ${GREEN_UNDERLINE}taos${NC} in shell${NC}"
fi
if [ "$verMode" == "cluster" ]; then
if [ ${openresty_work} = 'true' ]; then
echo -e "${GREEN_DARK}To access TDengine ${NC}: use ${GREEN_UNDERLINE}taos${NC} in shell OR from ${GREEN_UNDERLINE}http://127.0.0.1:${nginx_port}${NC}"
else
echo -e "${GREEN_DARK}To access TDengine ${NC}: use ${GREEN_UNDERLINE}taos${NC} in shell${NC}"
fi
else
echo -e "${GREEN_DARK}To access TDengine ${NC}: use ${GREEN_UNDERLINE}taos${NC} in shell${NC}"
if [ ! -z "$firstEp" ]; then
echo
echo -e "${GREEN_DARK}Please run${NC}: taos -h $firstEp${GREEN_DARK} to login into cluster, then${NC}"
echo -e "${GREEN_DARK}execute ${NC}: create dnode 'newDnodeFQDN:port'; ${GREEN_DARK}to add this new node${NC}"
echo
fi
echo
echo -e "${GREEN_DARK}Please run${NC}: taos -h $firstEp ${GREEN_DARK} to login into cluster, then execute ${NC}: create dnode 'newDnodeFQDN:port'; ${GREEN_DARK}in TAOS shell to add this new node into the clsuter${NC}"
echo
echo -e "\033[44;32;1mTDengine is installed successfully!${NC}"
echo
else # Only install client
......
......@@ -106,6 +106,31 @@ function install_config() {
${csudo} mv ${cfg_dir}/taos.cfg ${cfg_dir}/taos.cfg.org
${csudo} ln -s ${cfg_install_dir}/taos.cfg ${cfg_dir}
#FQDN_FORMAT="(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)"
#FQDN_FORMAT="(:[1-6][0-9][0-9][0-9][0-9]$)"
#PORT_FORMAT="(/[1-6][0-9][0-9][0-9][0-9]?/)"
#FQDN_PATTERN=":[0-9]{1,5}$"
# first full-qualified domain name (FQDN) for TDengine cluster system
echo
echo -e -n "${GREEN}Enter FQDN:port (like h1.taosdata.com:6030) of an existing TDengine cluster node to join${NC}"
echo
echo -e -n "${GREEN}OR leave it blank to build one${NC}:"
read firstEp
while true; do
if [ ! -z "$firstEp" ]; then
# check the format of the firstEp
#if [[ $firstEp == $FQDN_PATTERN ]]; then
# Write the first FQDN to configuration file
${csudo} sed -i -r "s/#*\s*(firstEp\s*).*/\1$firstEp/" ${cfg_install_dir}/taos.cfg
break
#else
# read -p "Please enter the correct FQDN:port: " firstEp
#fi
else
break
fi
done
}
function clean_service_on_sysvinit() {
......@@ -227,8 +252,8 @@ function install_TDengine() {
install_config
# Ask if to start the service
echo
echo -e "\033[44;32;1mTDengine is installed successfully!${NC}"
#echo
#echo -e "\033[44;32;1mTDengine is installed successfully!${NC}"
echo
echo -e "${GREEN_DARK}To configure TDengine ${NC}: edit /etc/taos/taos.cfg"
if ((${service_mod}==0)); then
......@@ -241,7 +266,13 @@ function install_TDengine() {
fi
echo -e "${GREEN_DARK}To access TDengine ${NC}: use ${GREEN_UNDERLINE}taos${NC} in shell${NC}"
if [ ! -z "$firstEp" ]; then
echo
echo -e "${GREEN_DARK}Please run${NC}: taos -h $firstEp${GREEN_DARK} to login into cluster, then${NC}"
echo -e "${GREEN_DARK}execute ${NC}: create dnode 'newDnodeFQDN:port'; ${GREEN_DARK}to add this new node${NC}"
echo
fi
echo
echo -e "\033[44;32;1mTDengine is installed successfully!${NC}"
}
......
......@@ -14,10 +14,10 @@
*/
#define _DEFAULT_SOURCE
#include "os.h"
#include "tutil.h"
#include "tbalance.h"
#include "tsync.h"
#include "ttime.h"
#include "ttimer.h"
#include "tglobal.h"
#include "tdataformat.h"
......
......@@ -18,7 +18,6 @@
#include "tlog.h"
#include "tscUtil.h"
#include "tsclient.h"
#include "ttime.h"
#include "com_taosdata_jdbc_TSDBJNIConnector.h"
......
......@@ -27,7 +27,6 @@
#include "tscSubquery.h"
#include "tscompression.h"
#include "tsqlfunction.h"
#include "ttime.h"
#include "tutil.h"
#define GET_INPUT_CHAR(x) (((char *)((x)->aInputElemBuf)) + ((x)->startOffset) * ((x)->inputBytes))
......@@ -2108,7 +2107,7 @@ static void copyTopBotRes(SQLFunctionCtx *pCtx, int32_t type) {
}
}
tfree(pData);
taosTFree(pData);
}
/*
......
......@@ -326,7 +326,7 @@ static void tscProcessServerVer(SSqlObj *pSql) {
STR_WITH_SIZE_TO_VARSTR(vx, v, t);
tscSetLocalQueryResult(pSql, vx, pExpr->aliasName, pExpr->resType, pExpr->resBytes);
tfree(vx);
taosTFree(vx);
}
static void tscProcessClientVer(SSqlObj *pSql) {
......@@ -342,7 +342,7 @@ static void tscProcessClientVer(SSqlObj *pSql) {
STR_WITH_SIZE_TO_VARSTR(v, version, t);
tscSetLocalQueryResult(pSql, v, pExpr->aliasName, pExpr->resType, pExpr->resBytes);
tfree(v);
taosTFree(v);
}
static void tscProcessServStatus(SSqlObj *pSql) {
......
......@@ -230,7 +230,7 @@ void tscCreateLocalReducer(tExtMemBuffer **pMemBuffer, int32_t numOfBuffer, tOrd
if (ds == NULL) {
tscError("%p failed to create merge structure", pSql);
pRes->code = TSDB_CODE_TSC_OUT_OF_MEMORY;
tfree(pReducer);
taosTFree(pReducer);
return;
}
......@@ -257,7 +257,7 @@ void tscCreateLocalReducer(tExtMemBuffer **pMemBuffer, int32_t numOfBuffer, tOrd
if (ds->filePage.num == 0) { // no data in this flush, the index does not increase
tscDebug("%p flush data is empty, ignore %d flush record", pSql, idx);
tfree(ds);
taosTFree(ds);
continue;
}
......@@ -267,7 +267,7 @@ void tscCreateLocalReducer(tExtMemBuffer **pMemBuffer, int32_t numOfBuffer, tOrd
// no data actually, no need to merge result.
if (idx == 0) {
tfree(pReducer);
taosTFree(pReducer);
return;
}
......@@ -275,7 +275,7 @@ void tscCreateLocalReducer(tExtMemBuffer **pMemBuffer, int32_t numOfBuffer, tOrd
SCompareParam *param = malloc(sizeof(SCompareParam));
if (param == NULL) {
tfree(pReducer);
taosTFree(pReducer);
return;
}
param->pLocalData = pReducer->pLocalDataSrc;
......@@ -288,8 +288,8 @@ void tscCreateLocalReducer(tExtMemBuffer **pMemBuffer, int32_t numOfBuffer, tOrd
pRes->code = tLoserTreeCreate(&pReducer->pLoserTree, pReducer->numOfBuffer, param, treeComparator);
if (pReducer->pLoserTree == NULL || pRes->code != 0) {
tfree(param);
tfree(pReducer);
taosTFree(param);
taosTFree(pReducer);
return;
}
......@@ -332,14 +332,14 @@ void tscCreateLocalReducer(tExtMemBuffer **pMemBuffer, int32_t numOfBuffer, tOrd
if (pReducer->pTempBuffer == NULL || pReducer->discardData == NULL || pReducer->pResultBuf == NULL ||
/*pReducer->pBufForInterpo == NULL || */pReducer->pFinalRes == NULL || pReducer->prevRowOfInput == NULL) {
tfree(pReducer->pTempBuffer);
tfree(pReducer->discardData);
tfree(pReducer->pResultBuf);
tfree(pReducer->pFinalRes);
tfree(pReducer->prevRowOfInput);
tfree(pReducer->pLoserTree);
tfree(param);
tfree(pReducer);
taosTFree(pReducer->pTempBuffer);
taosTFree(pReducer->discardData);
taosTFree(pReducer->pResultBuf);
taosTFree(pReducer->pFinalRes);
taosTFree(pReducer->prevRowOfInput);
taosTFree(pReducer->pLoserTree);
taosTFree(param);
taosTFree(pReducer);
pRes->code = TSDB_CODE_TSC_OUT_OF_MEMORY;
return;
}
......@@ -516,38 +516,38 @@ void tscDestroyLocalReducer(SSqlObj *pSql) {
tVariantDestroy(&pCtx->tag);
if (pCtx->tagInfo.pTagCtxList != NULL) {
tfree(pCtx->tagInfo.pTagCtxList);
taosTFree(pCtx->tagInfo.pTagCtxList);
}
}
tfree(pLocalReducer->pCtx);
taosTFree(pLocalReducer->pCtx);
}
tfree(pLocalReducer->prevRowOfInput);
taosTFree(pLocalReducer->prevRowOfInput);
tfree(pLocalReducer->pTempBuffer);
tfree(pLocalReducer->pResultBuf);
taosTFree(pLocalReducer->pTempBuffer);
taosTFree(pLocalReducer->pResultBuf);
if (pLocalReducer->pResInfo != NULL) {
for (int32_t i = 0; i < pQueryInfo->fieldsInfo.numOfOutput; ++i) {
tfree(pLocalReducer->pResInfo[i].interResultBuf);
taosTFree(pLocalReducer->pResInfo[i].interResultBuf);
}
tfree(pLocalReducer->pResInfo);
taosTFree(pLocalReducer->pResInfo);
}
if (pLocalReducer->pLoserTree) {
tfree(pLocalReducer->pLoserTree->param);
tfree(pLocalReducer->pLoserTree);
taosTFree(pLocalReducer->pLoserTree->param);
taosTFree(pLocalReducer->pLoserTree);
}
tfree(pLocalReducer->pFinalRes);
tfree(pLocalReducer->discardData);
taosTFree(pLocalReducer->pFinalRes);
taosTFree(pLocalReducer->discardData);
tscLocalReducerEnvDestroy(pLocalReducer->pExtMemBuffer, pLocalReducer->pDesc, pLocalReducer->resColModel,
pLocalReducer->numOfVnode);
for (int32_t i = 0; i < pLocalReducer->numOfBuffer; ++i) {
tfree(pLocalReducer->pLocalDataSrc[i]);
taosTFree(pLocalReducer->pLocalDataSrc[i]);
}
pLocalReducer->numOfBuffer = 0;
......@@ -593,7 +593,7 @@ static int32_t createOrderDescriptor(tOrderDescriptor **pOrderDesc, SSqlCmd *pCm
}
*pOrderDesc = tOrderDesCreate(orderIdx, numOfGroupByCols, pModel, pQueryInfo->order.order);
tfree(orderIdx);
taosTFree(orderIdx);
if (*pOrderDesc == NULL) {
return TSDB_CODE_TSC_OUT_OF_MEMORY;
......@@ -705,7 +705,7 @@ int32_t tscLocalReducerEnvCreate(SSqlObj *pSql, tExtMemBuffer ***pMemBuffer, tOr
if (createOrderDescriptor(pOrderDesc, pCmd, pModel) != TSDB_CODE_SUCCESS) {
pRes->code = TSDB_CODE_TSC_OUT_OF_MEMORY;
tfree(pSchema);
taosTFree(pSchema);
return pRes->code;
}
......@@ -746,7 +746,7 @@ int32_t tscLocalReducerEnvCreate(SSqlObj *pSql, tExtMemBuffer ***pMemBuffer, tOr
}
*pFinalModel = createColumnModel(pSchema, size, capacity);
tfree(pSchema);
taosTFree(pSchema);
return TSDB_CODE_SUCCESS;
}
......@@ -765,7 +765,7 @@ void tscLocalReducerEnvDestroy(tExtMemBuffer **pMemBuffer, tOrderDescriptor *pDe
pMemBuffer[i] = destoryExtMemBuffer(pMemBuffer[i]);
}
tfree(pMemBuffer);
taosTFree(pMemBuffer);
}
/**
......@@ -1036,10 +1036,10 @@ static void doFillResult(SSqlObj *pSql, SLocalReducer *pLocalReducer, bool doneO
pFinalDataPage->num = 0;
for (int32_t i = 0; i < pQueryInfo->fieldsInfo.numOfOutput; ++i) {
tfree(pResPages[i]);
taosTFree(pResPages[i]);
}
tfree(pResPages);
taosTFree(pResPages);
}
static void savePreviousRow(SLocalReducer *pLocalReducer, tFilePage *tmpBuffer) {
......
......@@ -30,7 +30,6 @@
#include "tscLog.h"
#include "tscSubquery.h"
#include "tstoken.h"
#include "ttime.h"
#include "tdataformat.h"
......@@ -1388,7 +1387,7 @@ static void parseFileSendDataBlock(void *param, TAOS_RES *tres, int code) {
assert(taos_errno(pSql) == code);
taos_free_result(pSql);
tfree(pSupporter);
taosTFree(pSupporter);
fclose(fp);
pParentSql->res.code = code;
......@@ -1453,7 +1452,7 @@ static void parseFileSendDataBlock(void *param, TAOS_RES *tres, int code) {
}
}
tfree(tokenBuf);
taosTFree(tokenBuf);
free(line);
if (count > 0) {
......@@ -1466,7 +1465,7 @@ static void parseFileSendDataBlock(void *param, TAOS_RES *tres, int code) {
} else {
taos_free_result(pSql);
tfree(pSupporter);
taosTFree(pSupporter);
fclose(fp);
pParentSql->fp = pParentSql->fetchFp;
......@@ -1496,7 +1495,7 @@ void tscProcessMultiVnodesImportFromFile(SSqlObj *pSql) {
pSql->res.code = TAOS_SYSTEM_ERROR(errno);
tscError("%p failed to open file %s to load data from file, code:%s", pSql, pCmd->payload, tstrerror(pSql->res.code));
tfree(pSupporter)
taosTFree(pSupporter)
tscQueueAsyncRes(pSql);
return;
......
......@@ -613,7 +613,7 @@ int taos_stmt_execute(TAOS_STMT* stmt) {
if (sql == NULL) {
ret = TSDB_CODE_TSC_OUT_OF_MEMORY;
} else {
tfree(pStmt->pSql->sqlstr);
taosTFree(pStmt->pSql->sqlstr);
pStmt->pSql->sqlstr = sql;
SSqlObj* pSql = taos_query((TAOS*)pStmt->taos, pStmt->pSql->sqlstr);
ret = taos_errno(pSql);
......
......@@ -16,7 +16,6 @@
#include "os.h"
#include "tscLog.h"
#include "tsclient.h"
#include "ttime.h"
#include "ttimer.h"
#include "tutil.h"
#include "taosmsg.h"
......
......@@ -29,7 +29,6 @@
#include "tsclient.h"
#include "tstoken.h"
#include "tstrbuild.h"
#include "ttime.h"
#include "ttokendef.h"
#define DEFAULT_PRIMARY_TIMESTAMP_COL_NAME "_c0"
......@@ -737,7 +736,7 @@ int32_t tscSetTableFullName(STableMetaInfo* pTableMetaInfo, SSQLToken* pzTableNa
assert(pTableMetaInfo->pTableMeta == NULL);
}
tfree(oldName);
taosTFree(oldName);
return TSDB_CODE_SUCCESS;
}
......@@ -3648,7 +3647,7 @@ static int32_t setTableCondForSTableQuery(SSqlCmd* pCmd, SQueryInfo* pQueryInfo,
int32_t ret = setObjFullName(idBuf, account, &dbToken, &t, &xlen);
if (ret != TSDB_CODE_SUCCESS) {
taosStringBuilderDestroy(&sb1);
tfree(segments);
taosTFree(segments);
invalidSqlErrMsg(tscGetErrorMsgPayload(pCmd), msg);
return ret;
......@@ -3661,7 +3660,7 @@ static int32_t setTableCondForSTableQuery(SSqlCmd* pCmd, SQueryInfo* pQueryInfo,
pQueryInfo->tagCond.tbnameCond.cond = strdup(str);
taosStringBuilderDestroy(&sb1);
tfree(segments);
taosTFree(segments);
return TSDB_CODE_SUCCESS;
}
......
......@@ -23,7 +23,6 @@
#include "tscUtil.h"
#include "tschemautil.h"
#include "tsclient.h"
#include "ttime.h"
#include "ttimer.h"
#include "tutil.h"
#include "tlockfree.h"
......@@ -196,7 +195,7 @@ void tscProcessActivityTimer(void *handle, void *tmrId) {
pSql->cmd.command = TSDB_SQL_HB;
if (TSDB_CODE_SUCCESS != tscAllocPayload(&(pSql->cmd), TSDB_DEFAULT_PAYLOAD_SIZE)) {
tfree(pSql);
taosTFree(pSql);
return;
}
......@@ -1538,7 +1537,7 @@ int tscBuildTableMetaMsg(SSqlObj *pSql, SSqlInfo *pInfo) {
pCmd->payloadLen = pMsg - (char*)pInfoMsg;
pCmd->msgType = TSDB_MSG_TYPE_CM_TABLE_META;
tfree(tmpData);
taosTFree(tmpData);
assert(msgLen + minMsgSize() <= pCmd->allocSize);
return TSDB_CODE_SUCCESS;
......@@ -1572,7 +1571,7 @@ int tscBuildMultiMeterMetaMsg(SSqlObj *pSql, SSqlInfo *pInfo) {
memcpy(pInfoMsg->tableIds, tmpData, pCmd->payloadLen);
}
tfree(tmpData);
taosTFree(tmpData);
pCmd->payloadLen += sizeof(SMgmtHead) + sizeof(SCMMultiTableInfoMsg);
pCmd->msgType = TSDB_MSG_TYPE_CM_TABLES_META;
......@@ -1962,7 +1961,7 @@ int tscProcessShowRsp(SSqlObj *pSql) {
pCmd->numOfCols = pQueryInfo->fieldsInfo.numOfOutput;
tscFieldInfoUpdateOffset(pQueryInfo);
tfree(pTableMeta);
taosTFree(pTableMeta);
return 0;
}
......
......@@ -474,7 +474,7 @@ int taos_fetch_block(TAOS_RES *res, TAOS_ROW *rows) {
pRes->rspType = 0;
pSql->numOfSubs = 0;
tfree(pSql->pSubs);
taosTFree(pSql->pSubs);
assert(pSql->fp == NULL);
......@@ -753,7 +753,7 @@ int taos_validate_sql(TAOS *taos, const char *sql) {
if (sqlLen > tsMaxSQLStringLen) {
tscError("%p sql too long", pSql);
pRes->code = TSDB_CODE_TSC_INVALID_SQL;
tfree(pSql);
taosTFree(pSql);
return pRes->code;
}
......@@ -762,7 +762,7 @@ int taos_validate_sql(TAOS *taos, const char *sql) {
pRes->code = TSDB_CODE_TSC_OUT_OF_MEMORY;
tscError("%p failed to malloc sql string buffer", pSql);
tscDebug("%p Valid SQL result:%d, %s pObj:%p", pSql, pRes->code, taos_errstr(taos), pObj);
tfree(pSql);
taosTFree(pSql);
return pRes->code;
}
......@@ -896,7 +896,7 @@ int taos_load_table_info(TAOS *taos, const char *tableNameList) {
if (tblListLen > MAX_TABLE_NAME_LENGTH) {
tscError("%p tableNameList too long, length:%d, maximum allowed:%d", pSql, tblListLen, MAX_TABLE_NAME_LENGTH);
pRes->code = TSDB_CODE_TSC_INVALID_SQL;
tfree(pSql);
taosTFree(pSql);
return pRes->code;
}
......@@ -904,7 +904,7 @@ int taos_load_table_info(TAOS *taos, const char *tableNameList) {
if (str == NULL) {
pRes->code = TSDB_CODE_TSC_OUT_OF_MEMORY;
tscError("%p failed to malloc sql string buffer", pSql);
tfree(pSql);
taosTFree(pSql);
return pRes->code;
}
......
......@@ -21,7 +21,6 @@
#include "tsched.h"
#include "tcache.h"
#include "tsclient.h"
#include "ttime.h"
#include "ttimer.h"
#include "tutil.h"
......@@ -156,7 +155,7 @@ static void tscProcessStreamQueryCallback(void *param, TAOS_RES *tres, int numOf
STableMetaInfo* pTableMetaInfo = tscGetTableMetaInfoFromCmd(&pStream->pSql->cmd, 0, 0);
taosCacheRelease(tscCacheHandle, (void**)&(pTableMetaInfo->pTableMeta), true);
tfree(pTableMetaInfo->vgroupList);
taosTFree(pTableMetaInfo->vgroupList);
tscSetRetryTimer(pStream, pStream->pSql, retryDelay);
return;
......@@ -260,9 +259,9 @@ static void tscProcessStreamRetrieveResult(void *param, TAOS_RES *res, int numOf
taosCacheRelease(tscCacheHandle, (void**)&(pTableMetaInfo->pTableMeta), false);
tscFreeSqlResult(pSql);
tfree(pSql->pSubs);
taosTFree(pSql->pSubs);
pSql->numOfSubs = 0;
tfree(pTableMetaInfo->vgroupList);
taosTFree(pTableMetaInfo->vgroupList);
tscSetNextLaunchTimer(pStream, pSql);
}
}
......@@ -592,6 +591,6 @@ void taos_close_stream(TAOS_STREAM *handle) {
tscFreeSqlObj(pSql);
pStream->pSql = NULL;
tfree(pStream);
taosTFree(pStream);
}
}
......@@ -18,7 +18,6 @@
#include "trpc.h"
#include "tsclient.h"
#include "tsocket.h"
#include "ttime.h"
#include "ttimer.h"
#include "tutil.h"
#include "tscLog.h"
......
......@@ -183,7 +183,7 @@ SJoinSupporter* tscCreateJoinSupporter(SSqlObj* pSql, SSubqueryState* pState, in
pSupporter->uid = pTableMetaInfo->pTableMeta->id.uid;
assert (pSupporter->uid != 0);
getTmpfilePath("join-", pSupporter->path);
taosGetTmpfilePath("join-", pSupporter->path);
pSupporter->f = fopen(pSupporter->path, "w");
// todo handle error
......@@ -215,7 +215,7 @@ static void tscDestroyJoinSupporter(SJoinSupporter* pSupporter) {
pSupporter->f = NULL;
}
tfree(pSupporter->pIdTagList);
taosTFree(pSupporter->pIdTagList);
tscTagCondRelease(&pSupporter->tagCond);
free(pSupporter);
}
......@@ -407,7 +407,7 @@ void freeJoinSubqueryObj(SSqlObj* pSql) {
}
}
tfree(pState);
taosTFree(pState);
pSql->numOfSubs = 0;
}
......@@ -773,7 +773,7 @@ static void tsCompRetrieveCallback(void* param, TAOS_RES* tres, int32_t numOfRow
// continue to retrieve ts-comp data from vnode
if (!pRes->completed) {
getTmpfilePath("ts-join", pSupporter->path);
taosGetTmpfilePath("ts-join", pSupporter->path);
pSupporter->f = fopen(pSupporter->path, "w");
pRes->row = pRes->numOfRows;
......@@ -797,7 +797,7 @@ static void tsCompRetrieveCallback(void* param, TAOS_RES* tres, int32_t numOfRow
tscResetForNextRetrieve(&pSql->res);
assert(pSupporter->f == NULL);
getTmpfilePath("ts-join", pSupporter->path);
taosGetTmpfilePath("ts-join", pSupporter->path);
// TODO check for failure
pSupporter->f = fopen(pSupporter->path, "w");
......@@ -1317,12 +1317,12 @@ static void doCleanupSubqueries(SSqlObj *pSql, int32_t numOfSubs, SSubqueryState
SRetrieveSupport* pSupport = pSub->param;
tfree(pSupport->localBuffer);
taosTFree(pSupport->localBuffer);
pthread_mutex_unlock(&pSupport->queryMutex);
pthread_mutex_destroy(&pSupport->queryMutex);
tfree(pSupport);
taosTFree(pSupport);
tscFreeSqlObj(pSub);
}
......@@ -1358,7 +1358,7 @@ int32_t tscHandleMasterSTableQuery(SSqlObj *pSql) {
if (ret != 0) {
pRes->code = TSDB_CODE_TSC_OUT_OF_MEMORY;
tscQueueAsyncRes(pSql);
tfree(pMemoryBuf);
taosTFree(pMemoryBuf);
return ret;
}
......@@ -1386,7 +1386,7 @@ int32_t tscHandleMasterSTableQuery(SSqlObj *pSql) {
trs->localBuffer = (tFilePage *)calloc(1, nBufferSize + sizeof(tFilePage));
if (trs->localBuffer == NULL) {
tscError("%p failed to malloc buffer for local buffer, orderOfSub:%d, reason:%s", pSql, i, strerror(errno));
tfree(trs);
taosTFree(trs);
break;
}
......@@ -1404,8 +1404,8 @@ int32_t tscHandleMasterSTableQuery(SSqlObj *pSql) {
SSqlObj *pNew = tscCreateSqlObjForSubquery(pSql, trs, NULL);
if (pNew == NULL) {
tscError("%p failed to malloc buffer for subObj, orderOfSub:%d, reason:%s", pSql, i, strerror(errno));
tfree(trs->localBuffer);
tfree(trs);
taosTFree(trs->localBuffer);
taosTFree(trs);
break;
}
......@@ -1450,12 +1450,12 @@ static void tscFreeSubSqlObj(SRetrieveSupport *trsupport, SSqlObj *pSql) {
taos_free_result(pSql);
tfree(trsupport->localBuffer);
taosTFree(trsupport->localBuffer);
pthread_mutex_unlock(&trsupport->queryMutex);
pthread_mutex_destroy(&trsupport->queryMutex);
tfree(trsupport);
taosTFree(trsupport);
}
static void tscRetrieveFromDnodeCallBack(void *param, TAOS_RES *tres, int numOfRows);
......@@ -1572,7 +1572,7 @@ void tscHandleSubqueryError(SRetrieveSupport *trsupport, SSqlObj *pSql, int numO
tscLocalReducerEnvDestroy(trsupport->pExtMemBuffer, trsupport->pOrderDescriptor, trsupport->pFinalColModel,
pState->numOfTotal);
tfree(trsupport->pState);
taosTFree(trsupport->pState);
tscFreeSubSqlObj(trsupport, pSql);
// in case of second stage join subquery, invoke its callback function instead of regular QueueAsyncRes
......@@ -1651,7 +1651,7 @@ static void tscAllDataRetrievedFromDnode(SRetrieveSupport *trsupport, SSqlObj* p
pParentSql->res.row = 0;
// only free once
tfree(trsupport->pState);
taosTFree(trsupport->pState);
tscFreeSubSqlObj(trsupport, pSql);
// set the command flag must be after the semaphore been correctly set.
......@@ -1855,7 +1855,7 @@ static void multiVnodeInsertFinalize(void* param, TAOS_RES* tres, int numOfRows)
}
taos_free_result(tres);
tfree(pSupporter);
taosTFree(pSupporter);
if (atomic_sub_fetch_32(&pState->numOfRemain, 1) > 0) {
return;
......@@ -1864,7 +1864,7 @@ static void multiVnodeInsertFinalize(void* param, TAOS_RES* tres, int numOfRows)
tscDebug("%p Async insertion completed, total inserted:%" PRId64, pParentObj, pParentObj->res.numOfRows);
// release data block data
tfree(pState);
taosTFree(pState);
// restore user defined fp
pParentObj->fp = pParentObj->fetchFp;
......@@ -1968,11 +1968,11 @@ int32_t tscHandleMultivnodeInsert(SSqlObj *pSql) {
_error:
for(int32_t j = 0; j < numOfSub; ++j) {
tfree(pSql->pSubs[j]->param);
taosTFree(pSql->pSubs[j]->param);
taos_free_result(pSql->pSubs[j]);
}
tfree(pState);
taosTFree(pState);
return TSDB_CODE_TSC_OUT_OF_MEMORY;
}
......@@ -2143,7 +2143,7 @@ void **doSetResultRowData(SSqlObj *pSql, bool finalResult) {
assert(pRes->row >= 0 && pRes->row <= pRes->numOfRows);
if (pRes->row >= pRes->numOfRows) { // all the results has returned to invoker
tfree(pRes->tsrow);
taosTFree(pRes->tsrow);
return pRes->tsrow;
}
......
......@@ -18,7 +18,6 @@
#include "tcache.h"
#include "trpc.h"
#include "tsystem.h"
#include "ttime.h"
#include "ttimer.h"
#include "tutil.h"
#include "tsched.h"
......
......@@ -245,7 +245,7 @@ void tscClearInterpInfo(SQueryInfo* pQueryInfo) {
}
pQueryInfo->fillType = TSDB_FILL_NONE;
tfree(pQueryInfo->fillVal);
taosTFree(pQueryInfo->fillVal);
}
int32_t tscCreateResPointerInfo(SSqlRes* pRes, SQueryInfo* pQueryInfo) {
......@@ -259,9 +259,9 @@ int32_t tscCreateResPointerInfo(SSqlRes* pRes, SQueryInfo* pQueryInfo) {
// not enough memory
if (pRes->tsrow == NULL || (pRes->buffer == NULL && pRes->numOfCols > 0)) {
tfree(pRes->tsrow);
tfree(pRes->buffer);
tfree(pRes->length);
taosTFree(pRes->tsrow);
taosTFree(pRes->buffer);
taosTFree(pRes->length);
pRes->code = TSDB_CODE_TSC_OUT_OF_MEMORY;
return pRes->code;
......@@ -274,23 +274,23 @@ int32_t tscCreateResPointerInfo(SSqlRes* pRes, SQueryInfo* pQueryInfo) {
void tscDestroyResPointerInfo(SSqlRes* pRes) {
if (pRes->buffer != NULL) { // free all buffers containing the multibyte string
for (int i = 0; i < pRes->numOfCols; i++) {
tfree(pRes->buffer[i]);
taosTFree(pRes->buffer[i]);
}
pRes->numOfCols = 0;
}
tfree(pRes->pRsp);
tfree(pRes->tsrow);
tfree(pRes->length);
taosTFree(pRes->pRsp);
taosTFree(pRes->tsrow);
taosTFree(pRes->length);
tfree(pRes->pGroupRec);
tfree(pRes->pColumnIndex);
tfree(pRes->buffer);
taosTFree(pRes->pGroupRec);
taosTFree(pRes->pColumnIndex);
taosTFree(pRes->buffer);
if (pRes->pArithSup != NULL) {
tfree(pRes->pArithSup->data);
tfree(pRes->pArithSup);
taosTFree(pRes->pArithSup->data);
taosTFree(pRes->pArithSup);
}
pRes->data = NULL; // pRes->data points to the buffer of pRsp, no need to free
......@@ -307,11 +307,11 @@ static void tscFreeQueryInfo(SSqlCmd* pCmd) {
freeQueryInfoImpl(pQueryInfo);
clearAllTableMetaInfo(pQueryInfo, (const char*)addr, false);
tfree(pQueryInfo);
taosTFree(pQueryInfo);
}
pCmd->numOfClause = 0;
tfree(pCmd->pQueryInfo);
taosTFree(pCmd->pQueryInfo);
}
void tscResetSqlCmdObj(SSqlCmd* pCmd) {
......@@ -357,13 +357,13 @@ void tscPartiallyFreeSqlObj(SSqlObj* pSql) {
// pSql->sqlstr will be used by tscBuildQueryStreamDesc
if (pObj->signature == pObj) {
//pthread_mutex_lock(&pObj->mutex);
tfree(pSql->sqlstr);
taosTFree(pSql->sqlstr);
//pthread_mutex_unlock(&pObj->mutex);
}
tscFreeSqlResult(pSql);
tfree(pSql->pSubs);
taosTFree(pSql->pSubs);
pSql->numOfSubs = 0;
tscResetSqlCmdObj(pCmd);
......@@ -383,10 +383,10 @@ void tscFreeSqlObj(SSqlObj* pSql) {
SSqlCmd* pCmd = &pSql->cmd;
memset(pCmd->payload, 0, (size_t)pCmd->allocSize);
tfree(pCmd->payload);
taosTFree(pCmd->payload);
pCmd->allocSize = 0;
tfree(pSql->sqlstr);
taosTFree(pSql->sqlstr);
sem_destroy(&pSql->rspSem);
free(pSql);
}
......@@ -396,12 +396,12 @@ void tscDestroyDataBlock(STableDataBlocks* pDataBlock) {
return;
}
tfree(pDataBlock->pData);
tfree(pDataBlock->params);
taosTFree(pDataBlock->pData);
taosTFree(pDataBlock->params);
// free the refcount for metermeta
taosCacheRelease(tscCacheHandle, (void**)&(pDataBlock->pTableMeta), false);
tfree(pDataBlock);
taosTFree(pDataBlock);
}
SParamInfo* tscAddParamToDataBlock(STableDataBlocks* pDataBlock, char type, uint8_t timePrec, short bytes,
......@@ -679,7 +679,7 @@ int32_t tscMergeTableDataBlocks(SSqlObj* pSql, SArray* pTableDataBlockList) {
taosHashCleanup(pVnodeDataBlockHashList);
tscDestroyBlockArrayList(pVnodeDataBlockList);
tfree(dataBuf->pData);
taosTFree(dataBuf->pData);
return TSDB_CODE_TSC_OUT_OF_MEMORY;
}
......@@ -735,7 +735,7 @@ void tscCloseTscObj(STscObj* pObj) {
}
tscDebug("%p DB connection is closed, dnodeConn:%p", pObj, pObj->pDnodeConn);
tfree(pObj);
taosTFree(pObj);
}
bool tscIsInsertData(char* sqlstr) {
......@@ -916,7 +916,7 @@ void tscFieldInfoClear(SFieldInfo* pFieldInfo) {
if (pInfo->pArithExprInfo != NULL) {
tExprTreeDestroy(&pInfo->pArithExprInfo->pExpr, NULL);
tfree(pInfo->pArithExprInfo);
taosTFree(pInfo->pArithExprInfo);
}
}
......@@ -1029,7 +1029,7 @@ void* sqlExprDestroy(SSqlExpr* pExpr) {
tVariantDestroy(&pExpr->param[i]);
}
tfree(pExpr);
taosTFree(pExpr);
return NULL;
}
......@@ -1116,11 +1116,11 @@ SColumn* tscColumnListInsert(SArray* pColumnList, SColumnIndex* pColIndex) {
static void destroyFilterInfo(SColumnFilterInfo* pFilterInfo, int32_t numOfFilters) {
for(int32_t i = 0; i < numOfFilters; ++i) {
if (pFilterInfo[i].filterstr) {
tfree(pFilterInfo[i].pz);
taosTFree(pFilterInfo[i].pz);
}
}
tfree(pFilterInfo);
taosTFree(pFilterInfo);
}
SColumn* tscColumnClone(const SColumn* src) {
......@@ -1351,7 +1351,7 @@ void tscTagCondRelease(STagCond* pTagCond) {
size_t s = taosArrayGetSize(pTagCond->pCond);
for (int32_t i = 0; i < s; ++i) {
SCond* p = taosArrayGet(pTagCond->pCond, i);
tfree(p->cond);
taosTFree(p->cond);
}
taosArrayDestroy(pTagCond->pCond);
......@@ -1546,7 +1546,7 @@ static void freeQueryInfoImpl(SQueryInfo* pQueryInfo) {
pQueryInfo->tsBuf = tsBufDestroy(pQueryInfo->tsBuf);
tfree(pQueryInfo->fillVal);
taosTFree(pQueryInfo->fillVal);
}
void tscClearSubqueryInfo(SSqlCmd* pCmd) {
......@@ -1566,7 +1566,7 @@ void clearAllTableMetaInfo(SQueryInfo* pQueryInfo, const char* address, bool rem
free(pTableMetaInfo);
}
tfree(pQueryInfo->pTableMetaInfo);
taosTFree(pQueryInfo->pTableMetaInfo);
}
STableMetaInfo* tscAddTableMetaInfo(SQueryInfo* pQueryInfo, const char* name, STableMeta* pTableMeta,
......@@ -1613,7 +1613,7 @@ void tscClearTableMetaInfo(STableMetaInfo* pTableMetaInfo, bool removeFromCache)
}
taosCacheRelease(tscCacheHandle, (void**)&(pTableMetaInfo->pTableMeta), removeFromCache);
tfree(pTableMetaInfo->vgroupList);
taosTFree(pTableMetaInfo->vgroupList);
tscColumnListDestroy(pTableMetaInfo->tagColList);
pTableMetaInfo->tagColList = NULL;
......@@ -2084,7 +2084,7 @@ void tscTryQueryNextClause(SSqlObj* pSql, __async_cb_func_t fp) {
pRes->numOfTotal = num;
tfree(pSql->pSubs);
taosTFree(pSql->pSubs);
pSql->numOfSubs = 0;
pSql->fp = fp;
......
#include "os.h"
#include <gtest/gtest.h>
#include <cassert>
#include <iostream>
#include "taos.h"
#include "tstoken.h"
#include "ttime.h"
#include "tutil.h"
int main(int argc, char** argv) {
......
......@@ -80,7 +80,7 @@ typedef struct {
#define schemaFLen(s) ((s)->flen)
#define schemaVLen(s) ((s)->vlen)
#define schemaColAt(s, i) ((s)->columns + i)
#define tdFreeSchema(s) tfree((s))
#define tdFreeSchema(s) taosTFree((s))
STSchema *tdDupSchema(STSchema *pSchema);
int tdEncodeSchema(void **buf, STSchema *pSchema);
......@@ -284,7 +284,7 @@ typedef struct {
#define kvRowCpy(dst, r) memcpy((dst), (r), kvRowLen(r))
#define kvRowColVal(r, colIdx) POINTER_SHIFT(kvRowValues(r), (colIdx)->offset)
#define kvRowColIdxAt(r, i) (kvRowColIdx(r) + (i))
#define kvRowFree(r) tfree(r)
#define kvRowFree(r) taosTFree(r)
#define kvRowEnd(r) POINTER_SHIFT(r, kvRowLen(r))
SKVRow tdKVRowDup(SKVRow row);
......
......@@ -93,7 +93,7 @@ int tdInitTSchemaBuilder(STSchemaBuilder *pBuilder, int32_t version) {
void tdDestroyTSchemaBuilder(STSchemaBuilder *pBuilder) {
if (pBuilder) {
tfree(pBuilder->columns);
taosTFree(pBuilder->columns);
}
}
......@@ -361,8 +361,8 @@ int tdInitDataCols(SDataCols *pCols, STSchema *pSchema) {
void tdFreeDataCols(SDataCols *pCols) {
if (pCols) {
tfree(pCols->buf);
tfree(pCols->cols);
taosTFree(pCols->buf);
taosTFree(pCols->cols);
free(pCols);
}
}
......@@ -685,8 +685,8 @@ int tdInitKVRowBuilder(SKVRowBuilder *pBuilder) {
}
void tdDestroyKVRowBuilder(SKVRowBuilder *pBuilder) {
tfree(pBuilder->pColIdx);
tfree(pBuilder->buf);
taosTFree(pBuilder->pColIdx);
taosTFree(pBuilder->buf);
}
void tdResetKVRowBuilder(SKVRowBuilder *pBuilder) {
......
......@@ -111,7 +111,7 @@ int32_t tsFsyncPeriod = TSDB_DEFAULT_FSYNC_PERIOD;
int32_t tsReplications = TSDB_DEFAULT_DB_REPLICA_OPTION;
int32_t tsQuorum = TSDB_DEFAULT_DB_QUORUM_OPTION;
int32_t tsMaxVgroupsPerDb = 0;
int32_t tsMinTablePerVnode = 100;
int32_t tsMinTablePerVnode = TSDB_TABLES_STEP;
int32_t tsMaxTablePerVnode = TSDB_DEFAULT_TABLES;
int32_t tsTableIncStepPerVnode = TSDB_TABLES_STEP;
......
......@@ -128,7 +128,7 @@ void tVariantDestroy(tVariant *pVar) {
if (pVar == NULL) return;
if (pVar->nType == TSDB_DATA_TYPE_BINARY || pVar->nType == TSDB_DATA_TYPE_NCHAR) {
tfree(pVar->pz);
taosTFree(pVar->pz);
pVar->nLen = 0;
}
......
......@@ -52,12 +52,7 @@
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
<version>${commons-lang3.version}</version>
</dependency>
<dependency>
<groupId>org.jacoco</groupId>
<artifactId>jacoco-maven-plugin</artifactId>
<version>0.8.3</version>
</dependency>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
......@@ -105,32 +100,7 @@
<configuration>
<testFailureIgnore>true</testFailureIgnore>
</configuration>
</plugin>
<plugin>
<groupId>org.jacoco</groupId>
<artifactId>jacoco-maven-plugin</artifactId>
<version>0.8.3</version>
<configuration>
<includes>
<include>com/**/*</include>
</includes>
</configuration>
<executions>
<execution>
<id>pre-test</id>
<goals>
<goal>prepare-agent</goal>
</goals>
</execution>
<execution>
<id>post-test</id>
<phase>test</phase>
<goals>
<goal>report</goal>
</goals>
</execution>
</executions>
</plugin>
</plugin>
</plugins>
</build>
</project>
......@@ -10,6 +10,7 @@ const Struct = require('ref-struct');
const FieldTypes = require('./constants');
const errors = require ('./error');
const TaosObjects = require('./taosobjects');
const { NULL_POINTER } = require('ref');
module.exports = CTaosInterface;
......@@ -177,9 +178,10 @@ var char_arr = ArrayType(ref.types.char);
var TaosField = Struct({
'name': char_arr,
});
TaosField.fields.name.type.size = 64;
TaosField.defineProperty('bytes', ref.types.short);
TaosField.fields.name.type.size = 65;
TaosField.defineProperty('type', ref.types.char);
TaosField.defineProperty('bytes', ref.types.short);
/**
*
......@@ -202,10 +204,10 @@ function CTaosInterface (config = null, pass = false) {
'taos_connect': [ ref.types.void_ptr, [ ref.types.char_ptr, ref.types.char_ptr, ref.types.char_ptr, ref.types.char_ptr, ref.types.int ] ],
//void taos_close(TAOS *taos)
'taos_close': [ ref.types.void, [ ref.types.void_ptr ] ],
//TAOS_RES *taos_use_result(TAOS *taos);
'taos_use_result': [ ref.types.void_ptr, [ ref.types.void_ptr ] ],
//int *taos_fetch_lengths(TAOS_RES *taos);
'taos_fetch_lengths': [ ref.types.void_ptr, [ ref.types.void_ptr ] ],
//int taos_query(TAOS *taos, char *sqlstr)
'taos_query': [ ref.types.int, [ ref.types.void_ptr, ref.types.char_ptr ] ],
'taos_query': [ ref.types.void_ptr, [ ref.types.void_ptr, ref.types.char_ptr ] ],
//int taos_affected_rows(TAOS *taos)
'taos_affected_rows': [ ref.types.int, [ ref.types.void_ptr] ],
//int taos_fetch_block(TAOS_RES *res, TAOS_ROW *rows)
......@@ -329,22 +331,22 @@ CTaosInterface.prototype.query = function query(connection, sql) {
CTaosInterface.prototype.affectedRows = function affectedRows(connection) {
return this.libtaos.taos_affected_rows(connection);
}
CTaosInterface.prototype.useResult = function useResult(connection) {
let result = this.libtaos.taos_use_result(connection);
CTaosInterface.prototype.useResult = function useResult(result) {
let fields = [];
let pfields = this.fetchFields(result);
if (ref.isNull(pfields) == false) {
pfields = ref.reinterpret(pfields, this.fieldsCount(connection) * 68, 0);
pfields = ref.reinterpret(pfields, this.fieldsCount(result) * 68, 0);
for (let i = 0; i < pfields.length; i += 68) {
//0 - 63 = name //64 - 65 = bytes, 66 - 67 = type
fields.push( {
name: ref.readCString(ref.reinterpret(pfields,64,i)),
bytes: pfields[i + 64],
type: pfields[i + 66]
name: ref.readCString(ref.reinterpret(pfields,65,i)),
type: pfields[i + 65],
bytes: pfields[i + 66]
})
}
}
return {result:result, fields:fields}
return fields;
}
CTaosInterface.prototype.fetchBlock = function fetchBlock(result, fields) {
let pblock = ref.ref(ref.ref(ref.NULL)); // equal to our raw data
......@@ -352,19 +354,33 @@ CTaosInterface.prototype.fetchBlock = function fetchBlock(result, fields) {
if (num_of_rows == 0) {
return {block:null, num_of_rows:0};
}
let isMicro = (this.libtaos.taos_result_precision(result) == FieldTypes.C_TIMESTAMP_MICRO)
var fieldL = this.libtaos.taos_fetch_lengths(result);
let isMicro = (this.libtaos.taos_result_precision(result) == FieldTypes.C_TIMESTAMP_MICRO);
var fieldlens = [];
if (ref.isNull(fieldL) == false) {
for (let i = 0; i < fields.length; i ++) {
let plen = ref.reinterpret(fieldL, 4, i*4);
let len = plen.readInt32LE(0);
fieldlens.push(len);
}
}
let blocks = new Array(fields.length);
blocks.fill(null);
num_of_rows = Math.abs(num_of_rows);
let offset = 0;
pblock = pblock.deref();
for (let i = 0; i < fields.length; i++) {
pdata = ref.reinterpret(pblock,8,i*8);
pdata = ref.ref(pdata.readPointer());
if (!convertFunctions[fields[i]['type']] ) {
throw new errors.DatabaseError("Invalid data type returned from database");
}
blocks[i] = convertFunctions[fields[i]['type']](pblock, num_of_rows, fields[i]['bytes'], offset, isMicro);
offset += fields[i]['bytes'] * num_of_rows;
blocks[i] = convertFunctions[fields[i]['type']](pdata, 1, fieldlens[i], offset, isMicro);
}
return {blocks: blocks, num_of_rows:Math.abs(num_of_rows)}
}
......@@ -381,17 +397,17 @@ CTaosInterface.prototype.numFields = function numFields(result) {
return this.libtaos.taos_num_fields(result);
}
// Fetch fields count by connection, the latest query
CTaosInterface.prototype.fieldsCount = function fieldsCount(connection) {
return this.libtaos.taos_field_count(connection);
CTaosInterface.prototype.fieldsCount = function fieldsCount(result) {
return this.libtaos.taos_field_count(result);
}
CTaosInterface.prototype.fetchFields = function fetchFields(result) {
return this.libtaos.taos_fetch_fields(result);
}
CTaosInterface.prototype.errno = function errno(connection) {
return this.libtaos.taos_errno(connection);
CTaosInterface.prototype.errno = function errno(result) {
return this.libtaos.taos_errno(result);
}
CTaosInterface.prototype.errStr = function errStr(connection) {
return ref.readCString(this.libtaos.taos_errstr(connection));
CTaosInterface.prototype.errStr = function errStr(result) {
return ref.readCString(this.libtaos.taos_errstr(result));
}
// Async
CTaosInterface.prototype.query_a = function query_a(connection, sql, callback, param = ref.ref(ref.NULL)) {
......@@ -412,18 +428,32 @@ CTaosInterface.prototype.fetch_rows_a = function fetch_rows_a(result, callback,
// Data preparation to pass to cursor. Could be bottleneck in query execution callback times.
let row = cti.libtaos.taos_fetch_row(result2);
let fields = cti.fetchFields_a(result2);
let isMicro = (cti.libtaos.taos_result_precision(result2) == FieldTypes.C_TIMESTAMP_MICRO);
let blocks = new Array(fields.length);
blocks.fill(null);
numOfRows2 = Math.abs(numOfRows2);
let offset = 0;
var fieldL = cti.libtaos.taos_fetch_lengths(result);
var fieldlens = [];
if (ref.isNull(fieldL) == false) {
for (let i = 0; i < fields.length; i ++) {
let plen = ref.reinterpret(fieldL, 8, i*8);
let len = ref.get(plen,0,ref.types.int32);
fieldlens.push(len);
}
}
if (numOfRows2 > 0){
for (let i = 0; i < fields.length; i++) {
if (!convertFunctions[fields[i]['type']] ) {
throw new errors.DatabaseError("Invalid data type returned from database");
}
blocks[i] = convertFunctions[fields[i]['type']](row, numOfRows2, fields[i]['bytes'], offset, isMicro);
offset += fields[i]['bytes'] * numOfRows2;
let prow = ref.reinterpret(row,8,i*8);
prow = prow.readPointer();
prow = ref.ref(prow);
blocks[i] = convertFunctions[fields[i]['type']](prow, 1, fieldlens[i], offset, isMicro);
//offset += fields[i]['bytes'] * numOfRows2;
}
}
callback(param2, result2, numOfRows2, blocks);
......@@ -440,11 +470,11 @@ CTaosInterface.prototype.fetchFields_a = function fetchFields_a (result) {
if (ref.isNull(pfields) == false) {
pfields = ref.reinterpret(pfields, 68 * pfieldscount , 0);
for (let i = 0; i < pfields.length; i += 68) {
//0 - 63 = name //64 - 65 = bytes, 66 - 67 = type
//0 - 64 = name //65 = type, 66 - 67 = bytes
fields.push( {
name: ref.readCString(ref.reinterpret(pfields,64,i)),
bytes: pfields[i + 64],
type: pfields[i + 66]
name: ref.readCString(ref.reinterpret(pfields,65,i)),
type: pfields[i + 65],
bytes: pfields[i + 66]
})
}
}
......
......@@ -74,9 +74,11 @@ TDengineConnection.prototype.rollback = function rollback() {
* Clear the results from connector
* @private
*/
TDengineConnection.prototype._clearResultSet = function _clearResultSet() {
/*
TDengineConnection.prototype._clearResultSet = function _clearResultSet() {
var result = this._chandle.useResult(this._conn).result;
if (result) {
this._chandle.freeResult(result)
}
}
*/
......@@ -98,7 +98,7 @@ TDengineCursor.prototype.execute = function execute(operation, options, callback
if (this._connection == null) {
throw new errors.ProgrammingError('Cursor is not connected');
}
this._connection._clearResultSet();
this._reset_result();
let stmt = operation;
......@@ -111,18 +111,18 @@ TDengineCursor.prototype.execute = function execute(operation, options, callback
});
obs.observe({ entryTypes: ['measure'] });
performance.mark('A');
res = this._chandle.query(this._connection._conn, stmt);
this._result = this._chandle.query(this._connection._conn, stmt);
performance.mark('B');
performance.measure('query', 'A', 'B');
}
else {
res = this._chandle.query(this._connection._conn, stmt);
this._result = this._chandle.query(this._connection._conn, stmt);
}
res = this._chandle.errno(this._result);
if (res == 0) {
let fieldCount = this._chandle.fieldsCount(this._connection._conn);
let fieldCount = this._chandle.fieldsCount(this._result);
if (fieldCount == 0) {
let affectedRowCount = this._chandle.affectedRows(this._connection._conn);
let affectedRowCount = this._chandle.affectedRows(this._result);
let response = this._createAffectedResponse(affectedRowCount, time)
if (options['quiet'] != true) {
console.log(response);
......@@ -131,16 +131,15 @@ TDengineCursor.prototype.execute = function execute(operation, options, callback
return affectedRowCount; //return num of affected rows, common with insert, use statements
}
else {
let resAndField = this._chandle.useResult(this._connection._conn, fieldCount)
this._result = resAndField.result;
this._fields = resAndField.fields;
this.fields = resAndField.fields;
this._fields = this._chandle.useResult(this._result);
this.fields = this._fields;
wrapCB(callback);
return this._result; //return a pointer to the result
}
}
else {
throw new errors.ProgrammingError(this._chandle.errStr(this._connection._conn))
throw new errors.ProgrammingError(this._chandle.errStr(this._result))
}
}
......@@ -198,18 +197,18 @@ TDengineCursor.prototype.fetchall = function fetchall(options, callback) {
while(true) {
let blockAndRows = this._chandle.fetchBlock(this._result, this._fields);
let block = blockAndRows.blocks;
let num_of_rows = blockAndRows.num_of_rows;
if (num_of_rows == 0) {
break;
}
this._rowcount += num_of_rows;
let numoffields = this._fields.length;
for (let i = 0; i < num_of_rows; i++) {
data.push([]);
let rowBlock = new Array(this._fields.length);
for (let j = 0; j < this._fields.length; j++) {
let rowBlock = new Array(numoffields);
for (let j = 0; j < numoffields; j++) {
rowBlock[j] = block[j][i];
}
data[data.length-1] = (rowBlock);
......@@ -221,7 +220,7 @@ TDengineCursor.prototype.fetchall = function fetchall(options, callback) {
let response = this._createSetResponse(this._rowcount, time)
console.log(response);
this._connection._clearResultSet();
// this._connection._clearResultSet();
let fields = this.fields;
this._reset_result();
this.data = data;
......@@ -266,13 +265,15 @@ TDengineCursor.prototype.execute_a = function execute_a (operation, options, cal
}
if (resCode >= 0) {
let fieldCount = cr._chandle.numFields(res2);
if (fieldCount == 0) {
cr._chandle.freeResult(res2);
}
else {
return res2;
}
// let fieldCount = cr._chandle.numFields(res2);
// if (fieldCount == 0) {
// //cr._chandle.freeResult(res2);
// return res2;
// }
// else {
// return res2;
// }
return res2;
}
else {
......@@ -381,6 +382,9 @@ TDengineCursor.prototype.stopQuery = function stopQuery(result) {
}
TDengineCursor.prototype._reset_result = function _reset_result() {
this._rowcount = -1;
if (this._result != null) {
this._chandle.freeResult(this._result);
}
this._result = null;
this._fields = null;
this.data = [];
......
{
"name": "td-connector",
"version": "1.6.1",
"name": "td2.0-connector",
"version": "2.0.1",
"lockfileVersion": 1,
"requires": true,
"dependencies": {
......
{
"name": "td-connector",
"version": "2.0.0",
"name": "td2.0-connector",
"version": "2.0.1",
"description": "A Node.js connector for TDengine.",
"main": "tdengine.js",
"scripts": {
......
# TDengine Node.js connector
[![minzip](https://img.shields.io/bundlephobia/minzip/td-connector.svg)](https://github.com/taosdata/TDengine/tree/master/src/connector/nodejs) [![NPM](https://img.shields.io/npm/l/td-connector.svg)](https://github.com/taosdata/TDengine/#what-is-tdengine)
[![minzip](https://img.shields.io/bundlephobia/minzip/td2.0-connector.svg)](https://github.com/taosdata/TDengine/tree/master/src/connector/nodejs) [![NPM](https://img.shields.io/npm/l/td2.0-connector.svg)](https://github.com/taosdata/TDengine/#what-is-tdengine)
This is the Node.js library that lets you connect to [TDengine](https://www.github.com/taosdata/tdengine). It is built so that you can use as much of it as you want or as little of it as you want through providing an extensive API. If you want the raw data in the form of an array of arrays for the row data retrieved from a table, you can do that. If you want to wrap that data with objects that allow you easily manipulate and display data such as using a prettifier function, you can do that!
This is the Node.js library that lets you connect to [TDengine](https://www.github.com/taosdata/tdengine) 2.0 version. It is built so that you can use as much of it as you want or as little of it as you want through providing an extensive API. If you want the raw data in the form of an array of arrays for the row data retrieved from a table, you can do that. If you want to wrap that data with objects that allow you easily manipulate and display data such as using a prettifier function, you can do that!
## Installation
To get started, just type in the following to install the connector through [npm](https://www.npmjs.com/)
```cmd
npm install td-connector
npm install td2.0-connector
```
To interact with TDengine, we make use of the [node-gyp](https://github.com/nodejs/node-gyp) library. To install, you will need to install the following depending on platform (the following instructions are quoted from node-gyp)
### On Unix
### On Linux
- `python` (`v2.7` recommended, `v3.x.x` is **not** supported)
- `make`
- A proper C/C++ compiler toolchain, like [GCC](https://gcc.gnu.org)
- `node` (between `v10.x` and `v11.x`, other version has some dependency compatibility problems)
### On macOS
......@@ -71,12 +72,12 @@ The following is a short summary of the basic usage of the connector, the full
### Connection
To use the connector, first require the library ```td-connector```. Running the function ```taos.connect``` with the connection options passed in as an object will return a TDengine connection object. The required connection option is ```host```, other options if not set, will be the default values as shown below.
To use the connector, first require the library ```td2.0-connector```. Running the function ```taos.connect``` with the connection options passed in as an object will return a TDengine connection object. The required connection option is ```host```, other options if not set, will be the default values as shown below.
A cursor also needs to be initialized in order to interact with TDengine from Node.js.
```javascript
const taos = require('td-connector');
const taos = require('td2.0-connector');
var conn = taos.connect({host:"127.0.0.1", user:"root", password:"taosdata", config:"/etc/taos",port:0})
var cursor = conn.cursor(); // Initializing a new cursor
```
......
......@@ -19,7 +19,7 @@ function randomBool() {
}
// Initialize
//c1.execute('drop database td_connector_test;');
c1.execute('create database if not exists td_connector_test;');
c1.execute('use td_connector_test;')
c1.execute('create table if not exists all_types (ts timestamp, _int int, _bigint bigint, _float float, _double double, _binary binary(40), _smallint smallint, _tinyint tinyint, _bool bool, _nchar nchar(40));');
......@@ -46,12 +46,14 @@ for (let i = 0; i < 10000; i++) {
}
// Select
c1.execute('select * from td_connector_test.all_types limit 10 offset 1000;');
console.log('select * from td_connector_test.all_types limit 3 offset 100;');
c1.execute('select * from td_connector_test.all_types limit 2 offset 100;');
var d = c1.fetchall();
console.log(c1.fields);
console.log(d);
// Functions
console.log('select count(*), avg(_int), sum(_float), max(_bigint), min(_double) from td_connector_test.all_types;')
c1.execute('select count(*), avg(_int), sum(_float), max(_bigint), min(_double) from td_connector_test.all_types;');
var d = c1.fetchall();
console.log(c1.fields);
......@@ -62,9 +64,11 @@ console.log(d);
c1.query('select count(*), stddev(_double), min(_tinyint) from all_types where _tinyint > 50 and _int < 0;', true).then(function(result){
result.pretty();
})
c1.query('select _tinyint, _bool from all_types where _tinyint > 50 and _int < 0 limit 50;', true).then(function(result){
result.pretty();
})
c1.query('select stddev(_double), stddev(_bigint), stddev(_float) from all_types;', true).then(function(result){
result.pretty();
})
......@@ -83,54 +87,58 @@ q.execute().then(function(r) {
// Raw Async Testing (Callbacks, not promises)
function cb2(param, result, rowCount, rd) {
console.log('CB2 Callbacked!');
console.log("RES *", result);
console.log("Async fetched", rowCount, "rows");
console.log("Async fetched", rowCount, " rows");
console.log("Passed Param: ", param);
console.log("Fields", rd.fields);
console.log("Data", rd.data);
console.log("Fields ", rd.fields);
console.log("Data ", rd.data);
}
function cb1(param,result,code) {
console.log('Callbacked!');
console.log("RES *", result);
console.log('CB1 Callbacked!');
console.log("RES * ", result);
console.log("Status: ", code);
console.log("Passed Param", param);
c1.fetchall_a(result, cb2, param)
console.log("Passed Param ", param);
c1.fetchall_a(result, cb2, param);
}
c1.execute_a("describe td_connector_test.all_types;", cb1, {myparam:3.141});
function cb4(param, result, rowCount, rd) {
console.log('CB4 Callbacked!');
console.log("RES *", result);
console.log("Async fetched", rowCount, "rows");
console.log("Passed Param: ", param);
console.log("Fields", rd.fields);
console.log("Data", rd.data);
}
// Without directly calling fetchall_a
var thisRes;
function cb3(param,result,code) {
console.log('Callbacked!');
console.log('CB3 Callbacked!');
console.log("RES *", result);
console.log("Status: ", code);
console.log("Status:", code);
console.log("Passed Param", param);
thisRes = result;
}
//Test calling execute and fetchall seperately and not through callbacks
var param = c1.execute_a("describe td_connector_test.all_types;", cb3, {e:2.718});
console.log("Passed Param outside of callback: ", param);
console.log(param);
setTimeout(function(){
c1.fetchall_a(thisRes, cb4, param);
},100);
// Async through promises
var aq = c1.query('select count(*) from td_connector_test.all_types;')
var aq = c1.query('select count(*) from td_connector_test.all_types;',false);
aq.execute_a().then(function(data) {
data.pretty();
})
});
c1.query('describe td_connector_test.stabletest;').execute_a().then(r=> r.pretty());
setTimeout(function(){
c1.query('drop database td_connector_test;');
},200);
setTimeout(function(){
conn.close();
},2000);
conn.close();
......@@ -114,7 +114,7 @@ void cqClose(void *handle) {
SCqObj *pTemp = pObj;
pObj = pObj->next;
tdFreeSchema(pTemp->pSchema);
tfree(pTemp->sqlStr);
taosTFree(pTemp->sqlStr);
free(pTemp);
}
......
......@@ -16,7 +16,8 @@ IF ((TD_LINUX_64) OR (TD_LINUX_32 AND TD_ARM))
AUX_SOURCE_DIRECTORY(src SRC)
ADD_EXECUTABLE(taosd ${SRC})
TARGET_LINK_LIBRARIES(taosd mnode taos_static monitor http mqtt tsdb twal vnode cJson lz4 balance sync)
# TARGET_LINK_LIBRARIES(taosd mnode taos_static monitor http mqtt tsdb twal vnode cJson lz4 balance sync)
TARGET_LINK_LIBRARIES(taosd mnode taos monitor http mqtt tsdb twal vnode cJson lz4 balance sync)
IF (TD_ACCOUNT)
TARGET_LINK_LIBRARIES(taosd account)
......
......@@ -75,7 +75,7 @@ void dnodeCleanupMnodePeer() {
}
taosCloseQset(tsMPeerQset);
tfree(tsMPeerPool.peerWorker);
taosTFree(tsMPeerPool.peerWorker);
dInfo("dnode mpeer is closed");
}
......
......@@ -77,7 +77,7 @@ void dnodeCleanupMnodeWrite() {
}
taosCloseQset(tsMWriteQset);
tfree(tsMWritePool.writeWorker);
taosTFree(tsMWritePool.writeWorker);
dInfo("dnode mwrite is closed");
}
......
......@@ -18,13 +18,11 @@
#include "cJSON.h"
#include "taoserror.h"
#include "taosmsg.h"
#include "ttime.h"
#include "ttimer.h"
#include "tsdb.h"
#include "twal.h"
#include "tqueue.h"
#include "tsync.h"
#include "ttime.h"
#include "ttimer.h"
#include "tbalance.h"
#include "tglobal.h"
......
......@@ -22,6 +22,7 @@ extern "C" {
#include <stdint.h>
#include <stdbool.h>
#include "osDef.h"
#include "taos.h"
#define TSDB__packed
......@@ -161,7 +162,7 @@ extern tDataTypeDescriptor tDataTypeDesc[11];
bool isValidDataType(int32_t type);
//bool isNull(const char *val, int32_t type);
static inline __attribute__((always_inline)) bool isNull(const char *val, int32_t type) {
static FORCE_INLINE bool isNull(const char *val, int32_t type) {
switch (type) {
case TSDB_DATA_TYPE_BOOL:
return *(uint8_t *)val == TSDB_DATA_BOOL_NULL;
......
......@@ -15,11 +15,11 @@ IF ((TD_LINUX_64) OR (TD_LINUX_32 AND TD_ARM))
LIST(REMOVE_ITEM SRC ./src/shellDarwin.c)
ADD_EXECUTABLE(shell ${SRC})
IF (TD_PAGMODE_LITE)
# IF (TD_PAGMODE_LITE)
TARGET_LINK_LIBRARIES(shell taos)
ELSE ()
TARGET_LINK_LIBRARIES(shell taos_static)
ENDIF ()
# ELSE ()
# TARGET_LINK_LIBRARIES(shell taos_static)
# ENDIF ()
SET_TARGET_PROPERTIES(shell PROPERTIES OUTPUT_NAME taos)
ELSEIF (TD_WINDOWS_64)
......
......@@ -229,8 +229,8 @@ void shellReadCommand(TAOS *con, char *command) {
printf("\n");
if (isReadyGo(&cmd)) {
sprintf(command, "%s%s", cmd.buffer, cmd.command);
tfree(cmd.buffer);
tfree(cmd.command);
taosTFree(cmd.buffer);
taosTFree(cmd.command);
return;
} else {
updateBuffer(&cmd);
......
......@@ -21,7 +21,6 @@
#include "os.h"
#include "shell.h"
#include "shellCommand.h"
#include "ttime.h"
#include "tutil.h"
#include "taosdef.h"
#include "taoserror.h"
......@@ -176,7 +175,7 @@ int32_t shellRunCommand(TAOS* con, char* command) {
history.hist[(history.hend + MAX_HISTORY_SIZE - 1) % MAX_HISTORY_SIZE] == NULL ||
strcmp(command, history.hist[(history.hend + MAX_HISTORY_SIZE - 1) % MAX_HISTORY_SIZE]) != 0) {
if (history.hist[history.hend] != NULL) {
tfree(history.hist[history.hend]);
taosTFree(history.hist[history.hend]);
}
history.hist[history.hend] = strdup(command);
......@@ -770,7 +769,7 @@ void write_history() {
for (int i = history.hstart; i != history.hend;) {
if (history.hist[i] != NULL) {
fprintf(f, "%s\n", history.hist[i]);
tfree(history.hist[i]);
taosTFree(history.hist[i]);
}
i = (i + 1) % MAX_HISTORY_SIZE;
}
......
......@@ -21,7 +21,6 @@
#include "shell.h"
#include "shellCommand.h"
#include "tglobal.h"
#include "ttime.h"
#include "tutil.h"
static char **shellSQLFiles = NULL;
......
......@@ -201,8 +201,8 @@ void shellReadCommand(TAOS *con, char *command) {
printf("\n");
if (isReadyGo(&cmd)) {
sprintf(command, "%s%s", cmd.buffer, cmd.command);
tfree(cmd.buffer);
tfree(cmd.command);
taosTFree(cmd.buffer);
taosTFree(cmd.command);
return;
} else {
updateBuffer(&cmd);
......@@ -320,7 +320,7 @@ void *shellLoopQuery(void *arg) {
reset_terminal_mode();
} while (shellRunCommand(con, command) == 0);
tfree(command);
taosTFree(command);
exitShell();
pthread_cleanup_pop(1);
......
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册