提交 5da9d427 编写于 作者: S shenglian zhou

Merge branch 'develop' of github.com:taosdata/TDengine into szhou/feature/sml-perf

# Use the latest 2.1 version of CircleCI pipeline process engine. See: https://circleci.com/docs/2.0/configuration-reference
version: 2.1
# Use a package of configuration called an orb.
orbs:
# Declare a dependency on the welcome-orb
welcome: circleci/welcome-orb@0.4.1
# Orchestrate or schedule a set of jobs
workflows:
# Name the workflow "welcome"
welcome:
# Run the welcome/run job in its own container
jobs:
- welcome/run
---
kind: pipeline
name: test_arm64_bionic
platform:
os: linux
arch: arm64
steps:
- name: build
image: arm64v8/ubuntu:bionic
commands:
- apt-get update
- apt-get install -y cmake git build-essential wget
- wget https://dl.google.com/go/go1.16.9.linux-arm64.tar.gz
- tar -C /usr/local -xzf go1.16.9.linux-arm64.tar.gz
- export PATH=$PATH:/usr/local/go/bin
- git submodule update --init --recursive
- mkdir debug
- cd debug
- cmake .. -DCPUTYPE=aarch64 > /dev/null
- make -j4
trigger:
event:
- pull_request
when:
branch:
- develop
- master
- 2.0
---
kind: pipeline
name: test_arm64_focal
platform:
os: linux
arch: arm64
steps:
- name: build
image: arm64v8/ubuntu:focal
commands:
- echo 'debconf debconf/frontend select Noninteractive' | debconf-set-selections
- apt-get update
- apt-get install -y -qq git cmake build-essential wget
- wget https://dl.google.com/go/go1.16.9.linux-arm64.tar.gz
- tar -C /usr/local -xzf go1.16.9.linux-arm64.tar.gz
- export PATH=$PATH:/usr/local/go/bin
- git submodule update --init --recursive
- mkdir debug
- cd debug
- cmake .. -DCPUTYPE=aarch64 > /dev/null
- make -j4
trigger:
event:
- pull_request
when:
branch:
- develop
- master
- 2.0
---
kind: pipeline
name: test_arm64_centos7
platform:
os: linux
arch: arm64
steps:
- name: build
image: arm64v8/centos:7
commands:
- yum install -y epel-release
- yum install -y gcc gcc-c++ make cmake3 wget git
- wget https://dl.google.com/go/go1.16.9.linux-arm64.tar.gz
- tar -C /usr/local -xzf go1.16.9.linux-arm64.tar.gz
- export PATH=$PATH:/usr/local/go/bin
- ln -s /usr/bin/cmake3 /usr/bin/cmake
- go version
- git submodule update --init --recursive
- mkdir debug
- cd debug
- cmake3 .. -DCPUTYPE=aarch64 > /dev/null
- make -j4
trigger:
event:
- pull_request
when:
branch:
- develop
- master
- 2.0
---
kind: pipeline
name: test_arm64_centos8
platform:
os: linux
arch: arm64
steps:
- name: build
image: arm64v8/centos:8
commands:
- dnf install -y gcc gcc-c++ make cmake epel-release git libarchive golang
- git submodule update --init --recursive
- mkdir debug
- cd debug
- cmake .. -DCPUTYPE=aarch64 > /dev/null
- make -j4
trigger:
event:
- pull_request
when:
branch:
- develop
- master
- 2.0
---
kind: pipeline
name: test_arm_bionic
platform:
os: linux
arch: arm
steps:
- name: build
image: arm32v7/ubuntu:bionic
commands:
- apt-get update
- apt-get install -y cmake build-essential golang-go git
- git submodule update --init --recursive
- mkdir debug
- cd debug
- cmake .. -DCPUTYPE=aarch32 > /dev/null
- make -j4
trigger:
event:
- pull_request
when:
branch:
- develop
- master
- 2.0
---
kind: pipeline
name: build_trusty
platform:
os: linux
arch: amd64
steps:
- name: build
image: ubuntu:trusty
commands:
- apt-get update
- apt-get install -y gcc cmake3 build-essential git binutils-2.26 wget
- wget https://dl.google.com/go/go1.16.9.linux-amd64.tar.gz
- tar -C /usr/local -xzf go1.16.9.linux-amd64.tar.gz
- export PATH=$PATH:/usr/local/go/bin
- git submodule update --init --recursive
- mkdir debug
- cd debug
- cmake ..
- make -j4
trigger:
event:
- pull_request
when:
branch:
- develop
- master
- 2.0
---
kind: pipeline
name: build_xenial
platform:
os: linux
arch: amd64
steps:
- name: build
image: ubuntu:xenial
commands:
- apt-get update
- apt-get install -y gcc cmake build-essential git wget
- wget https://dl.google.com/go/go1.16.9.linux-amd64.tar.gz
- tar -C /usr/local -xzf go1.16.9.linux-amd64.tar.gz
- export PATH=$PATH:/usr/local/go/bin
- git submodule update --init --recursive
- mkdir debug
- cd debug
- cmake ..
- make -j4
trigger:
event:
- pull_request
when:
branch:
- develop
- master
- 2.0
---
kind: pipeline
name: build_bionic
platform:
os: linux
arch: amd64
steps:
- name: build
image: ubuntu:bionic
commands:
- apt-get update
- apt-get install -y gcc cmake build-essential git wget
- wget https://dl.google.com/go/go1.16.9.linux-amd64.tar.gz
- tar -C /usr/local -xzf go1.16.9.linux-amd64.tar.gz
- export PATH=$PATH:/usr/local/go/bin
- git submodule update --init --recursive
- mkdir debug
- cd debug
- cmake ..
- make -j4
trigger:
event:
- pull_request
when:
branch:
- develop
- master
- 2.0
---
kind: pipeline
name: build_centos7
platform:
os: linux
arch: amd64
steps:
- name: build
image: ansible/centos7-ansible
commands:
- yum install -y epel-release
- yum install -y gcc gcc-c++ make cmake3 wget git
- wget https://dl.google.com/go/go1.16.9.linux-amd64.tar.gz
- tar -C /usr/local -xzf go1.16.9.linux-amd64.tar.gz
- export PATH=$PATH:/usr/local/go/bin
- ln -s /usr/bin/cmake3 /usr/bin/cmake
- git submodule update --init --recursive
- mkdir debug
- cd debug
- cmake3 ..
- make -j4
trigger:
event:
- pull_request
when:
branch:
- develop
- master
- 2.0
\ No newline at end of file
......@@ -20,3 +20,9 @@
[submodule "examples/rust"]
path = examples/rust
url = https://github.com/songtianyi/tdengine-rust-bindings.git
[submodule "src/connector/php-tdengine"]
path = src/connector/php-tdengine
url = https://github.com/Yurunsoft/php-tdengine.git
[submodule "src/connector/php-tdengine-restful-connector"]
path = src/connector/php-tdengine-restful-connector
url = https://github.com/Yurunsoft/tdengine-restful-connector.git
......@@ -116,7 +116,7 @@ def pre_test(){
make > /dev/null
make install > /dev/null
cd ${WKC}/tests
pip3 install ${WKC}/src/connector/python/
pip3 install taospy
'''
return 1
}
......
......@@ -21,21 +21,25 @@ def sync_source() {
if (env.CHANGE_TARGET == 'master') {
sh '''
cd ${WKC}
git clean -fxd
git checkout master
'''
} else if (env.CHANGE_TARGET == '2.0') {
sh '''
cd ${WKC}
git clean -fxd
git checkout 2.0
'''
} else if (env.CHANGE_TARGET == '2.4') {
sh '''
cd ${WKC}
git clean -fxd
git checkout 2.4
'''
} else {
sh '''
cd ${WKC}
git clean -fxd
git checkout develop
'''
}
......@@ -83,6 +87,16 @@ def sync_source() {
cd ${WKC}
git fetch origin +refs/pull/${CHANGE_ID}/merge
git checkout -qf FETCH_HEAD
if [ ! -d src/connector/python/.github ]; then
rm -rf src/connector/python/* || :
rm -rf src/connector/python/.* || :
git clone --depth 1 https://github.com/taosdata/taos-connector-python src/connector/python || echo "failed to clone python connector"
else
cd src/connector/python || echo "src/connector/python not exist"
git pull || :
cd ${WKC}
fi
'''
} else if (env.CHANGE_URL =~ /\/TDinternal\//) {
sh '''
......@@ -90,6 +104,16 @@ def sync_source() {
cd ${WK}
git fetch origin +refs/pull/${CHANGE_ID}/merge
git checkout -qf FETCH_HEAD
if [ ! -d community/src/connector/python/.github ]; then
rm -rf community/src/connector/python/* || :
rm -rf community/src/connector/python/.* || :
git clone --depth 1 https://github.com/taosdata/taos-connector-python community/src/connector/python || echo "failed to clone python connector"
else
cd community/src/connector/python || echo "community/src/connector/python not exist"
git pull || :
cd ${WK}
fi
'''
} else {
sh '''
......@@ -251,20 +275,6 @@ pipeline {
}
}
parallel {
stage ('build worker08_arm32') {
agent {label " worker08_arm32"}
steps {
timeout(time: 20, unit: 'MINUTES') {
pre_test()
script {
sh '''
echo "worker08_arm32 build done"
date
'''
}
}
}
}
stage ('build worker07_arm64') {
agent {label " worker07_arm64 "}
steps {
......
......@@ -287,9 +287,17 @@ IF (TD_LINUX)
SET(COMMON_FLAGS "${COMMON_FLAGS} -pipe -Wshadow")
ENDIF ()
MESSAGE(STATUS "CMAKE_CXX_COMPILER_ID: " ${CMAKE_CXX_COMPILER_ID})
IF ("${CMAKE_CXX_COMPILER_ID}" MATCHES "Clang")
EXECUTE_PROCESS( COMMAND ${CMAKE_CXX_COMPILER} --version OUTPUT_VARIABLE clang_full_version_string )
string (REGEX REPLACE ".*clang version ([0-9]+\\.[0-9]+).*" "\\1" CLANG_VERSION_STRING ${clang_full_version_string})
IF (CLANG_VERSION_STRING GREATER_EQUAL 13.0)
SET(COMMON_FLAGS "${COMMON_FLAGS} -Wno-unused-but-set-variable")
ENDIF ()
ENDIF ()
INCLUDE_DIRECTORIES(${TD_COMMUNITY_DIR}/src/inc)
INCLUDE_DIRECTORIES(${TD_COMMUNITY_DIR}/src/os/inc)
INCLUDE_DIRECTORIES(${TD_COMMUNITY_DIR}/src/util/inc)
INCLUDE_DIRECTORIES(${TD_COMMUNITY_DIR}/src/common/inc)
MESSAGE(STATUS "CMAKE_CXX_COMPILER_ID: " ${CMAKE_CXX_COMPILER_ID})
......@@ -53,11 +53,6 @@ IF (${MEM_CHECK} MATCHES "true")
MESSAGE(STATUS "build with memory check")
ENDIF ()
IF (${MQTT} MATCHES "false")
SET(TD_MQTT FALSE)
MESSAGE(STATUS "build without mqtt module")
ENDIF ()
IF (${RANDOM_FILE_FAIL} MATCHES "true")
SET(TD_RANDOM_FILE_FAIL TRUE)
MESSAGE(STATUS "build with random-file-fail enabled")
......@@ -104,4 +99,4 @@ ELSE()
MESSAGE(STATUS "build with TSZ enabled")
ADD_DEFINITIONS(-DTD_TSZ)
set(VAR_TSZ "TSZ" CACHE INTERNAL "global variant tsz" )
ENDIF()
\ No newline at end of file
ENDIF()
......@@ -20,7 +20,7 @@ ELSEIF (TD_WINDOWS)
INSTALL(FILES ${EXECUTABLE_OUTPUT_PATH}/taos.exe DESTINATION .)
IF (TD_MVN_INSTALLED)
INSTALL(FILES ${LIBRARY_OUTPUT_PATH}/taos-jdbcdriver-2.0.37-dist.jar DESTINATION connector/jdbc)
INSTALL(FILES ${LIBRARY_OUTPUT_PATH}/taos-jdbcdriver-2.0.38-dist.jar DESTINATION connector/jdbc)
ENDIF ()
ELSEIF (TD_DARWIN)
SET(TD_MAKE_INSTALL_SH "${TD_COMMUNITY_DIR}/packaging/tools/make_install.sh")
......
---
sidebar_label: 产品简介
title: 产品简介
toc_max_heading_level: 2
---
# 产品简介
## TDengine 简介
TDengine 是一款高性能、分布式、支持 SQL 的时序数据库。而且除时序数据库功能外,它还提供缓存、数据订阅、流式计算等功能,最大程度减少研发和运维的复杂度,且核心代码,包括集群功能全部开源(开源协议,AGPL v3.0)。与其他时序数据数据库相比,TDengine 有以下特点:
......@@ -25,15 +24,16 @@ TDengine 是一款高性能、分布式、支持 SQL 的时序数据库。而且
- **互动 Console**: 通过命令行 console,不用编程,执行 SQL 语句就能做即席查询、各种数据库的操作、管理以及集群的维护.
采用 TDengine,可将典型的物联网、车联网、工业互联网大数据平台的总拥有成本大幅降低。但需要指出的是,因充分利用了物联网时序数据的特点,它无法用来处理网络爬虫、微博、微信、电商、ERP、CRM 等通用型数据
采用 TDengine,可将典型的物联网、车联网、工业互联网大数据平台的总拥有成本大幅降低。表现在几个方面,1:由于其超强性能,它能将系统需要的计算资源和存储资源大幅降低;2:因为采用SQL接口,能与众多第三放软件无缝集成,学习迁移成本大幅下降;3:因为其All In One的特性,系统复杂度降低,能降研发成本;4:因为运维维护简单,运营维护成本能大幅降低
在整个时序大数据平台中,TDengine在其中扮演的角色如下:
![TDengine技术生态图](eco_system.png)
<center>图 1. TDengine技术生态图</center>
## TDengine 总体适用场景
作为一个 IoT 大数据平台,TDengine 的典型适用场景是在 IoT 范畴,而且用户有一定的数据量。本文后续的介绍主要针对这个范畴里面的系统。范畴之外的系统,比如 CRM,ERP 等,不在本文讨论范围内
作为一个高性能、分布式、支持 SQL 的时序数据库,TDengine 的典型适用场景包括但不限于 IoT、工业互联网、车联网、IT运维、能源、金融证券等领域。需要指出的是,TDengine是针对时序数据场景设计的专用数据库和专用大数据处理工具,因充分利用了时序大数据的特点,它无法用来处理网络爬虫、微博、微信、电商、ERP、CRM 等通用型数据。本文对适用场景做更多详细的分析
### 数据源特点和需求
......
# 基本概念
---
title: 数据模型和基本概念
---
## 物联网典型场景
在典型的物联网、车联网、运维监测场景中,往往有多种不同类型的数据采集设备,采集一个到多个不同的物理量。而同一种采集设备类型,往往又有多个具体的采集设备分布在不同的地点。大数据处理系统就是要将各种采集的数据汇总,然后进行计算和分析。对于同一类设备,其采集的数据类似如下的表格:
| Device ID | Time Stamp | Value 1 | Value 2 | Value 3 | Tag 1 | Tag 2 |
| :-------: | :-----------: | :-----: | :-----: | :-----: | :---: | :---: |
| D1001 | 1538548685000 | 10.3 | 219 | 0.31 | Red | Tesla |
| D1002 | 1538548684000 | 10.2 | 220 | 0.23 | Blue | BMW |
| D1003 | 1538548686500 | 11.5 | 221 | 0.35 | Black | Honda |
| D1004 | 1538548685500 | 13.4 | 223 | 0.29 | Red | Volvo |
| D1001 | 1538548695000 | 12.6 | 218 | 0.33 | Red | Tesla |
| D1004 | 1538548696600 | 11.8 | 221 | 0.28 | Black | Honda |
每一条记录都有设备 ID,时间戳,采集的物理量,还有与每个设备相关的静态标签。每个设备是受外界的触发,或按照设定的周期采集数据。采集的数据点是时序的,是一个数据流。
**数据特征**
除时序特征外,仔细研究发现,物联网、车联网、运维监测类数据还具有很多其他明显的特征。
在典型的物联网、车联网、运维监测场景中,往往有多种不同类型的数据采集设备或采集点,采集一个到多个不同的物理量。而同一种采集设备类型,往往又有多个具体的采集设备分布在不同的地点。采集的物理量都带有时间标签,而且数据量随时间不断增长,但每个数据采集设备或采集点还有自身的静态属性。对于同一类设备,其采集的数据以及静态属性都是很规则的。以智能电表为例,假设每个智能电表采集电流、电压、相位三个量,其采集的数据类似如下的表格:
<table>
<thead><tr>
<th >设备ID</th>
<th >时间戳</th>
<th colspan="3">采集量</th>
<th colspan="2">标签</th>
</tr>
<tr>
<th >Device ID</th>
<th >Time Stamp</th>
<th >current</th>
<th >voltage</th>
<th >phase</th>
<th >location</th>
<th >groupId</th>
</tr>
</thead>
<tbody>
<tr>
<td >d1001</td>
<td >1538548685000</td>
<td >10.3</td>
<td >219</td>
<td >0.31</td>
<td >Beijing.Chaoyang</td>
<td >2</td>
</tr>
<tr>
<td >d1002</td>
<td >1538548684000</td>
<td >10.2</td>
<td >220</td>
<td >0.23</td>
<td >Beijing.Chaoyang</td>
<td >3</td>
</tr>
<tr>
<td >d1003</td>
<td >1538548686500</td>
<td >11.5</td>
<td >221</td>
<td >0.35</td>
<td >Beijing.Haidian</td>
<td >3</td>
</tr>
<tr>
<td >d1004</td>
<td >1538548685500</td>
<td >13.4</td>
<td >223</td>
<td >0.29</td>
<td >Beijing.Haidian</td>
<td >2</td>
</tr>
<tr>
<td >d1001</td>
<td >1538548695000</td>
<td >12.6</td>
<td >218</td>
<td >0.33</td>
<td >Beijing.Chaoyang</td>
<td >2</td>
</tr>
<tr>
<td >d1004</td>
<td >1538548696600</td>
<td >11.8</td>
<td >221</td>
<td >0.28</td>
<td >Beijing.Haidian</td>
<td >2</td>
</tr>
<tr>
<td >d1002</td>
<td >1538548696650</td>
<td >10.3</td>
<td >218</td>
<td >0.25</td>
<td >Beijing.Chaoyang</td>
<td >3</td>
</tr>
<tr>
<td >d1001</td>
<td >1538548696800</td>
<td >12.3</td>
<td >221</td>
<td >0.31</td>
<td >Beijing.Chaoyang</td>
<td >2</td>
</tr>
</tbody>
</table>
<center> <a href="#model_table1">表 1:智能电表数据示例</a></center>
每一条记录都有设备 ID,时间戳,采集的物理量(如上图中的电流、电压、相位),还有与每个设备相关的静态标签(如上述表 1 中的位置 location 和分组 groupId)。每个设备是受外界的触发,或按照设定的周期采集数据。采集的数据点是时序的,是一个数据流。
## 数据特征
除时序特征外,仔细研究发现,物联网、车联网、运维监测类数据及其应用还具有很多其他明显的特征。
1. 数据是结构化的;
2. 数据极少有更新或删除操作;
......@@ -28,41 +115,62 @@
6. 用户关注的是一段时间的趋势,而不是某一特点时间点的值;
7. 数据是有保留期限的;
8. 数据的查询分析一定是基于时间段和地理区域的;
9. 除存储查询外,还往往需要各种统计和实时计算操作;
9. 系统需要各种实时计算和统计操作,包括降采样、插值等特种操作;
10. 数据量巨大,一天采集的数据就可以超过 100 亿条。
充分利用上述特征,TDengine 采取了一特殊的优化的存储和计算设计来处理时序数据,能将系统处理能力显著提高。
## 数据采集点
## 采集量(Metric)
采集量是指传感器、设备或其他类型采集点采集的物理量,比如电流、电压、温度、压力、GPS位置等,是随时间变化的,数据类型可以是整型、浮点型、布尔型,也可是字符串。随着时间的推移,存储的采集量的数据量越来越大。
## 标签(Label/Tag)
标签是指传感器、设备或其他类型采集点的静态属性,不是随时间变化的,比如设备型号、颜色、设备的所在地等,数据类型可以是任何类型。虽然是静态的,但TDengine容许用户修改、删除或增加标签值。与采集量不一样的是,随时间的推移,存储的标签的数据量不会有什么变化。
## 数据采集点(Data Colletion Point)
数据采集点是指按照预设时间周期或受事件触发采集物理量的硬件或软件。一个数据采集点可以采集一个或多个物理量,**但这些物理量都是同一时刻采集的,具有相同的时间戳**。对于复杂的设备,往往有多个数据采集点,每个采集点采集的周期都可能不一样,而且完全独立,不同步。比如对于一台汽车,有数据采集点专门采集GPS位置,有数据采集点专门采集发动机状态,有数据采集点专门采集车内的环境,这样一台汽车就有三个数据采集点。
## 关系型数据库模型
因为采集的数据一般是结构化数据,同时为降低学习门槛,TDengine 采用传统的关系型数据库模型管理数据。用户需要先创建库,然后创建表,之后才能插入或查询数据。TDengine 采用的是结构化存储,而不是 NoSQL 的 key-value 存储。
与通用数据库相比,TDengine通过一个数据采集点一张表,来大幅提高单个数据采集点的插入和查询速度。同时TDengine引入了超级表的概念,让每个表都带有标签,解决多个数据采集点之间的聚合分析问题。
持续按照预设频率生成数据的软件或硬件设备称为数据采集点。TDengine中推荐一个数据采集点生成的数据存储在对应的一个或若干个表中。采集点产生的数据通常是包括时间戳、测量值、标签等必要信息构成的元组。
## 一个数据采集点一张表
## 采集量
为充分利用其数据的时序性和其他数据特点,TDengine 要求**对每个数据采集点单独建表**(比如有一千万个智能电表,就需创建一千万张表,上述表格中的 d1001,d1002,d1003,d1004 都需单独建表),用来存储这个采集点所采集的时序数据。这种设计有几大优点:
数据采集点生成的具有时间、测量值、标签的元组信息。除了时间戳、标签信息以外的测量值称为采集量。
1. 由于不同采集设备产生数据的过程完全独立,每个设备的数据源是唯一的,一张表也就只有一个写入者,这样就可采用无锁方式来写,写入速度就能大幅提升。
2. 对于一个数据采集点而言,其产生的数据是按照时间排序的,因此写的操作可用追加的方式实现,进一步大幅提高数据写入速度。
3. 一个数据采集点的数据是以块为单位连续存储的。如果读取一个时间段的数据,它能大幅减少随机读取操作,成数量级的提升读取和查询速度。
4. 一个数据块内部,采用列式存储,对于不同数据类型,采用不同压缩算法,而且由于一个数据采集点的采集量的变化是缓慢的,压缩率更高。
## 标签
如果采用传统的方式,将多个设备的数据写入一张表,由于网络延时不可控,不同设备的数据到达服务器的时序是无法保证的,写入操作是要有锁保护的,而且一个设备的数据是难以保证连续存储在一起的。**采用一个数据采集点一张表的方式,能最大程度的保证单个数据采集点的插入和查询的性能是最优的。**
表的结构化描述信息,以一维数组形式存在。标签模式需要在创建超级表的时候指定,后续可动态调整。只有基于超级表创建的子表才具有标签。标签信息的内容首次创建子表的时候指定,并可按需调整。可以看到,TDengine中标签信息是表级别,而不是记录级别
TDengine 建议用数据采集点的名字(如上表中的 D1001)来做表名。每个数据采集点可能同时采集多个物理量(如上表中的 curent,voltage,phase),每个物理量对应一张表中的一列,数据类型可以是整型、浮点型、字符串等。除此之外,表的第一列必须是时间戳,即数据类型为 timestamp。对采集的数据,TDengine 将自动按照时间戳建立索引,但对采集的物理量不建任何索引。数据用列式存储方式保存
## 数据库
对于复杂的设备,比如汽车,它有多个数据采集点,那么就需要为一台汽车建立多张表。
TDengine中数据库与普通数据库管理系统中的数据库语义和行为相同,但是结合应用需求增加了若干配置参数用以控制其行为。
## 超级表:同一类型数据采集点的集合
## 超级表
由于一个数据采集点一张表,导致表的数量巨增,难以管理,而且应用经常需要做采集点之间的聚合操作,聚合的操作也变得复杂起来。为解决这个问题,TDengine 引入超级表(Super Table,简称为 STable)的概念。
超级表(Super Table, STable)是TDengine中一个重要的概念。超级表是面向相同数据模式的数据表,提供(数据+标签)模式管理和查询处理的逻辑抽象。通常将基于超级表创建的表称为该超级表的子表,并在系统内部建立逻辑关联。超级表与(基于其创建的)子表的关系体现在以下几个方面:
超级表是指某一特定类型的数据采集点的集合。同一类型的数据采集点,其表的结构是完全一样的,但每个表(数据采集点)的静态属性(标签)是不一样的。描述一个超级表(某一特定类型的数据采集点的集合),除需要定义采集量的表结构之外,还需要定义其标签的 schema,标签的数据类型可以是整数、浮点数、字符串,标签可以有多个,可以事后增加、删除或修改。如果整个系统有 N 个不同类型的数据采集点,就需要建立 N 个超级表。
超级表的子表共享其数据模式和标签模式。因此,不能通过子表调整数据或标签的模式。对于超级表的数据模式修改立即对所有的子表生效。
在 TDengine 的设计里,**表用来代表一个具体的数据采集点,超级表用来代表一组相同类型的数据采集点集合**。当为某个具体数据采集点创建表时,用户使用超级表的定义做模板,同时指定该具体采集点(表)的标签值。与传统的关系型数据库相比,表(一个数据采集点)是带有静态标签的,而且这些标签可以事后增加、删除、修改。超级表与与基于超级表建立的子表之间的关系表现在:
超级表自身不能存储任何数据或标签信息。因此,不能向一个超级表写入数据,只能将数据写入子表中。
1. 一张超级表包含有多张子表,这些子表具有相同的采集量 schema,但带有不同的标签值。
2. 不能通过子表调整数据或标签的模式,对于超级表的数据模式修改立即对所有的子表生效。
3. 超级表只定义一个模板,自身不存储任何数据或标签信息。因此,不能向一个超级表写入数据,只能将数据写入子表中。
针对超级表的查询,将所有子表中的数据视为一个整体数据集进行处理。但是可以直接发起针对某个或若干个子表的查询,此时查询请求将该子表视为一个普通的表进行处理
针对超级表的查询,TDengine将把所有子表中的数据视为一个整体数据集进行处理,会先把满足标签过滤条件的表从超级表中找出来,然后再扫描这些表的时序数据,进行聚合操作,这样需要扫描的数据集会大幅减少,从而显著提高查询的性能。本质上,TDengine通过对超级表查询的支持,实现了多个同类数据采集点的高效聚合
##
## FQDN & End Point
一系列二维数组的集合,用来代表和储存数据对象之间的关系,由纵向的列和横向的行组成。TDengine中的表与普通数据库中的表没有差别
FQDN (fully qualified domain name, 完全限定域名)是 Internet 上特定计算机或主机的完整域名。FQDN由两部分组成:主机名和域名。例如,假设邮件服务器的FQDN可能是mail.tdengine.com。主机名是mail,主机位于域名tdengine.com中。DNS(Domain Name System),负责将FQDN翻译成IP,是互联网应用的寻址方式。对于没有DNS的系统,可以通过配置hosts文件来解决
但是,对于通过超级表创建的子表,还具有额外的标签数据信息。不能针对某个子表调整数据模式。每个子表具有与其关联的标签数据,并可按需调整内容。但是模式调整必须要通过超级表模式调整来完成
TDengine集群的每个节点是由End Point来唯一标识的,End Point是由 FQDN 外加 Port 组成,比如 h1.tdengine.com:6030。这样当IP发生变化的时候,我们依然可以使用 FQDN 来动态找到节点,不需要更改集群的任何配置。而且采用 FQDN,便于内网和外网对同一个集群的统一访问
使用TDengine存储和管理物联网数据的时候,推荐使用一个子表存储一个数据采集点生成的数据,而使用超级表用来代表一组相同类型的数据采集点的集合
TDengine 不建议采用直接的IP地址访问集群,不利于管理。不了解 FQDN 概念,请看博文[《一篇文章说清楚 TDengine 的 FQDN》](https://www.taosdata.com/blog/2020/09/11/1824.html)
# 立即开始
---
title: 立即开始
description: " Docker,安装包或使用 apt-get 快速安装 TDengine, 通过命令行程序TAOS CLI和工具 taosdemo 快速体验 TDengine 功能"
---
## 从 Docker 快速开始
import Tabs from "@theme/Tabs";
import TabItem from "@theme/TabItem";
import PkgInstall from "./\_pkg_install.mdx";
import AptGetInstall from "./\_apt_get_install.mdx";
## 安装
TDengine 完整的软件包包括服务端(taosd)、用于与第三方系统对接并提供RESTful接口的taosAdapter、应用驱动(taosc)、命令行程序 (CLI,taos) 和一些工具软件,目前 2.X 版服务端taosd、taosAdapter 仅在 Linux 系统上安装和运行,后续将支持 Windows、macOS 等系统。应用驱动 taosc 与 TDengine CLI 可以在 Windows 或 Linux 上安装和运行。TDengine 除 RESTful接口外,还提供一些列编程语言的连接器。2.4 之前的版本中,无 taosAdapter,RESTfule 接口均由 taosd 内置的 http 服务提供。
TDengine 支持 X64/ARM64/MIPS64/Alpha64 硬件平台,后续将支持 ARM32、RISC-V 等 CPU 架构。
<Tabs defaultValue="apt-get">
<TabItem value="docker" label="Docker">
如果已经安装了 docker, 只需执行下面的命令。
```shell
......@@ -22,46 +36,32 @@ docker exec -it <containrid> bash
然后就可以执行相关的 Linux 命令操作和访问 TDengine
详细操作方法请参照 [通过 Docker 快速体验 TDengine](/train-fqa/docker)
详细操作方法请参照 [通过 Docker 快速体验 TDengine](/train-faq/docker)
:::info
从 2.4.0.10 开始,除 taosd 以外,Docker 镜像还包含:taos、taosAdapter、taosdump、taosBenchmark、TDinsight 安装脚本和示例代码。启动 Docker 容器时,将同时启动 taosAdapter 和 taosd,实现对 RESTful 的支持。
:::
:::note
暂时不建议生产环境采用 Docker 来部署 TDengine 的客户端或服务端,但在开发环境下或初次尝试时,使用 Docker 方式部署是十分方便的。特别是,利用 Docker,可以方便地在 macOS 和 Windows 环境下尝试 TDengine。
:::
## 安装
</TabItem>
<TabItem value="apt-get" label="apt-get">
<AptGetInstall />
</TabItem>
<TabItem value="pkg" label="安装包">
<PkgInstall />
</TabItem>
<TabItem value="src" label="源码">
import Tabs from "@theme/Tabs";
import TabItem from "@theme/TabItem";
import PkgInstall from "./\_pkg_install.mdx";
import AptGetInstall from "./\_apt_get_install.mdx";
import SrcInstall from "./\_src_install.mdx";
如果您希望对 TDengine 贡献代码或对内部实现感兴趣,请参考我们的 [TDengine GitHub 主页](https://github.com/taosdata/TDengine) 下载源码构建和安装.
TDengine 包括服务端、客户端和周边生态工具软件,目前 2.0 版服务端仅在 Linux 系统上安装和运行,后续将支持 Windows、macOS 等系统。客户端可以在 Windows 或 Linux 上安装和运行。在任何操作系统上的应用都可以使用 RESTful 接口连接服务端程序 taosd,其中 2.4 之后版本默认使用单独运行的独立组件 taosAdapter 提供 http 服务和更多数据写入方式。taosAdapter 需要手动启动。
之前版本 TDengine 服务端,以及所有服务端 lite 版,均使用内置 http 服务。
下载其他组件、最新 Beta 版及之前版本的安装包,请点击[这里](https://www.taosdata.com/cn/all-downloads/)
TDengine 支持 X64/ARM64/MIPS64/Alpha64 硬件平台,后续将支持 ARM32、RISC-V 等 CPU 架构。
<Tabs defaultValue="apt-get">
<TabItem value="apt-get" label="apt-get">
<AptGetInstall />
</TabItem>
<TabItem value="pkg" label="安装包">
<PkgInstall />
</TabItem>
<TabItem value="src" label="源码">
<SrcInstall />
</TabItem>
</TabItem>
</Tabs>
## 启动
使用 `systemctl` 命令来启动 TDengine 的服务进程。
安装后,请使用 `systemctl` 命令来启动 TDengine 的服务进程。
```bash
systemctl start taosd
......@@ -79,7 +79,7 @@ systemctl status taosd
- systemctl 命令需要 _root_ 权限来运行,如果您非 _root_ 用户,请在命令前添加 sudo 。
- 为更好的获得产品反馈,改善产品,TDengine 会采集基本的使用信息,但您可以修改系统配置文件 taos.cfg 里的配置参数 telemetryReporting,将其设为 0,就可将其关闭。
- TDengine 采用 FQDN(一般就是 hostname)作为节点的 ID,为保证正常运行,需要给运行 taosd 的服务器配置好 hostname,在客户端应用运行的机器配置好 DNS 服务或 hosts 文件,保证 FQDN 能够解析。
- TDengine 采用 FQDN(一般就是 hostname)作为节点的 ID,为保证正常运行,需要给运行 taosd 的服务器配置好 FQDN,在 TDengine CLI 或应用运行的机器配置好 DNS 服务或 hosts 文件,保证 FQDN 能够解析。
- `systemctl stop taosd` 指令在执行后并不会马上停止 TDengine 服务,而是会等待系统中必要的落盘工作正常完成。在数据量很大的情况下,这可能会消耗较长时间。
TDengine 支持在使用 [`systemd`](https://en.wikipedia.org/wiki/Systemd) 做进程服务管理的 Linux 系统上安装,用 `which systemctl` 命令来检测系统中是否存在 `systemd` 包:
......@@ -92,23 +92,23 @@ which systemctl
:::note
## 进入命令行
## TDengine 命令行 (CLI)
执行 TDengine 客户端程序,您只要在 Linux 终端执行 `taos` 即可。
为便于检查 TDengine 的状态,执行各种即席(Ad Hoc)查询,TDengine 提供一命令行应用程序(以下简称为 TDengine CLI) taos。要进入 TDengine 命令行,您只要在安装有 TDengine 的 Linux 终端执行 `taos` 即可。
```bash
taos
```
如果连接服务成功,将会打印出欢迎消息和版本信息。如果失败,则会打印错误消息出来(请参考 [FAQ](/train-fqa/faq) 来解决终端连接服务端失败的问题)。客户端的提示符号如下:
如果连接服务成功,将会打印出欢迎消息和版本信息。如果失败,则会打印错误消息出来(请参考 [FAQ](/train-faq/faq) 来解决终端连接服务端失败的问题)。 TDengine CLI 的提示符号如下:
```cmd
taos>
```
在 TDengine 客户端中,用户可以通过 SQL 命令来创建/删除数据库、表等,并进行插入查询操作。在终端中运行的 SQL 语句需要以分号结束来运行。示例:
在 TDengine CLI中,用户可以通过 SQL 命令来创建/删除数据库、表等,并进行插入查询操作。在终端中运行的 SQL 语句需要以分号结束来运行。示例:
```mysql
```sql
create database demo;
use demo;
create table t (ts timestamp, speed int);
......@@ -122,45 +122,11 @@ select * from t;
Query OK, 2 row(s) in set (0.003128s)
```
除执行 SQL 语句外,系统管理员还可以从 TDengine 客户端进行检查系统运行状态、添加删除用户账号等操作。
## 命令行参数
您可通过配置命令行参数来改变 TDengine 客户端的行为。以下为常用的几个命令行参数:
- -c, --config-dir: 指定配置文件目录,默认为 `/etc/taos`
- -h, --host: 指定服务的 FQDN 地址或 IP 地址,默认为连接本地服务
- -s, --commands: 在不进入终端的情况下运行 TDengine 命令
- -u, --user: 连接 TDengine 服务端的用户名,缺省为 root
- -p, --password: 连接 TDengine 服务端的密码,缺省为 taosdata
- -?, --help: 打印出所有命令行参数
示例:
```bash
taos -h h1.taos.com -s "use db; show tables;"
```
## 运行 SQL 命令脚本
TDengine 终端可以通过 `source` 命令来运行 SQL 命令脚本。
```mysql
taos> source <filename>;
```
## taos shell 小技巧
- 可以使用上下光标键查看历史输入的指令
- 修改用户密码:在 shell 中使用 `alter user` 命令,缺省密码为 taosdata
- ctrl+c 中止正在进行中的查询
- 执行 `RESET QUERY CACHE` 可清除本地缓存的表 schema
- 批量执行 SQL 语句。可以将一系列的 shell 命令(以英文 ; 结尾,每个 SQL 语句为一行)按行存放在文件里,在 shell 里执行命令 `source <file-name>` 自动执行该文件里所有的 SQL 语句
- 输入 q 回车,退出 taos shell
除执行 SQL 语句外,系统管理员还可以从 TDengine CLI 进行检查系统运行状态、添加删除用户账号等操作。TAOS CLI 连同应用驱动也可以独立安装在 Linux 或 windows 机器上运行,更多细节请参考 [这里](../reference/taos-shell/)
## 使用 taosBenchmark 体验写入速度
启动 TDengine 的服务,在 Linux 终端执行 `taosBenchmark` (曾命名为 taosdemo):
启动 TDengine 的服务,在 Linux 终端执行 `taosBenchmark` (曾命名为 `taosdemo`):
```bash
taosBenchmark
......@@ -170,42 +136,38 @@ taosBenchmark
这条命令很快完成 1 亿条记录的插入。具体时间取决于硬件性能,即使在一台普通的 PC 服务器往往也仅需十几秒。
## taosBenchmark 详细功能列表
taosBenchmark 命令本身带有很多选项,配置表的数目、记录条数等等,请执行 `taosBenchmark --help` 详细列出。您可以设置不同参数进行体验。
taosBenchmark 详细使用方法请参照 [如何使用 taosBenchmark 对 TDengine 进行性能测试](https://www.taosdata.com/2021/10/09/3111.html)
taosBenchmark 命令本身带有很多选项,配置表的数目、记录条数等等,您可以设置不同参数进行体验,请执行 `taosBenchmark --help` 详细列出。taosBenchmark 详细使用方法请参照 [如何使用 taosBenchmark 对 TDengine 进行性能测试](https://www.taosdata.com/2021/10/09/3111.html)
## 使用 taos shell 体验查询速度
## 使用 TDengine CLI 体验查询速度
在 TDengine 客户端输入查询命令,体验查询速度。
使用上述 taosBenchmark 插入数据后,可以在 TDengine CLI 输入查询命令,体验查询速度。
查询超级表下记录总条数:
```mysql
```sql
taos> select count(*) from test.meters;
```
查询 1 亿条记录的平均值、最大值、最小值等:
```mysql
```sql
taos> select avg(current), max(voltage), min(phase) from test.meters;
```
查询 location="beijing" 的记录总条数:
```mysql
```sql
taos> select count(*) from test.meters where location="beijing";
```
查询 groupId=10 的所有记录的平均值、最大值、最小值等:
```mysql
```sql
taos> select avg(current), max(voltage), min(phase) from test.meters where groupId=10;
```
对表 d10 按 10s 进行平均值、最大值和最小值聚合统计:
```mysql
```sql
taos> select avg(current), max(voltage), min(phase) from test.d10 interval(10s);
```
如果,可以使用 apt-get 工具从官方仓库安装。
可以使用 apt-get 工具从官方仓库安装。
**安装包仓库**
......
import PkgList from "./_pkg_list.mdx";
TDengine 的安装非常简单,从下载到安装成功仅仅只要几秒钟。
为方便使用,从 2.4.0.10 开始,标准的服务端安装包包含了 taos、taosd、taosAdapter、taosdump、taosBenchmark、TDinsight 安装脚本和示例代码;如果您只需要用到服务端程序和客户端连接的 C/C++ 语言支持,也可以仅下载 lite 版本的安装包。
......@@ -8,6 +6,51 @@ TDengine 的安装非常简单,从下载到安装成功仅仅只要几秒钟
发布版本包括稳定版和 Beta 版,Beta 版含有更多新功能。正式上线或测试建议安装稳定版。您可以根据需要选择下载:
<PkgList />
<ul id="server-packageList" class="package-list">
<li>
<a id="tdengine_rpm" name="TDengine RPM">
TDengine-server-2.4.0.16-Linux-x64.rpm (14.5 M)
</a>
</li>
<li>
<a id="tdengine_deb" name="TDengine DEB">
TDengine-server-2.4.0.16-Linux-x64.deb (12.8 M)
</a>
</li>
<li>
<a id="tdengine_tar" name="TDengine Tarball">
TDengine-server-2.4.0.16-Linux-x64.tar.gz (15.5 M)
</a>
</li>
<li>
<a id="tdengine_Lite_tar" name="undefined">
TDengine-server-2.4.0.16-Linux-x64-Lite.tar.gz (3.4 M)
</a>
</li>
<li>
<a id="tdengine_Lite_beta_tar" name="TDengine Lite Beta Tarball">
TDengine-server-2.3.5.0-beta-Linux-x64-Lite.tar.gz (3 M)
</a>
</li>
<li>
<a id="tdengine_beta_rpm" name="TDengine Beta RPM">
TDengine-server-2.3.5.0-beta-Linux-x64.rpm (18.4 M)
</a>
</li>
<li>
<a id="tdengine_beta_deb" name="TDengine Beta DEB">
TDengine-server-2.3.5.0-beta-Linux-x64.deb (16.8 M)
</a>
</li>
<li>
<a id="tdengine_beta_tar" name="TDengine Beta Tarball">
TDengine-server-2.3.5.0-beta-Linux-x64.tar.gz (18.8 M)
</a>
</li>
</ul>
具体的安装方法,请参见[安装包的安装和卸载](/operation/pkg-install)。
下载其他组件、最新 Beta 版及之前版本的安装包,请点击[这里](https://www.taosdata.com/all-downloads)
具体的安装方法,请参见 [安装包的安装和卸载](/operation/pkg-install) 以及 [视频教程](https://www.taosdata.com/blog/2020/11/11/1941.html)
请点击[这里](https://github.com/taosdata/TDengine/releases) 查看 Release Notes
**最新安装包**
<ul id="server-packageList" className="package-list">
<li>
<a id="tdengine_rpm" name="TDengine RPM">
TDengine-server-2.4.0.12-Linux-x64.rpm (14.5 M)
</a>
</li>
<li>
<a id="tdengine_deb" name="TDengine DEB">
TDengine-server-2.4.0.12-Linux-x64.deb (12.8 M)
</a>
</li>
<li>
<a id="tdengine_tar" name="TDengine Tarball">
TDengine-server-2.4.0.12-Linux-x64.tar.gz (15.5 M)
</a>
</li>
<li>
<a id="tdengine_Lite_tar" name="undefined">
TDengine-server-2.4.0.12-Linux-x64-Lite.tar.gz (3.4 M)
</a>
</li>
<li>
<a id="tdengine_Lite_beta_tar" name="TDengine Lite Beta Tarball">
TDengine-server-2.3.5.0-beta-Linux-x64-Lite.tar.gz (3 M)
</a>
</li>
<li>
<a id="tdengine_beta_rpm" name="TDengine Beta RPM">
TDengine-server-2.3.5.0-beta-Linux-x64.rpm (18.4 M)
</a>
</li>
<li>
<a id="tdengine_beta_deb" name="TDengine Beta DEB">
TDengine-server-2.3.5.0-beta-Linux-x64.deb (16.8 M)
</a>
</li>
<li>
<a id="tdengine_beta_tar" name="TDengine Beta Tarball">
TDengine-server-2.3.5.0-beta-Linux-x64.tar.gz (18.8 M)
</a>
</li>
</ul>
**所有下载**
https://www.taosdata.com/all-downloads
如果您希望对 TDengine 贡献代码或对内部实现感兴趣,请参考我们的 [TDengine GitHub 主页](https://github.com/taosdata/TDengine) 下载源码构建和安装.
下载其他组件、最新 Beta 版及之前版本的安装包,请点击[这里](https://www.taosdata.com/cn/all-downloads/)。
---
sidebar_label: 建立连接
sidebar_position: 4
---
# 建立连接
import Tabs from "@theme/Tabs";
import TabItem from "@theme/TabItem";
import ConnRest from "./_connect_restful.mdx";
import ConnJava from "./_connect_java.mdx";
import ConnGo from "./_connect_go.mdx";
import ConnRust from "./_connect_rust.mdx";
import ConnNode from "./_connect_node.mdx";
import ConnJavaNative from "./_connect_java_native.mdx";
import ConnPythonNative from "./_connect_python_native.mdx";
import ConnGoNative from "./_connect_go_native.mdx";
import ConnRustNative from "./_connect_rust_native.mdx";
import ConnNodeNative from "./_connect_node_native.mdx";
import ConnCSNative from "./_connect_cs_native.mdx";
import ConnC from "./_connect_c.mdx";
## 连接器介绍
TDengine 提供了丰富的应用程序开发接口,其中包括 C/C++、Java、Python、Go、Node.js、C# 、RESTful 等,便于用户快速开发应用。
![image-connecotr](/img/connector.png)
<center>(图:连接器工作原理)</center>
TDengine 提供了 RESTful 接口,应用程序无需安装任何依赖,只需发送 HTTP 请求就可以连接到 TDengine。同时也提供了各语言的连接器,使用驱动程序 (taosc) 连接 TDengine。通过驱动程序可以使用 TDengine 更丰富的功能。
## 前提条件
在执行这一步之前,请确保有一个正在运行的,且可以访问到的 TDengine。以下所有示例代码,都假设 TDengine 安装在本机,且 fqdn(默认 localhost) 和 serverPort(默认 6030) 都使用默认配置。
## 建立连接
### RESTful
如果你安装的是 TDengine 2.4 之后的版本,使用 RESTful 方式连接时还需启动 taosAdaper。
<Tabs groupId="lang">
<TabItem label="curl" value="">
<ConnRest />
</TabItem>
<TabItem label="Java" value="java">
<ConnJava />
</TabItem>
<TabItem label="Go" value="go">
<ConnGo />
</TabItem>
<TabItem label="Rust" value="rust">
<ConnRust />
</TabItem>
<TabItem label="Node.js" value="node">
<ConnNode />
</TabItem>
</Tabs>
### 本地驱动
在没有安装 TDengine 服务端软件的系统上使用本地驱动连接 TDengine, 需要提前[安装客户端驱动程序](/reference/connector/#安装客户端驱动)。
:::note
需要单独安装客户端时,为避免客户端驱动和服务端不兼容,请尽量使用一致的版本。
:::
<Tabs groupId="lang" defaultValue="java">
<TabItem label="Java" value="java">
<ConnJavaNative />
</TabItem>
<TabItem label="Python" value="Python">
<ConnPythonNative />
</TabItem>
<TabItem label="Go" value="go">
<ConnGoNative />
</TabItem>
<TabItem label="Rust" value="rust">
<ConnRustNative />
</TabItem>
<TabItem label="Node.js" value="node">
<ConnNodeNative />
</TabItem>
<TabItem label="C#" value="csharp">
<ConnCSNative />
</TabItem>
<TabItem label="C" value="c">
<ConnC />
</TabItem>
</Tabs>
首先添加 [TDengine.Connector](https://www.nuget.org/packages/TDengine.Connector/) 的引用:
```bash
dotnet add package TDengine.Connector
```
```csharp
{{#include docs-examples/csharp/ConnectExample.cs}}
```
```go-mod title=go.mod
module goexample
go 1.17
require github.com/taosdata/driver-go/v2 develop
```
```go
{{#include docs-examples/go/connect/restexample/main.go}}
```
:::note
driver-go 使用 cgo 封装了 taosc 的 API。cgo 需要使用 gcc 编译 C 的源码。因此需要确保你的系统上有 gcc。
:::
```go-mod title=go.mod
module goexample
go 1.17
require github.com/taosdata/driver-go/v2 develop
```
```go
{{#include docs-examples/go/connect/cgoexample/main.go}}
```
```xml title=pom.xml
<dependency>
<groupId>com.taosdata.jdbc</groupId>
<artifactId>taos-jdbcdriver</artifactId>
<version>2.0.37</version>
</dependency>
```
```java
{{#include docs-examples/java/src/main/java/com/taos/example/RESTConnectExample.java}}
```
```xml title=pom.xml
<dependency>
<groupId>com.taosdata.jdbc</groupId>
<artifactId>taos-jdbcdriver</artifactId>
<version>2.0.37</version>
</dependency>
```
```java
{{#include docs-examples/java/src/main/java/com/taos/example/JNIConnectExample.java}}
```
推荐使用 `python >= 3.4`。首先需要安装 python 连接器 `taospy`。执行以下命令即可:
```
pip3 install taospy
```
```python
{{#include docs-examples/python/connect_exmaple.py}}
```
下面用 curl 工具来演示访问 RESTful 接口。在命令行执行下面的命令:
```bash
curl http://localhost:6041/rest/sql -u root:taosdata -d "select server_version()"
```
- `-u` 用于指定访问数据库的用户名和密码。
- `-d` 用于指定发送要执行的 SQL 语句。它会被放入 POST 请求的 Body 中。
如果正常,会返回一个 JSON 字符串,里面包含了服务端的版本。例如:
```json
{
"status": "succ",
"head": ["server_version()"],
"column_meta": [["server_version()", 8, 7]],
"data": [["2.4.0.0"]],
"rows": 1
}
```
了解更多:[RESTful API](/reference/restful-api)。
```toml title=Cargo.toml
[dependencies]
libtaos = { version = "*", features = ["rest"] }
```
```rust
{{#include docs-examples/rust/restexample/examples/connect.rs}}
```
```toml title=Cargo.toml
[dependencies]
libtaos = { version = "0.4.2"}
```
```rust
{{#include docs-examples/rust/nativeexample/examples/connect.rs}}
```
```c
```c title="原生连接"
{{#include docs-examples/c/connect_example.c}}
```
```csharp title="原生连接"
{{#include docs-examples/csharp/ConnectExample.cs}}
```
:::info
C# 连接器目前只支持原生连接。
:::
\ No newline at end of file
#### 使用数据库访问统一接口
```go title="原生连接"
{{#include docs-examples/go/connect/cgoexample/main.go}}
```
```go title="REST 连接"
{{#include docs-examples/go/connect/restexample/main.go}}
```
#### 使用高级封装
也可以使用 driver-go 的 af 包建立连接。这个模块封装了 TDengine 的高级功能, 如:参数绑定、订阅等。
```go title="使用 af 包建立原生连接"
{{#include docs-examples/go/connect/afconn/main.go}}
```
```java title="原生连接"
{{#include docs-examples/java/src/main/java/com/taos/example/JNIConnectExample.java}}
```
```java title="REST 连接"
{{#include docs-examples/java/src/main/java/com/taos/example/RESTConnectExample.java:main}}
```
使用REST 连接时,如果查询数据量比较大,还可开启批量拉取功能。
```java title="开启批量拉取功能" {4}
{{#include docs-examples/java/src/main/java/com/taos/example/WSConnectExample.java:main}}
```
更多连接参数配置,参考[Java 连接器](/reference/connector/java)
\ No newline at end of file
首先需要安装 node.js 的连接器 `td2.0-connector`:
```bash
npm install td2.0-connector
```
```js
```js title="原生连接"
{{#include docs-examples/node/nativeexample/connect.js}}
```
```js title="REST 连接"
{{#include docs-examples/node/restexample/connect.js}}
```
\ No newline at end of file
```python title="原生连接"
{{#include docs-examples/python/connect_exmaple.py}}
```
\ No newline at end of file
```r title="原生连接"
{{#include docs-examples/R/connect_native.r:demo}}
```
\ No newline at end of file
```rust title="原生连接/REST 连接"
{{#include docs-examples/rust/nativeexample/examples/connect.rs}}
```
:::note
对于 Rust 连接器, 连接方式的不同只体现在使用的特性不同。如果启用了 "rest" 特性,那么只有 RESTful 的实现会被编译进来。
:::
---
title: 建立连接
description: "本节介绍如何使用连接器建立与 TDengine 的连接,给出连接器安装、连接的简单说明。"
---
import Tabs from "@theme/Tabs";
import TabItem from "@theme/TabItem";
import ConnJava from "./_connect_java.mdx";
import ConnGo from "./_connect_go.mdx";
import ConnRust from "./_connect_rust.mdx";
import ConnNode from "./_connect_node.mdx";
import ConnPythonNative from "./_connect_python.mdx";
import ConnCSNative from "./_connect_cs.mdx";
import ConnC from "./_connect_c.mdx";
import ConnR from "./_connect_r.mdx";
import InstallOnWindows from "../../14-reference/03-connector/_linux_install.mdx";
import InstallOnLinux from "../../14-reference/03-connector/_windows_install.mdx";
import VerifyLinux from "../../14-reference/03-connector/_verify_linux.mdx";
import VerifyWindows from "../../14-reference/03-connector/_verify_windows.mdx";
TDengine 提供 REST API,容许在任何平台的任何应用程序通过它访问 TDengine 运行实例,详细介绍请看 [REST API](/reference/rest-api/)。除 REST API 之外,TDengine 还提供多种编程语言的连接器方便用户开发应用程序,其中包括 C/C++、Java、Python、Go、Node.js、C# 等。 本节介绍如何使用连接器建立与 TDengine 的连接,给出连接器安装、连接的简单说明。关于各连接器的详细功能说明,请查看[连接器](https://docs.taosdata.com/reference/connector/)
## 连接器建立连接的方式
连接器建立连接的方式,TDengine 提供两种:
1. 通过 taosAdapter 组件提供的 REST API 建立与 taosd 的连接,这种连接方式下文中简称"REST 连接“
2. 通过客户端驱动程序 taosc 直接与服务端程序 taosd 建立连接,这种连接方式下文中简称“原生连接”。
无论使用何种方式建立连接,连接器都提供了相同或相似的 API 操作数据库,都可以执行 SQL 语句,只是初始化连接的方式稍有不同,用户在使用上不会感到什么差别。
关键不同点在于:
1. 使用 REST 连接,用户无需安装客户端驱动程序 taosc,具有跨平台易用的优势,但性能要下降 30%左右。
2. 使用原生连接可以体验 TDengine 的全部功能,如[参数绑定接口](/reference/connector/cpp#参数绑定-api)[订阅](reference/connector/cpp#数据订阅接口)等等。
## 安装客户端驱动 taosc
如果选择原生连接,而且应用程序不在 TDengine 同一台服务器上运行,你需要先安装客户端驱动,否则可以跳过此一步。为避免客户端驱动和服务端不兼容,请使用一致的版本。
### 安装步骤
<Tabs defaultValue="linux" groupId="os">
<TabItem value="linux" label="Linux">
<InstallOnWindows />
</TabItem>
<TabItem value="windows" label="Windows">
<InstallOnLinux />
</TabItem>
</Tabs>
### 安装验证
以上安装和配置完成后,并确认 TDengine 服务已经正常启动运行,此时可以执行安装包里带有的 TDengine 命令行程序 taos 进行登录。
<Tabs defaultValue="linux" groupId="os">
<TabItem value="linux" label="Linux">
<VerifyLinux />
</TabItem>
<TabItem value="windows" label="Windows">
<VerifyWindows />
</TabItem>
</Tabs>
## 安装连接器
<Tabs groupId="lang">
<TabItem label="Java" value="java">
如果使用 maven 管理项目,只需在 pom.xml 中加入以下依赖。
```xml
<dependency>
<groupId>com.taosdata.jdbc</groupId>
<artifactId>taos-jdbcdriver</artifactId>
<version>2.0.38</version>
</dependency>
```
</TabItem>
<TabItem label="Python" value="python">
使用 `pip` 从 PyPI 安装:
```
pip install taospy
```
从 Git URL 安装:
```
pip install git+https://github.com/taosdata/taos-connector-python.git
```
</TabItem>
<TabItem label="Go" value="go">
编辑 `go.mod` 添加 `driver-go` 依赖即可。
```go-mod title=go.mod
module goexample
go 1.17
require github.com/taosdata/driver-go/v2 develop
```
:::note
driver-go 使用 cgo 封装了 taosc 的 API。cgo 需要使用 gcc 编译 C 的源码。因此需要确保你的系统上有 gcc。
:::
</TabItem>
<TabItem label="Rust" value="rust">
编辑 `Cargo.toml` 添加 `libtaos` 依赖即可。
```toml title=Cargo.toml
[dependencies]
libtaos = { version = "0.4.2"}
```
:::info
Rust 连接器通过不同的特性区分不同的连接方式。如果要建立 REST 连接,需要开启 `rest` 特性:
```toml
libtaos = { version = "*", features = ["rest"] }
```
:::
</TabItem>
<TabItem label="Node.js" value="node">
Node.js 连接器通过不同的包提供不同的连接方式。
1. 安装 Node.js 原生连接器
```
npm i td2.0-connector
```
:::note
推荐 Node 版本大于等于 `node-v12.8.0` 小于 `node-v13.0.0`
::: 2. 安装 Node.js REST 连接器
```
npm i td2.0-rest-connector
```
</TabItem>
<TabItem label="C#" value="csharp">
编辑项目配置文件中添加 [TDengine.Connector](https://www.nuget.org/packages/TDengine.Connector/) 的引用即可:
```xml title=csharp.csproj {12}
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net6.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
<StartupObject>TDengineExample.AsyncQueryExample</StartupObject>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="TDengine.Connector" Version="1.0.6" />
</ItemGroup>
</Project>
```
也可通过 dotnet 命令添加:
```
dotnet add package TDengine.Connector
```
:::note
以下示例代码,均基于 dotnet6.0,如果使用其它版本,可能需要做适当调整。
:::
</TabItem>
<TabItem label="R" value="r">
1. 下载 [taos-jdbcdriver-version-dist.jar](https://repo1.maven.org/maven2/com/taosdata/jdbc/taos-jdbcdriver/2.0.38/)
2. 安装 R 的依赖包`RJDBC`
```R
install.packages("RJDBC")
```
</TabItem>
<TabItem label="C" value="c">
如果已经安装了 TDengine 服务端软件或 TDengine 客户端驱动 taosc, 那么已经安装了 C 连接器,无需额外操作。
<br/>
</TabItem>
</Tabs>
## 建立连接
在执行这一步之前,请确保有一个正在运行的,且可以访问到的 TDengine,而且服务端的 FQDN 配置正确。以下示例代码,都假设 TDengine 安装在本机,且 FQDN(默认 localhost) 和 serverPort(默认 6030) 都使用默认配置。
<Tabs groupId="lang" defaultValue="java">
<TabItem label="Java" value="java">
<ConnJava />
</TabItem>
<TabItem label="Python" value="python">
<ConnPythonNative />
</TabItem>
<TabItem label="Go" value="go">
<ConnGo />
</TabItem>
<TabItem label="Rust" value="rust">
<ConnRust />
</TabItem>
<TabItem label="Node.js" value="node">
<ConnNode />
</TabItem>
<TabItem label="C#" value="csharp">
<ConnCSNative />
</TabItem>
<TabItem label="R" value="r">
<ConnR/>
</TabItem>
<TabItem label="C" value="c">
<ConnC />
</TabItem>
</Tabs>
:::tip
如果建立连接失败,大部分情况下是 FQDN 或防火墙的配置不正确,详细的排查方法请看[《常见问题及反馈》](https://docs.taosdata.com/train-faq/faq)中的“遇到错误 Unable to establish connection, 我怎么办?”
:::
# TDengine 数据建模
---
slug: /model
title: TDengine 数据建模
---
TDengine 采用关系型数据模型,需要建库、建表。因此对于一个具体的应用场景,需要考虑库、超级表和普通表的设计。本节不讨论细致的语法规则,只介绍概念。
TDengine 采用关系型数据模型,需要建库、建表。因此对于一个具体的应用场景,需要考虑库、超级表和普通表的设计。本节不讨论细致的语法规则,只介绍概念。
关于数据建模请参考[视频教程](https://www.taosdata.com/blog/2020/11/11/1945.html)。
## 创建库
不同类型的数据采集点往往具有不同的数据特征,包括数据采集频率的高低,数据保留时间的长短,副本的数目,数据块的大小,是否允许更新数据等等。为了在各种场景下 TDengine 都能最大效率的工作,TDengine 建议将不同数据特征的表创建在不同的库里,因为每个库可以配置不同的存储策略。创建一个库时,除 SQL 标准的选项外,应用还可以指定保留时长、副本数、内存块个数、时间精度、文件块里最大最小记录条数、是否压缩、一个数据文件覆盖的天数等多种参数。比如:
不同类型的数据采集点往往具有不同的数据特征,包括数据采集频率的高低,数据保留时间的长短,副本的数目,数据块的大小,是否允许更新数据等等。为了在各种场景下 TDengine 都能最大效率的工作,TDengine 建议将不同数据特征的表创建在不同的库里,因为每个库可以配置不同的存储策略。创建一个库时,除 SQL 标准的选项外,还可以指定保留时长、副本数、内存块个数、时间精度、文件块里最大最小记录条数、是否压缩、一个数据文件覆盖的天数等多种参数。比如:
```sql
CREATE DATABASE power KEEP 365 DAYS 10 BLOCKS 6 UPDATE 1;
```
上述语句将创建一个名为 power 的库,这个库的数据将保留 365 天(超过 365 天将被自动删除),每 10 天一个数据文件,内存块数为 6,允许更新数据。详细的语法及参数请见 [数据库管理](/reference/taos-sql/database) 章节。
上述语句将创建一个名为 power 的库,这个库的数据将保留 365 天(超过 365 天将被自动删除),每 10 天一个数据文件,内存块数为 6,允许更新数据。详细的语法及参数请见 [数据库管理](/taos-sql/database) 章节。
创建库之后,需要使用 SQL 命令 `USE` 将当前库切换过来,例如:
......@@ -24,7 +27,7 @@ USE power;
:::note
- 任何一张表或超级表是属于一个库的,在创建表之前,必须先创建库。
- 任何一张表或超级表必须属于某个库,在创建表之前,必须先创建库。
- 处于两个不同库的表是不能进行 JOIN 操作的。
- 创建并插入记录、查询历史记录的时候,均需要指定时间戳。
......@@ -42,11 +45,11 @@ CREATE STABLE meters (ts timestamp, current float, voltage int, phase float) TAG
这一指令中的 STABLE 关键字,在 2.0.15 之前的版本中需写作 TABLE 。
:::
与创建普通表一样,创建表时,需要提供表名(示例中为 meters),表结构 Schema,即数据列的定义。第一列必须为时间戳(示例中为 ts),其他列为采集的物理量(示例中为 current, voltage, phase),数据类型可以为整型、浮点型、字符串等。除此之外,还需要提供标签的 schema (示例中为 location, groupId),标签的数据类型可以为整型、浮点型、字符串等。采集点的静态属性往往可以作为标签,比如采集点的地理位置、设备型号、设备组 ID、管理员 ID 等等。标签的 schema 可以事后增加、删除、修改。具体定义以及细节请见 [TAOS SQL 的超级表管理](/reference/taos-sql/stable) 章节。
与创建普通表一样,创建超级表时,需要提供表名(示例中为 meters),表结构 Schema,即数据列的定义。第一列必须为时间戳(示例中为 ts),其他列为采集的物理量(示例中为 current, voltage, phase),数据类型可以为整型、浮点型、字符串等。除此之外,还需要提供标签的 schema (示例中为 location, groupId),标签的数据类型可以为整型、浮点型、字符串等。采集点的静态属性往往可以作为标签,比如采集点的地理位置、设备型号、设备组 ID、管理员 ID 等等。标签的 schema 可以事后增加、删除、修改。具体定义以及细节请见 [TAOS SQL 的超级表管理](/taos-sql/stable) 章节。
每一种类型的数据采集点需要建立一个超级表,因此一个物联网系统,往往会有多个超级表。对于电网,我们就需要对智能电表、变压器、母线、开关等都建立一个超级表。在物联网中,一个设备就可能有多个数据采集点(比如一台风力发电的风机,有的采集点采集电流、电压等电参数,有的采集点采集温度、湿度、风向等环境参数),这个时候,对这一类型的设备,需要建立多张超级表。一张超级表里包含的采集物理量必须是同时采集的(时间戳是一致的)。
每一种类型的数据采集点需要建立一个超级表,因此一个物联网系统,往往会有多个超级表。对于电网,我们就需要对智能电表、变压器、母线、开关等都建立一个超级表。在物联网中,一个设备就可能有多个数据采集点(比如一台风力发电的风机,有的采集点采集电流、电压等电参数,有的采集点采集温度、湿度、风向等环境参数),这个时候,对这一类型的设备,需要建立多张超级表。
一张超级表最多容许 1024 列,如果一个采集点采集的物理量个数超过 1024,需要建多张超级表来处理。一个系统可以有多个 DB,一个 DB 里可以有一到多个超级表。(从 2.1.7.0 版本开始,列数限制由 1024 列放宽到了 4096 列。)
一张超级表最多容许 4096 列 (在 2.1.7.0 版本之前,列数限制为 1024 列),如果一个采集点采集的物理量个数超过 4096,需要建多张超级表来处理。一个系统可以有多个 DB,一个 DB 里可以有一到多个超级表。
## 创建表
......@@ -56,10 +59,10 @@ TDengine 对每个数据采集点需要独立建表。与标准的关系型数
CREATE TABLE d1001 USING meters TAGS ("Beijing.Chaoyang", 2);
```
其中 d1001 是表名,meters 是超级表的表名,后面紧跟标签 Location 的具体标签值 ”Beijing.Chaoyang",标签 groupId 的具体标签值 2。虽然在创建表时,需要指定标签值,但可以事后修改。详细细则请见 [TAOS SQL 的表管理](/reference/taos-sql/table) 章节。
其中 d1001 是表名,meters 是超级表的表名,后面紧跟标签 Location 的具体标签值 ”Beijing.Chaoyang",标签 groupId 的具体标签值 2。虽然在创建表时,需要指定标签值,但可以事后修改。详细细则请见 [TAOS SQL 的表管理](/taos-sql/table) 章节。
:::warning
目前 TDengine 没有从技术层面限制使用一个 database (dbA)的超级表作为模板建立另一个 database (dbB)的子表,后续会禁止这种用法,不建议使用这种方法建表。
目前 TDengine 没有从技术层面限制使用一个 database (db1) 的超级表作为模板建立另一个 database (db2) 的子表,后续会禁止这种用法,不建议使用这种方法建表。
:::
......@@ -67,7 +70,7 @@ TDengine 建议将数据采集点的全局唯一 ID 作为表名(比如设备序
### 自动建表
在某些特殊场景中,用户在写数据时并不确定某个数据采集点的表是否存在,此时可在写入数据时使用自动建表语法来创建不存在的表,若该表已存在则不会建立新表。比如:
在某些特殊场景中,用户在写数据时并不确定某个数据采集点的表是否存在,此时可在写入数据时使用自动建表语法来创建不存在的表,若该表已存在则不会建立新表且后面的 USING 语句被忽略。比如:
```sql
INSERT INTO d1001 USING meters TAGS ("Beijng.Chaoyang", 2) VALUES (now, 10.2, 219, 0.32);
......@@ -75,7 +78,7 @@ 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`。
关于自动建表的详细语法请参见 [插入记录时自动建表](reference/taos-sql/insert#插入记录时自动建表) 章节。
关于自动建表的详细语法请参见 [插入记录时自动建表](/taos-sql/insert#插入记录时自动建表) 章节。
## 多列模型 vs 单列模型
......
# SQL 写入
---
title: SQL 写入
---
import Tabs from "@theme/Tabs";
import TabItem from "@theme/TabItem";
## SQL 写入
应用通过 C/C++, Java, Go, C#, Python, Node.js 连接器执行 SQL insert 语句来插入数据,用户还可以通过 TAOS Shell,手动输入 SQL insert 语句插入数据。比如下面这条 insert 就将一条记录写入到表 d1001 中:
```mysql
import JavaSQL from "./_java_sql.mdx";
import JavaStmt from "./_java_stmt.mdx";
import PySQL from "./_py_sql.mdx";
import PyStmt from "./_py_stmt.mdx";
import GoSQL from "./_go_sql.mdx";
import GoStmt from "./_go_stmt.mdx";
import RustSQL from "./_rust_sql.mdx";
import RustStmt from "./_rust_stmt.mdx";
import NodeSQL from "./_js_sql.mdx";
import NodeStmt from "./_js_stmt.mdx";
import CsSQL from "./_cs_sql.mdx";
import CsStmt from "./_cs_stmt.mdx";
import CSQL from "./_c_sql.mdx";
import CStmt from "./_c_stmt.mdx";
## SQL 写入简介
应用通过连接器执行 INSERT 语句来插入数据,用户还可以通过 TAOS Shell,手动输入 INSERT 语句插入数据。
### 一次写入一条
下面这条 INSERT 就将一条记录写入到表 d1001 中:
```sql
INSERT INTO d1001 VALUES (1538548685000, 10.3, 219, 0.31);
```
### 一次写入多条
TDengine 支持一次写入多条记录,比如下面这条命令就将两条记录写入到表 d1001 中:
```mysql
```sql
INSERT INTO d1001 VALUES (1538548684000, 10.2, 220, 0.23) (1538548696650, 10.3, 218, 0.25);
```
### 一次写入多表
TDengine 也支持一次向多个表写入数据,比如下面这条命令就向 d1001 写入两条记录,向 d1002 写入一条记录:
```mysql
```sql
INSERT INTO d1001 VALUES (1538548685000, 10.3, 219, 0.31) (1538548695000, 12.6, 218, 0.33) d1002 VALUES (1538548696800, 12.3, 221, 0.31);
```
详细的 SQL INSERT 语法规则请见 [TAOS SQL 的数据写入](https://www.taosdata.com/cn/documentation/taos-sql#insert) 章节
详细的 SQL INSERT 语法规则参考 [TAOS SQL 的数据写入](/taos-sql/insert)
:::tip
:::info
- 要提高写入效率,需要批量写入。一批写入的记录条数越多,插入效率就越高。但一条记录不能超过 16K,一条 SQL 语句总长度不能超过 1M 。
- TDengine 支持多线程同时写入,要进一步提高写入速度,一个客户端需要打开 20 个以上的线程同时写。但线程数达到一定数量后,无法再提高,甚至还会下降,因为线程频繁切换,带来额外开销。
:::
:::warning
- 对同一张表,如果新插入记录的时间戳已经存在,默认情形下(UPDATE=0)新记录将被直接抛弃,也就是说,在一张表里,时间戳必须是唯一的。如果应用自动生成记录,很有可能生成的时间戳是一样的,这样,成功插入的记录条数会小于应用插入的记录条数。如果在创建数据库时使用了 UPDATE 1 选项,插入相同时间戳的新记录将覆盖原有记录。
- 写入的数据的时间戳必须大于当前时间减去配置参数 keep 的时间。如果 keep 配置为 3650 天,那么无法写入比 3650 天还早的数据。写入数据的时间戳也不能大于当前时间加配置参数 days。如果 days 为 2,那么无法写入比当前时间还晚 2 天的数据。
......@@ -38,28 +66,64 @@ INSERT INTO d1001 VALUES (1538548685000, 10.3, 219, 0.31) (1538548695000, 12.6,
### 普通 SQL 写入
<Tabs defaultValue="java">
<TabItem label="Java" value="java"></TabItem>
<TabItem label="Python" value="Python"></TabItem>
<TabItem label="Go" value="go"></TabItem>
<TabItem label="C" value="c"></TabItem>
<TabItem label="Rust" value="rust"></TabItem>
<TabItem label="Node.js" value="nodejs"></TabItem>
<TabItem label="C#" value="csharp"></TabItem>
<Tabs defaultValue="java" groupId="lang">
<TabItem label="Java" value="java">
<JavaSQL />
</TabItem>
<TabItem label="Python" value="python">
<PySQL />
</TabItem>
<TabItem label="Go" value="go">
<GoSQL />
</TabItem>
<TabItem label="Rust" value="rust">
<RustSQL />
</TabItem>
<TabItem label="Node.js" value="nodejs">
<NodeSQL />
</TabItem>
<TabItem label="C#" value="csharp">
<CsSQL />
</TabItem>
<TabItem label="C" value="c">
<CSQL />
</TabItem>
</Tabs>
### 动态绑定写入
:::note
(补充介绍)
1. 无论 RESTful 方式建立连接还是本地驱动方式建立连接,以上示例代码都能正常工作。
2. 唯一需要注意的是:由于 RESTful 接口无状态, 不能使用 `use db` 语句来切换数据库, 所以在上面示例中使用了`dbName.tbName`指定表名。
### 示例代码
:::
<Tabs defaultValue="java">
<TabItem label="Java" value="java"></TabItem>
<TabItem label="Python" value="Python"></TabItem>
<TabItem label="Go" value="go"></TabItem>
<TabItem label="C" value="c"></TabItem>
<TabItem label="Rust" value="rust"></TabItem>
<TabItem label="Node.js" value="nodejs"></TabItem>
<TabItem label="C#" value="csharp"></TabItem>
### 参数绑定写入
TDengine 也提供了支持参数绑定的 Prepare API,与 MySQL 类似,这些 API 目前也仅支持用问号 `?` 来代表待绑定的参数。从 2.1.1.0 和 2.1.2.0 版本开始,TDengine 大幅改进了参数绑定接口对数据写入(INSERT)场景的支持。这样在通过参数绑定接口写入数据时,就避免了 SQL 语法解析的资源消耗,从而在绝大多数情况下显著提升写入性能。
需要注意的是,只有使用原生连接的连接器,才能使用参数绑定功能。
<Tabs defaultValue="java" groupId="lang">
<TabItem label="Java" value="java">
<JavaStmt />
</TabItem>
<TabItem label="Python" value="python">
<PyStmt />
</TabItem>
<TabItem label="Go" value="go">
<GoStmt />
</TabItem>
<TabItem label="Rust" value="rust">
<RustStmt />
</TabItem>
<TabItem label="Node.js" value="nodejs">
<NodeStmt />
</TabItem>
<TabItem label="C#" value="csharp">
<CsStmt />
</TabItem>
<TabItem label="C" value="c">
<CStmt />
</TabItem>
</Tabs>
---
sidebar_label: InfluxDB 行协议
title: InfluxDB 行协议
---
import Tabs from "@theme/Tabs";
import TabItem from "@theme/TabItem";
import JavaLine from "./_java_line.mdx";
import PyLine from "./_py_line.mdx";
import GoLine from "./_go_line.mdx";
import RustLine from "./_rust_line.mdx";
import NodeLine from "./_js_line.mdx";
import CsLine from "./_cs_line.mdx";
import CLine from "./_c_line.mdx";
## 协议介绍
InfluxDB Line 协议采用一行字符串来表示一行数据。分为四部分:
```
measurement,tag_set field_set timestamp
```
- measurement 将作为超级表名。它与 tag_set 之间使用一个英文逗号来分隔。
- tag_set 将作为标签数据,其格式形如 `<tag_key>=<tag_value>,<tag_key>=<tag_value>`,也即可以使用英文逗号来分隔多个标签数据。它与 field_set 之间使用一个半角空格来分隔。
- field_set 将作为普通列数据,其格式形如 `<field_key>=<field_value>,<field_key>=<field_value>`,同样是使用英文逗号来分隔多个普通列的数据。它与 timestamp 之间使用一个半角空格来分隔。
- timestamp 即本行数据对应的主键时间戳。
例如:
```
meters,location=Beijing.Haidian,groupid=2 current=13.4,voltage=223,phase=0.29 1648432611249500
```
:::note
- tag_set 中的所有的数据自动转化为 nchar 数据类型;
- field_set 中的每个数据项都需要对自身的数据类型进行描述, 比如 1.2f32 代表 float 类型的数值 1.2, 如果不带类型后缀会被当作 double 处理;
- timestamp 支持多种时间精度。写入数据的时候需要用参数指定时间精度,支持从小时到纳秒的 6 种时间精度。
:::
要了解更多可参考:[InfluxDB Line 协议官方文档](https://docs.influxdata.com/influxdb/v2.0/reference/syntax/line-protocol/) 和 [TDengine 无模式写入参考指南](/reference/schemaless/#无模式写入行协议)
## 示例代码
<Tabs defaultValue="java" groupId="lang">
<TabItem label="Java" value="java">
<JavaLine />
</TabItem>
<TabItem label="Python" value="Python">
<PyLine />
</TabItem>
<TabItem label="Go" value="go">
<GoLine />
</TabItem>
<TabItem label="Rust" value="rust">
<RustLine />
</TabItem>
<TabItem label="Node.js" value="nodejs">
<NodeLine />
</TabItem>
<TabItem label="C#" value="csharp">
<CsLine />
</TabItem>
<TabItem label="C" value="c">
<CLine />
</TabItem>
</Tabs>
---
sidebar_label: OpentsDB 行协议
title: OpentsDB 行协议
---
import Tabs from "@theme/Tabs";
import TabItem from "@theme/TabItem";
import JavaTelnet from "./_java_opts_telnet.mdx";
import PyTelnet from "./_py_opts_telnet.mdx";
import GoTelnet from "./_go_opts_telnet.mdx";
import RustTelnet from "./_rust_opts_telnet.mdx";
import NodeTelnet from "./_js_opts_telnet.mdx";
import CsTelnet from "./_cs_opts_telnet.mdx";
import CTelnet from "./_c_opts_telnet.mdx";
## 协议介绍
OpentsDB 行协议同样采用一行字符串来表示一行数据。OpentsDB 采用的是单列模型,因此一行只能包含一个普通数据列。标签列依然可以有多个。分为四部分,具体格式约定如下:
```txt
<metric> <timestamp> <value> <tagk_1>=<tagv_1>[ <tagk_n>=<tagv_n>]
```
- metric 将作为超级表名。
- timestamp 本行数据对应的时间戳。根据时间戳的长度自动识别时间精度。支持秒和毫秒两种时间精度
- value 度量值,必须为一个数值。对应的列名也是 “value”。
- 最后一部分是标签集, 用空格分隔不同标签, 所有标签自动转化为 nchar 数据类型;
例如:
```txt
meters.current 1648432611250 11.3 location=Beijing.Haidian groupid=3
```
参考[OpenTSDB Telnet API文档](http://opentsdb.net/docs/build/html/api_telnet/put.html)。
## 示例代码
<Tabs defaultValue="java" groupId="lang">
<TabItem label="Java" value="java">
<JavaTelnet />
</TabItem>
<TabItem label="Python" value="Python">
<PyTelnet />
</TabItem>
<TabItem label="Go" value="go">
<GoTelnet />
</TabItem>
<TabItem label="Rust" value="rust">
<RustTelnet />
</TabItem>
<TabItem label="Node.js" value="nodejs">
<NodeTelnet />
</TabItem>
<TabItem label="C#" value="csharp">
<CsTelnet />
</TabItem>
<TabItem label="C" value="c">
<CTelnet />
</TabItem>
</Tabs>
以上示例代码会自动创建 2 个超级表, 每个超级表有 4 条数据。
```cmd
taos> use test;
Database changed.
taos> show stables;
name | created_time | columns | tags | tables |
============================================================================================
meters.current | 2022-03-30 17:04:10.877 | 2 | 2 | 2 |
meters.voltage | 2022-03-30 17:04:10.882 | 2 | 2 | 2 |
Query OK, 2 row(s) in set (0.002544s)
taos> select tbname, * from `meters.current`;
tbname | ts | value | groupid | location |
==================================================================================================================================
t_0e7bcfa21a02331c06764f275... | 2022-03-28 09:56:51.249 | 10.800000000 | 3 | Beijing.Haidian |
t_0e7bcfa21a02331c06764f275... | 2022-03-28 09:56:51.250 | 11.300000000 | 3 | Beijing.Haidian |
t_7e7b26dd860280242c6492a16... | 2022-03-28 09:56:51.249 | 10.300000000 | 2 | Beijing.Chaoyang |
t_7e7b26dd860280242c6492a16... | 2022-03-28 09:56:51.250 | 12.600000000 | 2 | Beijing.Chaoyang |
Query OK, 4 row(s) in set (0.005399s)
```
---
sidebar_label: OpentsDB JSON 格式协议
title: OpentsDB JSON 格式协议
---
import Tabs from "@theme/Tabs";
import TabItem from "@theme/TabItem";
import JavaJson from "./_java_opts_json.mdx";
import PyJson from "./_py_opts_json.mdx";
import GoJson from "./_go_opts_json.mdx";
import RustJson from "./_rust_opts_json.mdx";
import NodeJson from "./_js_opts_json.mdx";
import CsJson from "./_cs_opts_json.mdx";
import CJson from "./_c_opts_json.mdx";
## 协议介绍
OpentsDB JSON 格式协议采用一个 JSON 字符串表示一行或多行数据。例如:
```json
[
{
"metric": "sys.cpu.nice",
"timestamp": 1346846400,
"value": 18,
"tags": {
"host": "web01",
"dc": "lga"
}
},
{
"metric": "sys.cpu.nice",
"timestamp": 1346846400,
"value": 9,
"tags": {
"host": "web02",
"dc": "lga"
}
}
]
```
与 OpentsDB 行协议类似, metric 将作为超级表名, timestamp 表示时间戳,value 表示度量值, tags 表示标签集。
参考[OpenTSDB HTTP API文档](http://opentsdb.net/docs/build/html/api_http/put.html)。
:::note
- 对于 JSON 格式协议,TDengine 并不会自动把所有标签转成 nchar 类型, 字符串将将转为 nchar 类型, 数值将同样转换为 double 类型。
- TDengine 只接收 JSON **数组格式**的字符串,即使一行数据也需要转换成数组形式。
:::
## 示例代码
<Tabs defaultValue="java" groupId="lang">
<TabItem label="Java" value="java">
<JavaJson />
</TabItem>
<TabItem label="Python" value="Python">
<PyJson />
</TabItem>
<TabItem label="Go" value="go">
<GoJson />
</TabItem>
<TabItem label="Rust" value="rust">
<RustJson />
</TabItem>
<TabItem label="Node.js" value="nodejs">
<NodeJson />
</TabItem>
<TabItem label="C#" value="csharp">
<CsJson />
</TabItem>
<TabItem label="C" value="c">
<CJson />
</TabItem>
</Tabs>
以上示例代码会自动创建 2 个超级表, 每个超级表有 2 条数据。
```cmd
taos> use test;
Database changed.
taos> show stables;
name | created_time | columns | tags | tables |
============================================================================================
meters.current | 2022-03-29 16:05:25.193 | 2 | 2 | 1 |
meters.voltage | 2022-03-29 16:05:25.200 | 2 | 2 | 1 |
Query OK, 2 row(s) in set (0.001954s)
taos> select * from `meters.current`;
ts | value | groupid | location |
===================================================================================================================
2022-03-28 09:56:51.249 | 10.300000000 | 2.000000000 | Beijing.Chaoyang |
2022-03-28 09:56:51.250 | 12.600000000 | 2.000000000 | Beijing.Chaoyang |
Query OK, 2 row(s) in set (0.004076s)
```
```c
{{#include docs-examples/c/line_example.c:main}}
```
\ No newline at end of file
```c
{{#include docs-examples/c/json_protocol_example.c:main}}
```
\ No newline at end of file
```c
{{#include docs-examples/c/telnet_line_example.c:main}}
```
\ No newline at end of file
```c
{{#include docs-examples/c/insert_example.c}}
```
\ No newline at end of file
```c title=一次绑定一行
{{#include docs-examples/c/stmt_example.c}}
```
```c title=一次绑定多行 72:117
{{#include docs-examples/c/multi_bind_example.c}}
```
\ No newline at end of file
label: 写入数据
link:
type: generated-index
slug: /insert-data/
description: "TDengine 支持多种写入协议,包括 SQL,InfluxDB Line 协议, OpentsDB Telnet 协议,OpentsDB JSON 格式协议。数据可以单条插入,也可以批量插入,可以插入一个数据采集点的数据,也可以同时插入多个数据采集点的数据。同时,TDengine 支持多线程插入,支持时间乱序数据插入,也支持历史数据插入。InfluxDB Line 协议、OpentsDB Telnet 协议和 OpentsDB JSON 格式协议是 TDengine 支持的三种无模式写入协议。使用无模式方式写入无需提前创建超级表和子表,并且引擎能自适用数据对表结构做调整。"
```csharp
{{#include docs-examples/csharp/InfluxDBLineExample.cs}}
```
```csharp
{{#include docs-examples/csharp/OptsJsonExample.cs}}
```
```csharp
{{#include docs-examples/csharp/OptsTelnetExample.cs}}
```
```csharp
{{#include docs-examples/csharp/SQLInsertExample.cs}}
```
```csharp
{{#include docs-examples/csharp/StmtInsertExample.cs}}
```
```go
{{#include docs-examples/go/insert/line/main.go}}
```
```go
{{#include docs-examples/go/insert/json/main.go}}
```
```go
{{#include docs-examples/go/insert/telnet/main.go}}
```
```go
{{#include docs-examples/go/insert/sql/main.go}}
```
```go
{{#include docs-examples/go/insert/stmt/main.go}}
```
:::tip
driver-go 的模块 `github.com/taosdata/driver-go/v2/wrapper` 是 C 接口的底层封装。使用这个模块也可以实现参数绑定写入。
:::
```java
{{#include docs-examples/java/src/main/java/com/taos/example/LineProtocolExample.java}}
```
```java
{{#include docs-examples/java/src/main/java/com/taos/example/JSONProtocolExample.java}}
```
```java
{{#include docs-examples/java/src/main/java/com/taos/example/TelnetLineProtocolExample.java}}
```
```java
{{#include docs-examples/java/src/main/java/com/taos/example/RestInsertExample.java:insert}}
```
\ No newline at end of file
```java
{{#include docs-examples/java/src/main/java/com/taos/example/StmtInsertExample.java}}
```
```js
{{#include docs-examples/node/nativeexample/influxdb_line_example.js}}
```
```js
{{#include docs-examples/node/nativeexample/opentsdb_json_example.js}}
```
```js
{{#include docs-examples/node/nativeexample/opentsdb_telnet_example.js}}
```
```js
{{#include docs-examples/node/nativeexample/insert_example.js}}
```
```js title=一次绑定一行
{{#include docs-examples/node/nativeexample/param_bind_example.js}}
```
```js title=一次绑定多行
{{#include docs-examples/node/nativeexample/multi_bind_example.js:insertData}}
```
:::info
一次绑定一行效率不如一次绑定多行,但支持非 INSERT 语句。一次绑定多行效率更高,但仅支持 INSERT 语句。
:::
```py
{{#include docs-examples/python/line_protocol_example.py}}
```
```py
{{#include docs-examples/python/json_protocol_example.py}}
```
```py
{{#include docs-examples/python/telnet_line_protocol_example.py}}
```
```py
{{#include docs-examples/python/native_insert_example.py}}
```
```py title=一次绑定一行
{{#include docs-examples/python/bind_param_example.py}}
```
```py title=一次绑定多行
{{#include docs-examples/python/multi_bind_example.py:bind_batch}}
```
:::info
一次绑定一行效率不如一次绑定多行,但支持非 INSERT 语句。一次绑定多行效率更高,但仅支持 INSERT 语句。
:::
\ No newline at end of file
```rust
{{#include docs-examples/rust/schemalessexample/examples/influxdb_line_example.rs}}
```
```rust
{{#include docs-examples/rust/schemalessexample/examples/opentsdb_json_example.rs}}
```
```rust
{{#include docs-examples/rust/schemalessexample/examples/opentsdb_telnet_example.rs}}
```
```rust
{{#include docs-examples/rust/restexample/examples/insert_example.rs}}
```
```rust
{{#include docs-examples/rust/nativeexample/examples/stmt_example.rs}}
```
```c
{{#include docs-examples/c/query_example.c}}
```
\ No newline at end of file
```c
{{#include docs-examples/c/async_query_example.c:demo}}
```
\ No newline at end of file
```csharp
{{#include docs-examples/csharp/QueryExample.cs}}
```
```csharp
{{#include docs-examples/csharp/AsyncQueryExample.cs}}
```
```go
{{#include docs-examples/go/query/sync/main.go}}
```
```go
{{#include docs-examples/go/query/async/main.go}}
```
```java
{{#include docs-examples/java/src/main/java/com/taos/example/RestQueryExample.java}}
```
```js
{{#include docs-examples/node/nativeexample/query_example.js}}
```
```js
{{#include docs-examples/node/nativeexample/async_query_example.js}}
```
通过迭代逐行获取查询结果。
```py
{{#include docs-examples/python/query_example.py:iter}}
```
一次获取所有查询结果,并把每一行转化为一个字典返回。
```py
{{#include docs-examples/python/query_example.py:fetch_all}}
```
```py
{{#include docs-examples/python/async_query_example.py}}
```
:::note
这个示例程序,目前在 Windows 系统上还无法运行
:::
```rust
{{#include docs-examples/rust/restexample/examples/query_example.rs}}
```
# 查询数据
---
slug: /query-data
title: 查询数据
description: "主要查询功能,通过连接器执行同步查询和异步查询"
---
import Tabs from "@theme/Tabs";
import TabItem from "@theme/TabItem";
import JavaQuery from "./_java.mdx";
import PyQuery from "./_py.mdx";
import GoQuery from "./_go.mdx";
import RustQuery from "./_rust.mdx";
import NodeQuery from "./_js.mdx";
import CsQuery from "./_cs.mdx";
import CQuery from "./_c.mdx";
import PyAsync from "./_py_async.mdx";
import NodeAsync from "./_js_async.mdx";
import CsAsync from "./_cs_async.mdx";
import CAsync from "./_c_async.mdx";
## 主要查询功能
TDengine 采用 SQL 作为查询语言。应用程序可以通过 C/C++, Java, Go, C#, Python, Node.js 连接器发送 SQL 语句,用户可以通过 TDengine 提供的命令行(Command Line Interface, CLI)工具 TAOS Shell 手动执行 SQL 即席查询(Ad-Hoc Query)。TDengine 支持如下查询功能:
TDengine 采用 SQL 作为查询语言。应用程序可以通过 REST API 或连接器发送 SQL 语句,用户还可以通过 TDengine 命令行工具 taos 手动执行 SQL 即席查询(Ad-Hoc Query)。TDengine 支持如下查询功能:
- 单列、多列数据查询
- 标签和数值的多种过滤条件:>, <, =, <\>, like 等
......@@ -14,9 +29,9 @@ TDengine 采用 SQL 作为查询语言。应用程序可以通过 C/C++, Java, G
- 时间戳对齐的连接查询(Join Query: 隐式连接)操作
- 多种聚合/计算函数: count, max, min, avg, sum, twa, stddev, leastsquares, top, bottom, first, last, percentile, apercentile, last_row, spread, diff 等
例如:在 TAOS Shell 中,从表 d1001 中查询出 voltage > 215 的记录,按时间降序排列,仅仅输出 2 条。
例如:在命令行工具 taos 中,从表 d1001 中查询出 voltage > 215 的记录,按时间降序排列,仅仅输出 2 条。
```mysql
```sql
taos> select * from d1001 where voltage > 215 order by ts desc limit 2;
ts | current | voltage | phase |
======================================================================================
......@@ -27,13 +42,15 @@ Query OK, 2 row(s) in set (0.001100s)
为满足物联网场景的需求,TDengine 支持几个特殊的函数,比如 twa(时间加权平均),spread (最大值与最小值的差),last_row(最后一条记录)等,更多与物联网场景相关的函数将添加进来。TDengine 还支持连续查询。
具体的查询语法请看 [TAOS SQL 的数据查询](https://www.taosdata.com/cn/documentation/taos-sql#select) 章节。
具体的查询语法请看 [TAOS SQL 的数据查询](/taos-sql/select) 章节。
## 多表聚合查询
物联网场景中,往往同一个类型的数据采集点有多个。TDengine 采用超级表(STable)的概念来描述某一个类型的数据采集点,一张普通的表来描述一个具体的数据采集点。同时 TDengine 使用标签来描述数据采集点的静态属性,一个具体的数据采集点有具体的标签值。通过指定标签的过滤条件,TDengine 提供了一高效的方法将超级表(某一类型的数据采集点)所属的子表进行聚合查询。对普通表的聚合函数以及绝大部分操作都适用于超级表,语法完全一样。
**示例 1**:在 TAOS Shell,查找北京所有智能电表采集的电压平均值,并按照 location 分组
### 示例一
在 TAOS Shell,查找北京所有智能电表采集的电压平均值,并按照 location 分组。
```
taos> SELECT AVG(voltage) FROM meters GROUP BY location;
......@@ -44,7 +61,9 @@ taos> SELECT AVG(voltage) FROM meters GROUP BY location;
Query OK, 2 row(s) in set (0.002136s)
```
**示例 2**:在 TAOS shell, 查找 groupId 为 2 的所有智能电表过去 24 小时的记录条数,电流的最大值
### 示例二
在 TAOS shell, 查找 groupId 为 2 的所有智能电表过去 24 小时的记录条数,电流的最大值。
```
taos> SELECT count(*), max(current) FROM meters where groupId = 2 and ts > now - 24h;
......@@ -54,7 +73,7 @@ taos> SELECT count(*), max(current) FROM meters where groupId = 2 and ts > now -
Query OK, 1 row(s) in set (0.002136s)
```
TDengine 仅容许对属于同一个超级表的表之间进行聚合查询,不同超级表之间的聚合查询不支持。在 [TAOS SQL 的数据查询](https://www.taosdata.com/cn/documentation/taos-sql#select) 一章,查询类操作都会注明是否支持超级表。
TDengine 仅容许对属于同一个超级表的表之间进行聚合查询,不同超级表之间的聚合查询不支持。在 [TAOS SQL 的数据查询](/taos-sql/select) 一章,查询类操作都会注明是否支持超级表。
## 降采样查询、插值
......@@ -97,31 +116,63 @@ taos> SELECT SUM(current) FROM meters INTERVAL(1s, 500a);
Query OK, 5 row(s) in set (0.001521s)
```
物联网场景里,每个数据采集点采集数据的时间是难同步的,但很多分析算法(比如 FFT)需要把采集的数据严格按照时间等间隔的对齐,在很多系统里,需要应用自己写程序来处理,但使用 TDengine 的降采样操作就轻松解决。如果一个时间间隔里,没有采集的数据,TDengine 还提供插值计算的功能。
物联网场景里,每个数据采集点采集数据的时间是难同步的,但很多分析算法(比如 FFT)需要把采集的数据严格按照时间等间隔的对齐,在很多系统里,需要应用自己写程序来处理,但使用 TDengine 的降采样操作就轻松解决。
语法规则细节请见 [TAOS SQL 的时间维度聚合](https://www.taosdata.com/cn/documentation/taos-sql#aggregation) 章节
如果一个时间间隔里,没有采集的数据,TDengine 还提供插值计算的功能
## 示例代码
语法规则细节请见 [TAOS SQL 的按时间窗口切分聚合](/taos-sql/interval) 章节。
### 同步查询
## 示例代码
<Tabs defaultValue="java">
<TabItem label="Java" value="java"></TabItem>
<TabItem label="Python" value="Python"></TabItem>
<TabItem label="Go" value="go"></TabItem>
<TabItem label="C" value="c"></TabItem>
<TabItem label="Rust" value="rust"></TabItem>
<TabItem label="Node.js" value="nodejs"></TabItem>
<TabItem label="C#" value="csharp"></TabItem>
### 查询数据
在 [SQL 写入](/develop/insert-data/sql-writing) 一章,我们创建了 power 数据库,并向 meters 表写入了一些数据,以下示例代码展示如何查询这个表的数据。
<Tabs defaultValue="java" groupId="lang">
<TabItem label="Java" value="java">
<JavaQuery />
</TabItem>
<TabItem label="Python" value="python">
<PyQuery />
</TabItem>
<TabItem label="Go" value="go">
<GoQuery />
</TabItem>
<TabItem label="Rust" value="rust">
<RustQuery />
</TabItem>
<TabItem label="Node.js" value="nodejs">
<NodeQuery />
</TabItem>
<TabItem label="C#" value="csharp">
<CsQuery />
</TabItem>
<TabItem label="C" value="c">
<CQuery />
</TabItem>
</Tabs>
:::note
1. 无论是使用 REST 连接还是原生连接的连接器,以上示例代码都能正常工作。
2. 唯一需要注意的是:由于 RESTful 接口无状态, 不能使用 `use db` 语句来切换数据库。
:::
### 异步查询
<Tabs defaultValue="go">
<TabItem label="Python" value="Python"></TabItem>
<TabItem label="Go" value="go"></TabItem>
<TabItem label="C" value="c"></TabItem>
<TabItem label="Rust" value="rust"></TabItem>
<TabItem label="Node.js" value="nodejs"></TabItem>
<TabItem label="C#" value="csharp"></TabItem>
除同步查询 API 之外,TDengine 还提供性能更高的异步调用 API 处理数据插入、查询操作。在软硬件环境相同的情况下,异步 API 处理数据插入的速度比同步 API 快 2-4 倍。异步 API 采用非阻塞式的调用方式,在系统真正完成某个具体数据库操作前,立即返回。调用的线程可以去处理其他工作,从而可以提升整个应用的性能。异步 API 在网络延迟严重的情况下,优点尤为突出。
需要注意的是,只有使用原生连接的连接器,才能使用异步查询功能。
<Tabs defaultValue="python" groupId="lang">
<TabItem label="Python" value="python">
<PyAsync />
</TabItem>
<TabItem label="C#" value="csharp">
<CsAsync />
</TabItem>
<TabItem label="C" value="c">
<CAsync />
</TabItem>
</Tabs>
---
sidebar_label: 连续查询
description: "连续查询是一个按照预设频率自动执行的查询功能,提供按照时间窗口的聚合查询能力,是一种简化的时间驱动流式计算。"
title: "连续查询(Continuous Query)"
---
# 连续查询(Continuous Query)
import Tabs from "@theme/Tabs";
import TabItem from "@theme/TabItem";
连续查询是 TDengine 定期自动执行的查询,采用滑动窗口的方式进行计算,是一种简化的时间驱动的流式计算。针对库中的表或超级表,TDengine 可提供定期自动执行的连续查询,用户可让 TDengine 推送查询的结果,也可以将结果再写回到 TDengine 中。每次执行的查询是一个时间窗口,时间窗口随着时间流动向前滑动。在定义连续查询的时候需要指定时间窗口(time window, 参数 interval)大小和每次前向增量时间(forward sliding times, 参数 sliding)。
TDengine 的连续查询采用时间驱动模式,可以直接使用 TAOS SQL 进行定义,不需要额外的操作。使用连续查询,可以方便快捷地按照时间窗口生成结果,从而对原始采集数据进行降采样(down sampling)。用户通过 TAOS SQL 定义连续查询以后,TDengine 自动在最后的一个完整的时间周期末端拉起查询,并将计算获得的结果推送给用户或者写回 TDengine。
......@@ -15,7 +12,21 @@ TDengine 提供的连续查询与普通流计算中的时间窗口计算具有
- 不同于流计算的实时反馈计算结果,连续查询只在时间窗口关闭以后才开始计算。例如时间周期是 1 天,那么当天的结果只会在 23:59:59 以后才会生成。
- 如果有历史记录写入到已经计算完成的时间区间,连续查询并不会重新进行计算,也不会重新将结果推送给用户。对于写回 TDengine 的模式,也不会更新已经存在的计算结果。
- 使用连续查询推送结果的模式,服务端并不缓存客户端计算状态,也不提供 Exactly-Once 的语意保证。如果用户的应用端崩溃,再次拉起的连续查询将只会从再次拉起的时间开始重新计算最近的一个完整的时间窗口。如果使用写回模式,TDengine 可确保数据写回的有效性和连续性。
- 使用连续查询推送结果的模式,服务端并不缓存客户端计算状态,也不提供 Exactly-Once 的语义保证。如果用户的应用端崩溃,再次拉起的连续查询将只会从再次拉起的时间开始重新计算最近的一个完整的时间窗口。如果使用写回模式,TDengine 可确保数据写回的有效性和连续性。
## 连续查询语法
```sql
[CREATE TABLE AS] SELECT select_expr [, select_expr ...]
FROM {tb_name_list}
[WHERE where_condition]
[INTERVAL(interval_val [, interval_offset]) [SLIDING sliding_val]]
```
INTERVAL: 连续查询作用的时间窗口
SLIDING: 连续查询的时间窗口向前滑动的时间间隔
## 使用连续查询
......@@ -28,7 +39,7 @@ create table D1002 using meters tags ("Beijing.Haidian", 2);
...
```
我们已经知道,可以通过下面这条 SQL 语句以一分钟为时间窗口、30 秒为前向增量统计这些电表的平均电压。
可以通过下面这条 SQL 语句以一分钟为时间窗口、30 秒为前向增量统计这些电表的平均电压。
```sql
select avg(voltage) from meters interval(1m) sliding(30s);
......@@ -48,7 +59,7 @@ create table avg_vol as select avg(voltage) from meters interval(1m) sliding(30s
会自动创建一个名为 `avg_vol` 的新表,然后每隔 30 秒,TDengine 会增量执行 `as` 后面的 SQL 语句,并将查询结果写入这个表中,用户程序后续只要从 `avg_vol` 中查询数据即可。例如:
```mysql
```sql
taos> select * from avg_vol;
ts | avg_voltage_ |
===================================================
......@@ -62,7 +73,7 @@ taos> select * from avg_vol;
此外,TDengine 还支持用户指定连续查询的起止时间。如果不输入开始时间,连续查询将从第一条原始数据所在的时间窗口开始;如果没有输入结束时间,连续查询将永久运行;如果用户指定了结束时间,连续查询在系统时间达到指定的时间以后停止运行。比如使用下面的 SQL 创建的连续查询将运行一小时,之后会自动停止。
```mysql
```sql
create table avg_vol as select avg(voltage) from meters where ts > now and ts <= now + 1h interval(1m) sliding(30s);
```
......@@ -71,16 +82,3 @@ create table avg_vol as select avg(voltage) from meters where ts > now and ts <=
## 管理连续查询
用户可在控制台中通过 `show streams` 命令来查看系统中全部运行的连续查询,并可以通过 `kill stream` 命令杀掉对应的连续查询。后续版本会提供更细粒度和便捷的连续查询管理命令。
## 示例代码
<Tabs defaultValue="java">
<TabItem label="Java" value="java"></TabItem>
<TabItem label="Python" value="Python"></TabItem>
<TabItem label="Go" value="go"></TabItem>
<TabItem label="C" value="c"></TabItem>
<TabItem label="Rust" value="rust"></TabItem>
<TabItem label="Node.js" value="nodejs"></TabItem>
<TabItem label="C#" value="csharp"></TabItem>
</Tabs>
\ No newline at end of file
---
sidebar_position: 2
sidebar_label: 订阅
sidebar_label: 数据订阅
description: "轻量级的数据订阅与推送服务。连续写入到 TDengine 中的时序数据能够被自动推送到订阅客户端。"
title: 数据订阅
---
# 数据订阅(Publisher/Subscriber)
import Tabs from "@theme/Tabs";
import TabItem from "@theme/TabItem";
import Java from "./_sub_java.mdx";
import Python from "./_sub_python.mdx";
import Go from "./_sub_go.mdx";
import Rust from "./_sub_rust.mdx";
import Node from "./_sub_node.mdx";
import CSharp from "./_sub_cs.mdx";
import CDemo from "./_sub_c.mdx";
基于数据天然的时间序列特性,TDengine 的数据写入(insert)与消息系统的数据发布(pub)逻辑上一致,均可视为系统中插入一条带时间戳的新记录。同时,TDengine 在内部严格按照数据时间序列单调递增的方式保存数据。本质上来说,TDengine 中每一张表均可视为一个标准的消息队列。
基于数据天然的时间序列特性,TDengine 的数据写入(insert)与消息系统的数据发布(pub)逻辑上一致,均可视为系统中插入一条带时间戳的新记录。同时,TDengine 在内部严格按照数据时间序列单调递增的方式保存数据。本质上来说,TDengine 中每一张表均可视为一个标准的消息队列。
TDengine 内嵌支持轻量级的消息订阅与推送服务。使用系统提供的 API,用户可使用普通查询语句订阅数据库中的一张或多张表。订阅的逻辑和操作状态的维护均是由客户端完成,客户端定时轮询服务器是否有新的记录到达,有新的记录到达就会将结果反馈到客户。
TDengine 的订阅与推送服务的状态是客户端维持,TDengine 服务器并不维持。因此如果应用重启,从哪个时间点开始获取最新数据,由应用决定。
TDengine 的订阅与推送服务的状态是由客户端维持,TDengine 服务端并不维持。因此如果应用重启,从哪个时间点开始获取最新数据,由应用决定。
TDengine 的 API 中,与订阅相关的主要有以下三个:
......@@ -19,7 +28,7 @@ taos_consume
taos_unsubscribe
```
这些 API 的文档请见 [C/C++ Connector](https://www.taosdata.com/cn/documentation/connector#c-cpp),下面仍以智能电表场景为例介绍一下它们的具体用法(超级表和子表结构请参考上一节“连续查询”),完整的示例代码可以在 [这里](https://github.com/taosdata/TDengine/blob/master/examples/c/subscribe.c) 找到。
这些 API 的文档请见 [C/C++ Connector](/reference/connector/cpp),下面仍以智能电表场景为例介绍一下它们的具体用法(超级表和子表结构请参考上一节“连续查询”),完整的示例代码可以在 [这里](https://github.com/taosdata/TDengine/blob/master/examples/c/subscribe.c) 找到。
如果我们希望当某个电表的电流超过一定限制(比如 10A)后能得到通知并进行一些处理, 有两种方法:一是分别对每张子表进行查询,每次查询后记录最后一条数据的时间戳,后续只查询这个时间戳之后的数据:
......@@ -161,28 +170,26 @@ $ taos
这时,因为电流超过了 10A,您应该可以看到示例程序将它输出到了屏幕上。您可以继续插入一些数据观察示例程序的输出。
## Java 使用数据订阅功能
## 示例程序
订阅功能也提供了 Java 开发接口,相关说明请见 [Java Connector](https://www.taosdata.com/cn/documentation/connector/java#subscribe)。需要注意的是,目前 Java 接口没有提供异步订阅模式,但用户程序可以通过创建 `TimerTask` 等方式达到同样的效果。
下面以一个示例程序介绍其具体使用方法。它所完成的功能与前面介绍的 C 语言示例基本相同,也是订阅数据库中所有电流超过 10A 的记录。
下面以一个示例程序介绍其具体使用方法。示例程序的目的是订阅数据库中所有电流超过 10A 的记录。
### 准备数据
```sql
# 创建 power 库
```
# create database "power"
taos> create database power;
# 切换库
# use "power" as the database in following operations
taos> use power;
# 创建超级表
# create super table "meters"
taos> create table meters(ts timestamp, current float, voltage int, phase int) tags(location binary(64), groupId int);
# 创建表
# create tabes using the schema defined by super table "meters"
taos> create table d1001 using meters tags ("Beijing.Chaoyang", 2);
taos> create table d1002 using meters tags ("Beijing.Haidian", 2);
# 插入测试数据
# insert some rows
taos> insert into d1001 values("2020-08-15 12:00:00.000", 12, 220, 1),("2020-08-15 12:10:00.000", 12.3, 220, 2),("2020-08-15 12:20:00.000", 12.2, 220, 1);
taos> insert into d1002 values("2020-08-15 12:00:00.000", 9.9, 220, 1),("2020-08-15 12:10:00.000", 10.3, 220, 1),("2020-08-15 12:20:00.000", 11.2, 220, 1);
# 从超级表 meters 查询电流大于 10A 的记录
# filter out the rows in which current is bigger than 10A
taos> select * from meters where current > 10;
ts | current | voltage | phase | location | groupid |
===========================================================================================================
......@@ -193,64 +200,37 @@ taos> select * from meters where current > 10;
2020-08-15 12:20:00.000 | 12.20000 | 220 | 1 | Beijing.Chaoyang | 2 |
Query OK, 5 row(s) in set (0.004896s)
```
### 示例程序
```java
public class SubscribeDemo {
private static final String topic = "topic-meter-current-bg-10";
private static final String sql = "select * from meters where current > 10";
public static void main(String[] args) {
Connection connection = null;
TSDBSubscribe subscribe = null;
try {
Class.forName("com.taosdata.jdbc.TSDBDriver");
Properties properties = new Properties();
properties.setProperty(TSDBDriver.PROPERTY_KEY_CHARSET, "UTF-8");
properties.setProperty(TSDBDriver.PROPERTY_KEY_TIME_ZONE, "UTC-8");
String jdbcUrl = "jdbc:TAOS://127.0.0.1:6030/power?user=root&password=taosdata";
connection = DriverManager.getConnection(jdbcUrl, properties);
subscribe = ((TSDBConnection) connection).subscribe(topic, sql, true); // 创建订阅
int count = 0;
while (count < 10) {
TimeUnit.SECONDS.sleep(1); // 等待1秒,避免频繁调用 consume,给服务端造成压力
TSDBResultSet resultSet = subscribe.consume(); // 消费数据
if (resultSet == null) {
continue;
}
ResultSetMetaData metaData = resultSet.getMetaData();
while (resultSet.next()) {
int columnCount = metaData.getColumnCount();
for (int i = 1; i <= columnCount; i++) {
System.out.print(metaData.getColumnLabel(i) + ": " + resultSet.getString(i) + "\t");
}
System.out.println();
count++;
}
}
} catch (Exception e) {
e.printStackTrace();
} finally {
try {
if (null != subscribe)
subscribe.close(true); // 关闭订阅
if (connection != null)
connection.close();
} catch (SQLException throwables) {
throwables.printStackTrace();
}
}
}
}
```
运行示例程序,首先,它会消费符合查询条件的所有历史数据:
### 示例代码
<Tabs defaultValue="java" groupId="lang">
<TabItem label="Java" value="java">
<Java/>
</TabItem>
{/* <TabItem label="Python" value="Python">
<Python/>
</TabItem>
<TabItem label="Go" value="go">
<Go/>
</TabItem>
<TabItem label="Rust" value="rust">
<Rust/>
</TabItem>
<TabItem label="Node.js" value="nodejs">
<Node/>
</TabItem>
<TabItem label="C#" value="csharp">
<CSharp/>
</TabItem> */}
<TabItem label="C" value="c">
<CDemo/>
</TabItem>
</Tabs>
### 运行示例程序
示例程序会先消费符合查询条件的所有历史数据:
```bash
# java -jar subscribe.jar
ts: 1597464000000 current: 12.0 voltage: 220 phase: 1 location: Beijing.Chaoyang groupid : 2
ts: 1597464600000 current: 12.3 voltage: 220 phase: 2 location: Beijing.Chaoyang groupid : 2
ts: 1597465200000 current: 12.2 voltage: 220 phase: 1 location: Beijing.Chaoyang groupid : 2
......@@ -260,14 +240,14 @@ ts: 1597465200000 current: 11.2 voltage: 220 phase: 1 location: Beijing.Haidian
接着,使用 taos 客户端向表中新增一条数据:
```sql
```
# taos
taos> use power;
taos> insert into d1001 values("2020-08-15 12:40:00.000", 12.4, 220, 1);
taos> insert into d1001 values(now, 12.4, 220, 1);
```
因为这条数据的电流大于 10A,示例程序会将其消费:
```
ts: 1597466400000 current: 12.4 voltage: 220 phase: 1 location: Beijing.Chaoyang groupid: 2
ts: 1651146662805 current: 12.4 voltage: 220 phase: 1 location: Beijing.Chaoyang groupid: 2
```
---
sidebar_label: 缓存
title: 缓存
description: "提供写驱动的缓存管理机制,将每个表最近写入的一条记录持续保存在缓存中,可以提供高性能的最近状态查询。"
---
# 缓存(Cache)
TDengine 采用时间驱动缓存管理策略(First-In-First-Out,FIFO),又称为写驱动的缓存管理机制。这种策略有别于读驱动的数据缓存模式(Least-Recent-Used,LRU),直接将最近写入的数据保存在系统的缓存中。当缓存达到临界值的时候,将最早的数据批量写入磁盘。一般意义上来说,对于物联网数据的使用,用户最为关心最近产生的数据,即当前状态。TDengine 充分利用了这一特性,将最近到达的(当前状态)数据保存在缓存中。
TDengine 通过查询函数向用户提供毫秒级的数据获取能力。直接将最近到达的数据保存在缓存中,可以更加快速地响应用户针对最近一条或一批数据的查询分析,整体上提供更快的数据库查询响应能力。从这个意义上来说,可通过设置合适的配置参数将 TDengine 作为数据缓存来使用,而不需要再部署额外的缓存系统,可有效地简化系统架构,降低运维的成本。需要注意的是,TDengine 重启以后系统的缓存将被清空,之前缓存的数据均会被批量写入磁盘,缓存的数据将不会像专门的 key-value 缓存系统再将之前缓存的数据重新加载到缓存中。
......@@ -14,7 +14,7 @@ TDengine 将内存池按块划分进行管理,数据在内存块里是以行
你可以通过函数 last_row() 快速获取一张表或一张超级表的最后一条记录,这样很便于在大屏显示各设备的实时状态或采集值。例如:
```mysql
```sql
select last_row(voltage) from meters where location='Beijing.Chaoyang';
```
......
label: 开发指南
\ No newline at end of file
```c
{{#include docs-examples/c/subscribe_demo.c}}
```
\ No newline at end of file
```csharp
{{#include docs-examples/csharp/SubscribeDemo.cs}}
```
\ No newline at end of file
```go
{{#include docs-examples/go/sub/main.go}}
```
\ No newline at end of file
```java
{{#include docs-examples/java/src/main/java/com/taos/example/SubscribeDemo.java}}
```
:::note
目前 Java 接口没有提供异步订阅模式,但用户程序可以通过创建 `TimerTask` 等方式达到同样的效果。
:::
\ No newline at end of file
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册