提交 4e92a164 编写于 作者: haoranc's avatar haoranc

Merge remote-tracking branch 'origin/2.6' into release/TS-1573

......@@ -212,7 +212,7 @@ curl -L -o php-tdengine.tar.gz https://github.com/Yurunsoft/php-tdengine/archive
&& tar -xzf php-tdengine.tar.gz -C php-tdengine --strip-components=1
```
> 版本 `v1.0.0` 可替换为任意更新的版本,可在 Release 中查看最新版本。
> 版本 `v1.0.2` 只是示例,可替换为任意更新的版本,可在 [TDengine PHP Connector 发布历史](https://github.com/Yurunsoft/php-tdengine/releases) 中查看可用版本。
**非 Swoole 环境:**
......
......@@ -111,13 +111,6 @@ INSERT INTO d1001 FILE '/tmp/csvfile.csv';
INSERT INTO d21001 USING meters TAGS ('California.SanFrancisco', 2) FILE '/tmp/csvfile.csv';
```
也可以在一条语句中向多个表以自动建表的方式插入记录。例如:
```
INSERT INTO d21001 USING meters TAGS ('California.SanFrancisco', 2) FILE '/tmp/csvfile_21001.csv'
d21002 USING meters (groupId) TAGS (2) FILE '/tmp/csvfile_21002.csv';
```
## 历史记录写入
可使用 IMPORT 或者 INSERT 命令,IMPORT 的语法,功能与 INSERT 完全一样。
......
......@@ -93,8 +93,8 @@ Maven 项目中,在 pom.xml 中添加以下依赖:
可以通过下载 TDengine 的源码,自己编译最新版本的 Java connector
```shell
git clone https://github.com/taosdata/TDengine.git
cd TDengine/src/connector/jdbc
git clone https://github.com/taosdata/taos-connector-jdbc.git
cd taos-connector-jdbc
mvn clean install -Dmaven.test.skip=true
```
......@@ -199,6 +199,7 @@ url 中的配置参数如下:
- user:登录 TDengine 用户名,默认值 'root'。
- password:用户登录密码,默认值 'taosdata'。
- batchfetch: true:在执行查询时批量拉取结果集;false:逐行拉取结果集。默认值为:false。逐行拉取结果集使用 HTTP 方式进行数据传输。从 taos-jdbcdriver-2.0.38 和 TDengine 2.4.0.12 版本开始,JDBC REST 连接增加批量拉取数据功能。taos-jdbcdriver 与 TDengine 之间通过 WebSocket 连接进行数据传输。相较于 HTTP,WebSocket 可以使 JDBC REST 连接支持大数据量查询,并提升查询性能。
- charset: 当开启批量拉取数据时,指定解析字符串数据的字符集。
- batchErrorIgnore:true:在执行 Statement 的 executeBatch 时,如果中间有一条 SQL 执行失败,继续执行下面的 SQL 了。false:不再执行失败 SQL 后的任何语句。默认值为:false。
**注意**:部分配置项(比如:locale、timezone)在 REST 连接中不生效。
......@@ -260,7 +261,7 @@ properties 中的配置参数如下:
- TSDBDriver.PROPERTY_KEY_BATCH_LOAD: true:在执行查询时批量拉取结果集;false:逐行拉取结果集。默认值为:false。
- TSDBDriver.PROPERTY_KEY_BATCH_ERROR_IGNORE:true:在执行 Statement 的 executeBatch 时,如果中间有一条 SQL 执行失败,继续执行下面的 sq 了。false:不再执行失败 SQL 后的任何语句。默认值为:false。
- TSDBDriver.PROPERTY_KEY_CONFIG_DIR:仅在使用 JDBC 原生连接时生效。客户端配置文件目录路径,Linux OS 上默认值 `/etc/taos`,Windows OS 上默认值 `C:/TDengine/cfg`。
- TSDBDriver.PROPERTY_KEY_CHARSET:仅在使用 JDBC 原生连接时生效。 客户端使用的字符集,默认值为系统字符集。
- TSDBDriver.PROPERTY_KEY_CHARSET:客户端使用的字符集,默认值为系统字符集。
- TSDBDriver.PROPERTY_KEY_LOCALE:仅在使用 JDBC 原生连接时生效。 客户端语言环境,默认值系统当前 locale。
- TSDBDriver.PROPERTY_KEY_TIME_ZONE:仅在使用 JDBC 原生连接时生效。 客户端使用的时区,默认值为系统当前时区。
- 此外对 JDBC 原生连接,通过指定 URL 和 Properties 还可以指定其他参数,比如日志级别、SQL 长度等。更多详细配置请参考[客户端配置](/reference/config/#仅客户端适用)。
......@@ -348,7 +349,7 @@ JDBC 连接器可能报错的错误码包括 3 种:JDBC driver 本身的报错
具体的错误码请参考:
- [TDengine Java Connector](https://github.com/taosdata/TDengine/blob/develop/src/connector/jdbc/src/main/java/com/taosdata/jdbc/TSDBErrorNumbers.java)
- [TDengine Java Connector](https://github.com/taosdata/taos-connector-jdbc/blob/main/src/main/java/com/taosdata/jdbc/TSDBErrorNumbers.java)
- [TDengine_ERROR_CODE](https://github.com/taosdata/TDengine/blob/develop/src/inc/taoserror.h)
### 通过参数绑定写入数据
......
---
sidebar_position: 1
sidebar_label: PHP
title: PHP Connector
---
`php-tdengine` 是由社区贡献的 PHP 连接器扩展,还特别支持了 Swoole 协程化。
PHP 连接器依赖 TDengine 客户端驱动。
项目地址:<https://github.com/Yurunsoft/php-tdengine>
TDengine 服务端或客户端安装后,`taos.h` 位于:
- Linux:`/usr/local/taos/include`
- Windows:`C:\TDengine\include`
TDengine 客户端驱动的动态库位于:
- Linux: `/usr/local/taos/driver/libtaos.so`
- Windows: `C:\TDengine\taos.dll`
## 支持的平台
* Windows、Linux、MacOS
* PHP >= 7.4
* TDengine >= 2.0
* Swoole >= 4.8 (可选)
## 支持的版本
TDengine 客户端驱动的版本号与 TDengine 服务端的版本号是一一对应的强对应关系,建议使用与 TDengine 服务端完全相同的客户端驱动。虽然低版本的客户端驱动在前三段版本号一致(即仅第四段版本号不同)的情况下也能够与高版本的服务端相兼容,但这并非推荐用法。强烈不建议使用高版本的客户端驱动访问低版本的服务端。
## 安装步骤
### 安装 TDengine 客户端驱动
TDengine 客户端驱动的安装请参考 [安装指南](/reference/connector#安装步骤)
### 编译安装 php-tdengine
**下载代码并解压:**
```shell
curl -L -o php-tdengine.tar.gz https://github.com/Yurunsoft/php-tdengine/archive/refs/tags/v1.0.2.tar.gz \
&& mkdir php-tdengine \
&& tar -xzf php-tdengine.tar.gz -C php-tdengine --strip-components=1
```
> 版本 `v1.0.2` 可替换为任意更新的版本,可在 [TDengine PHP Connector 发布历史](https://github.com/Yurunsoft/php-tdengine/releases)。
**非 Swoole 环境:**
```shell
phpize && ./configure && make -j && make install
```
**手动指定 tdengine 目录:**
```shell
phpize && ./configure --with-tdengine-dir=/usr/local/Cellar/tdengine/2.4.0.0 && make -j && make install
```
> `--with-tdengine-dir=` 后跟上 tdengine 目录。
> 适用于默认找不到的情况,或者 MacOS 系统用户。
**Swoole 环境:**
```shell
phpize && ./configure --enable-swoole && make -j && make install
```
**启用扩展:**
方法一:在 `php.ini` 中加入 `extension=tdengine`
方法二:运行带参数 `php -dextension=tdengine test.php`
## 示例程序
本节展示了使用客户端驱动访问 TDengine 集群的常见访问方式的示例代码。
> 所有错误都会抛出异常: `TDengine\Exception\TDengineException`
### 建立连接
<details>
<summary>建立连接</summary>
```c
{{#include docs-examples/php/connect.php}}
```
</details>
### 插入数据
<details>
<summary>插入数据</summary>
```c
{{#include docs-examples/php/insert.php}}
```
</details>
### 同步查询
<details>
<summary>同步查询</summary>
```c
{{#include docs-examples/php/query.php}}
```
</details>
### 参数绑定
<details>
<summary>参数绑定</summary>
```c
{{#include docs-examples/php/insert_stmt.php}}
```
</details>
## 常量
| 常量 | 说明 |
| ------------ | ------------
| `TDengine\TSDB_DATA_TYPE_NULL` | null |
| `TDengine\TSDB_DATA_TYPE_BOOL` | bool |
| `TDengine\TSDB_DATA_TYPE_TINYINT` | tinyint |
| `TDengine\TSDB_DATA_TYPE_SMALLINT` | smallint |
| `TDengine\TSDB_DATA_TYPE_INT` | int |
| `TDengine\TSDB_DATA_TYPE_BIGINT` | bigint |
| `TDengine\TSDB_DATA_TYPE_FLOAT` | float |
| `TDengine\TSDB_DATA_TYPE_DOUBLE` | double |
| `TDengine\TSDB_DATA_TYPE_BINARY` | binary |
| `TDengine\TSDB_DATA_TYPE_TIMESTAMP` | timestamp |
| `TDengine\TSDB_DATA_TYPE_NCHAR` | nchar |
| `TDengine\TSDB_DATA_TYPE_UTINYINT` | utinyint |
| `TDengine\TSDB_DATA_TYPE_USMALLINT` | usmallint |
| `TDengine\TSDB_DATA_TYPE_UINT` | uint |
| `TDengine\TSDB_DATA_TYPE_UBIGINT` | ubigint |
......@@ -199,10 +199,9 @@ curl -u root:taosdata http://<FQDN>:<PORT>/rest/sql -d "select server_version()"
`connect()` 函数的所有参数都是可选的关键字参数。下面是连接参数的具体说明:
- `host`: 要连接的主机。默认是 localhost
- `url`: taosAdapter REST 服务的 URL。默认是 <http://localhost:6041>
- `user`: TDenigne 用户名。默认是 root。
- `password`: TDeingine 用户密码。默认是 taosdata。
- `port`: taosAdapter REST 服务监听端口。默认是 6041.
- `timeout`: HTTP 请求超时时间。单位为秒。默认为 `socket._GLOBAL_DEFAULT_TIMEOUT`。 一般无需配置。
</TabItem>
......
......@@ -21,7 +21,7 @@ taosBenchmark 有两种安装方式:
### 配置和运行方式
taosBenchmark 支持两种配置方式:[命令行参数](#命令行参数详解)[JSON 配置文件](#配置文件参数详解)。这两种方式是互斥的,在使用配置文件时只能使用一个命令行参数 `-f <json file>` 指定配置文件。在使用命令行参数运行 taosBenchmark 并控制其行为时则不能使用 `-f` 参数而要用其它参数来进行配置。除此之外,taosBenchmark 还提供了一种特殊的运行方式,即无参数运行。
taosBenchmark 需要在操作系统的终端执行,该工具支持两种配置方式:[命令行参数](#命令行参数详解)[JSON 配置文件](#配置文件参数详解)。这两种方式是互斥的,在使用配置文件时只能使用一个命令行参数 `-f <json file>` 指定配置文件。在使用命令行参数运行 taosBenchmark 并控制其行为时则不能使用 `-f` 参数而要用其它参数来进行配置。除此之外,taosBenchmark 还提供了一种特殊的运行方式,即无参数运行。
taosBenchmark 支持对 TDengine 做完备的性能测试,其所支持的 TDengine 功能分为三大类:写入、查询和订阅。这三种功能之间是互斥的,每次运行 taosBenchmark 只能选择其中之一。值得注意的是,所要测试的功能类型在使用命令行配置方式时是不可配置的,命令行配置方式只能测试写入性能。若要测试 TDengine 的查询和订阅性能,必须使用配置文件的方式,通过配置文件中的参数 `filetype` 指定所要测试的功能类型。
......
......@@ -134,7 +134,7 @@ taos --dump-config
| 适用范围 | 仅服务端适用 |
| 含义 | 服务器内部的系统监控开关。监控主要负责收集物理节点的负载状况,包括 CPU、内存、硬盘、网络带宽、HTTP 请求量的监控记录,记录信息存储在`LOG`库中。 |
| 取值范围 | 0:关闭监控服务, 1:激活监控服务。 |
| 缺省值 | 0 |
| 缺省值 | 1 |
### monitorInterval
......
......@@ -26,7 +26,7 @@ grafana-cli plugins install tdengine-datasource
sudo -u grafana grafana-cli plugins install tdengine-datasource
```
或者从 [GitHub](https://github.com/taosdata/grafanaplugin/releases/tag/latest) 或 [Grafana](https://grafana.com/grafana/plugins/tdengine-datasource/?tab=installation) 下载 .zip 文件到本地并解压到 Grafana 插件目录。命令行下载示例如下:
或者从 [GitHub](https://github.com/taosdata/grafanaplugin/tags) 或 [Grafana](https://grafana.com/grafana/plugins/tdengine-datasource/?tab=installation) 下载 .zip 文件到本地并解压到 Grafana 插件目录。命令行下载示例如下:
```bash
GF_VERSION=3.2.2
......
......@@ -8,30 +8,24 @@ MQTT 是流行的物联网数据传输协议,[EMQX](https://github.com/emqx/em
## 前置条件
要让 EMQX 能正常添加 TDengine 数据源,需要以下几方面的准备工作。
- TDengine 集群已经部署并正常运行
- taosAdapter 已经安装并正常运行。具体细节请参考 [taosAdapter 的使用手册](/reference/taosadapter)
- 如果使用后文介绍的模拟写入程序,需要安装合适版本的 Node.js,推荐安装 v12
- 如果使用后文介绍的模拟写入程序,需要安装合适版本的 Node.js,推荐安装 v12
## 安装并启动 EMQX
用户可以根据当前的操作系统,到 EMQX 官网下载安装包,并执行安装。下载地址如下:<https://www.emqx.io/zh/downloads>。安装后使用 `sudo emqx start``sudo systemctl start emqx` 启动 EMQX 服务。
## 在 TDengine 中为接收 MQTT 数据创建相应数据库和表结构
### 以 Docker 安装 TDengine 为例
```bash
docker exec -it tdengine bash
taos
```
## 创建数据库和表
### 创建数据库和表
在 TDengine 中为接收 MQTT 数据创建相应数据库和表结构。进入 TDengine CLI 复制并执行以下 SQL 语句:
```sql
create database test;
use test;
create table:
CREATE TABLE sensor_data (ts timestamp, temperature float, humidity float, volume float, PM10 float, pm25 float, SO2 float, NO2 float, CO float, sensor_id NCHAR(255), area TINYINT, coll_time timestamp);
CREATE DATABASE test;
USE test;
CREATE TABLE sensor_data (ts TIMESTAMP, temperature FLOAT, humidity FLOAT, volume FLOAT, pm10 FLOAT, pm25 FLOAT, so2 FLOAT, no2 FLOAT, co FLOAT, sensor_id NCHAR(255), area TINYINT, coll_time TIMESTAMP);
```
注:表结构以博客[数据传输、存储、展现,EMQX + TDengine 搭建 MQTT 物联网数据可视化平台](https://www.taosdata.com/blog/2020/08/04/1722.html)为例。后续操作均以此博客场景为例进行,请你根据实际应用场景进行修改。
......@@ -42,7 +36,7 @@ CREATE TABLE sensor_data (ts timestamp, temperature float, humidity float, volum
### 登录 EMQX Dashboard
使用浏览器打开网址 http://IP:18083 并登录 EMQX Dashboard。初次安装用户名为 `admin` 密码为:`public`
使用浏览器打开网址 http://IP:18083 并登录 EMQX Dashboard。初次安装用户名为 `admin` 密码为:`public`
![TDengine Database EMQX login dashboard](./emqx/login-dashboard.webp)
......@@ -54,6 +48,17 @@ CREATE TABLE sensor_data (ts timestamp, temperature float, humidity float, volum
### 编辑 SQL 字段
复制以下内容输入到 SQL 编辑框:
```sql
SELECT
payload
FROM
"sensor/data"
```
其中 `payload` 代表整个消息体, `sensor/data` 为本规则选取的消息主题。
![TDengine Database EMQX create rule](./emqx/create-rule.webp)
### 新增“动作(action handler)”
......@@ -64,101 +69,54 @@ CREATE TABLE sensor_data (ts timestamp, temperature float, humidity float, volum
![TDengine Database EMQX create resource](./emqx/create-resource.webp)
选择“发送数据到 Web 服务并点击“新建资源”按钮:
选择“发送数据到 Web 服务并点击“新建资源”按钮:
### 编辑“资源(Resource)”
选择“发送数据到 Web 服务“并填写 请求 URL 为 运行 taosAdapter 的服务器地址和端口(默认为 6041)。其他属性请保持默认值。
选择“WebHook”并填写“请求 URL”为 taosAdapter 提供 REST 服务的地址,如果是本地启动的 taosadapter, 那么默认地址为:
```
http://127.0.0.1:6041/rest/sql
```
其他属性请保持默认值。
![TDengine Database EMQX edit resource](./emqx/edit-resource.webp)
### 编辑“动作(action)”
编辑资源配置,增加 Authorization 认证的键/值配对项,相关文档请参考[ TDengine REST API 文档](https://docs.taosdata.com/reference/rest-api/)。在消息体中输入规则引擎替换模板。
编辑资源配置,增加 Authorization 认证的键/值配对项。默认用户名和密码对应的 Authorization 值为:
```
Basic cm9vdDp0YW9zZGF0YQ==
```
相关文档请参考[ TDengine REST API 文档](/reference/rest-api/)
在消息体中输入规则引擎替换模板:
```sql
INSERT INTO test.sensor_data VALUES(
now,
${payload.temperature},
${payload.humidity},
${payload.volume},
${payload.PM10},
${payload.pm25},
${payload.SO2},
${payload.NO2},
${payload.CO},
'${payload.id}',
${payload.area},
${payload.ts}
)
```
![TDengine Database EMQX edit action](./emqx/edit-action.webp)
最后点击左下方的 “Create” 按钮,保存规则。
## 编写模拟测试程序
```javascript
// mock.js
const mqtt = require('mqtt')
const Mock = require('mockjs')
const EMQX_SERVER = 'mqtt://localhost:1883'
const CLIENT_NUM = 10
const STEP = 5000 // 模拟采集时间间隔 ms
const AWAIT = 5000 // 每次发送完后休眠时间,防止消息速率过快 ms
const CLIENT_POOL = []
startMock()
function sleep(timer = 100) {
return new Promise(resolve => {
setTimeout(resolve, timer)
})
}
async function startMock() {
const now = Date.now()
for (let i = 0; i < CLIENT_NUM; i++) {
const client = await createClient(`mock_client_${i}`)
CLIENT_POOL.push(client)
}
// last 24h every 5s
const last = 24 * 3600 * 1000
for (let ts = now - last; ts <= now; ts += STEP) {
for (const client of CLIENT_POOL) {
const mockData = generateMockData()
const data = {
...mockData,
id: client.clientId,
area: 0,
ts,
}
client.publish('sensor/data', JSON.stringify(data))
}
const dateStr = new Date(ts).toLocaleTimeString()
console.log(`${dateStr} send success.`)
await sleep(AWAIT)
}
console.log(`Done, use ${(Date.now() - now) / 1000}s`)
}
/**
* Init a virtual mqtt client
* @param {string} clientId ClientID
*/
function createClient(clientId) {
return new Promise((resolve, reject) => {
const client = mqtt.connect(EMQX_SERVER, {
clientId,
})
client.on('connect', () => {
console.log(`client ${clientId} connected`)
resolve(client)
})
client.on('reconnect', () => {
console.log('reconnect')
})
client.on('error', (e) => {
console.error(e)
reject(e)
})
})
}
/**
* Generate mock data
*/
function generateMockData() {
return {
"temperature": parseFloat(Mock.Random.float(22, 100).toFixed(2)),
"humidity": parseFloat(Mock.Random.float(12, 86).toFixed(2)),
"volume": parseFloat(Mock.Random.float(20, 200).toFixed(2)),
"PM10": parseFloat(Mock.Random.float(0, 300).toFixed(2)),
"pm25": parseFloat(Mock.Random.float(0, 300).toFixed(2)),
"SO2": parseFloat(Mock.Random.float(0, 50).toFixed(2)),
"NO2": parseFloat(Mock.Random.float(0, 50).toFixed(2)),
"CO": parseFloat(Mock.Random.float(0, 50).toFixed(2)),
"area": Mock.Random.integer(0, 20),
"ts": 1596157444170,
}
}
{{#include docs-examples/other/mock.js}}
```
注意:代码中 CLIENT_NUM 在开始测试中可以先设置一个较小的值,避免硬件性能不能完全处理较大并发客户端数量。
......@@ -188,4 +146,3 @@ node mock.js
TDengine 详细使用方法请参考 [TDengine 官方文档](https://docs.taosdata.com/)
EMQX 详细使用方法请参考 [EMQX 官方文档](https://www.emqx.io/docs/zh/v4.4/rule/rule-engine.html)
......@@ -74,7 +74,7 @@ title: 常见问题及反馈
检查服务器侧 TCP 端口连接是否工作:`nc -l {port}`
检查客户端侧 TCP 端口连接是否工作:`nc {hostIP} {port}`
- Windows 系统请使用 PowerShell 命令 Net-TestConnection -ComputerName {fqdn} -Port {port} 检测服务段端口是否访问
- Windows 系统请使用 PowerShell 命令 Test-NetConnection -ComputerName {fqdn} -Port {port} 检测服务段端口是否访问
10. 也可以使用 taos 程序内嵌的网络连通检测功能,来验证服务器和客户端之间指定的端口连接是否通畅(包括 TCP 和 UDP):[TDengine 内嵌网络检测工具使用指南](https://www.taosdata.com/blog/2020/09/08/1816.html)
......
......@@ -19,7 +19,7 @@ import InstallOnLinux from "../../14-reference/03-connector/\_windows_install.md
import VerifyLinux from "../../14-reference/03-connector/\_verify_linux.mdx";
import VerifyWindows from "../../14-reference/03-connector/\_verify_windows.mdx";
Any application programs running on any kind of platform can access TDengine through the REST API provided by TDengine. For details, please refer to [REST API](/reference/rest-api/). Additionally, application programs can use the connectors of multiple programming languages including C/C++, Java, Python, Go, Node.js, C#, and Rust to access TDengine. This chapter describes how to establish a connection to TDengine and briefly introduces how to install and use connectors. For details about the connectors, please refer to [Connectors](/reference/connector/)
Any application programs running on any kind of platform can access TDengine through the REST API provided by TDengine. For details, please refer to [REST API](/reference/rest-api/). Additionally, application programs can use the connectors of multiple programming languages including C/C++, Java, Python, Go, Node.js, C#, Rust to access TDengine. This chapter describes how to establish a connection to TDengine and briefly introduces how to install and use connectors. TDengine community also provides connectors in LUA and PHP languages. For details about the connectors, please refer to [Connectors](/reference/connector/).
## Establish Connection
......@@ -200,6 +200,46 @@ install.packages("RJDBC")
If the client driver (taosc) is already installed, then the C connector is already available.
<br/>
</TabItem>
<TabItem label="PHP" value="php">
**Download Source Code Package and Unzip:**
```shell
curl -L -o php-tdengine.tar.gz https://github.com/Yurunsoft/php-tdengine/archive/refs/tags/v1.0.2.tar.gz \
&& mkdir php-tdengine \
&& tar -xzf php-tdengine.tar.gz -C php-tdengine --strip-components=1
```
> Version number `v1.0.2` is only for example, it can be replaced to any newer version, please check available version from [TDengine PHP Connector Releases](https://github.com/Yurunsoft/php-tdengine/releases).
**Non-Swoole Environment:**
```shell
phpize && ./configure && make -j && make install
```
**Specify TDengine Location:**
```shell
phpize && ./configure --with-tdengine-dir=/usr/local/Cellar/tdengine/2.4.0.0 && make -j && make install
```
> `--with-tdengine-dir=` is followed by the TDengine installation location.
> This way is useful in case TDengine location can't be found automatically or macOS.
**Swoole Environment:**
```shell
phpize && ./configure --enable-swoole && make -j && make install
```
**Enable The Extension:**
Option One: Add `extension=tdengine` in `php.ini`
Option Two: Specify the extension on CLI `php -d extension=tdengine test.php`
</TabItem>
</Tabs>
......
......@@ -113,13 +113,6 @@ From version 2.1.5.0, tables can be automatically created using a super table as
INSERT INTO d21001 USING meters TAGS ('California.SanFrancisco', 2) FILE '/tmp/csvfile.csv';
```
Multiple tables can be automatically created and inserted in a single SQL statement, like below:
```sql
INSERT INTO d21001 USING meters TAGS ('California.SanFrancisco', 2) FILE '/tmp/csvfile_21001.csv'
d21002 USING meters (groupId) TAGS (2) FILE '/tmp/csvfile_21002.csv';
```
## More About Insert
For SQL statement like `insert`, a stream parsing strategy is applied. That means before an error is found and the execution is aborted, the part prior to the error point has already been executed. Below is an experiment to help understand the behavior.
......
......@@ -26,7 +26,7 @@ Please refer to [list of supported platforms](/reference/connector#supported-pla
## Supported versions
The version number of the TDengine client driver and the version number of the TDengine server should be the same. A lower version of the client driver is compatible with a higher version of the server, if the first three version numbers are the same (i.e., only the fourth version number is different). For e.g. if the client version is x.y.z.1 and the server version is x.y.z.2 the client and server are compatible. But in general we do not recommend using a lower client version with a newer server version. It is also strongly discouraged to use a higher version of the client driver to access a lower version of the TDengine server.
The version number of the TDengine client driver and the version number of the TDengine server should be same. A lower version of the client driver is compatible with a higher version of the server, if the first three version numbers are the same (i.e., only the fourth version number is different). For e.g. if the client version is x.y.z.1 and the server version is x.y.z.2 the client and server are compatible. But in general we do not recommend using a lower client version with a newer server version. It is also strongly discouraged to use a higher version of the client driver to access a lower version of the TDengine server.
## Installation steps
......
......@@ -42,18 +42,18 @@ Please refer to [Version Support List](/reference/connector#version-support).
TDengine currently supports timestamp, number, character, Boolean type, and the corresponding type conversion with Java is as follows:
| TDengine DataType | JDBCType (driver version < 2.0.24) | JDBCType (driver version > = 2.0.24) |
| ----------------- | --------------------------------- | ---------------------------------- |
| TIMESTAMP | java.lang.Long | java.sql.Timestamp |
| INT | java.lang.Integer | java.lang.Integer |
| BIGINT | java.lang.Long | java.lang.Long |
| FLOAT | java.lang.Float | java.lang.Float |
| DOUBLE | java.lang.Double | java.lang.Double |
| SMALLINT | java.lang.Short | java.lang.Short |
| TINYINT | java.lang.Byte | java.lang.Byte |
| BOOL | java.lang.Boolean | java.lang.Boolean |
| BINARY | java.lang.String | byte array |
| NCHAR | java.lang.String | java.lang.String |
| JSON | - | java.lang.String |
| ----------------- | ---------------------------------- | ------------------------------------ |
| TIMESTAMP | java.lang.Long | java.sql.Timestamp |
| INT | java.lang.Integer | java.lang.Integer |
| BIGINT | java.lang.Long | java.lang.Long |
| FLOAT | java.lang.Float | java.lang.Float |
| DOUBLE | java.lang.Double | java.lang.Double |
| SMALLINT | java.lang.Short | java.lang.Short |
| TINYINT | java.lang.Byte | java.lang.Byte |
| BOOL | java.lang.Boolean | java.lang.Boolean |
| BINARY | java.lang.String | byte array |
| NCHAR | java.lang.String | java.lang.String |
| JSON | - | java.lang.String |
**Note**: Only TAG supports JSON types
......@@ -91,8 +91,8 @@ Add following dependency in the `pom.xml` file of your Maven project:
You can build Java connector from source code after cloning the TDengine project:
```shell
git clone https://github.com/taosdata/TDengine.git
cd TDengine/src/connector/jdbc
git clone https://github.com/taosdata/taos-connector-jdbc.git
cd taos-connector-jdbc
mvn clean install -Dmaven.test.skip=true
```
......@@ -197,6 +197,7 @@ The configuration parameters in the URL are as follows.
- user: Login TDengine user name, default value 'root'.
- password: user login password, default value 'taosdata'.
- batchfetch: true: pull the result set in batch when executing the query; false: pull the result set row by row. The default value is false. batchfetch uses HTTP for data transfer. The JDBC REST connection supports bulk data pulling function in taos-jdbcdriver-2.0.38 and TDengine 2.4.0.12 and later versions. taos-jdbcdriver and TDengine transfer data via WebSocket connection. Compared with HTTP, WebSocket enables JDBC REST connection to support large data volume querying and improve query performance.
- charset: specify the charset to parse the string, this parameter is valid only when set batchfetch to true.
- batchErrorIgnore: true: when executing executeBatch of Statement, if one SQL execution fails in the middle, continue to execute the following SQL. false: no longer execute any statement after the failed SQL. The default value is: false.
**Note**: Some configuration items (e.g., locale, timezone) do not work in the REST connection.
......@@ -258,10 +259,10 @@ The configuration parameters in properties are as follows.
- TSDBDriver.PROPERTY_KEY_BATCH_LOAD: true: pull the result set in batch when executing query; false: pull the result set row by row. The default value is: false.
- TSDBDriver.PROPERTY_KEY_BATCH_ERROR_IGNORE: true: when executing executeBatch of Statement, if there is a SQL execution failure in the middle, continue to execute the following sq. false: no longer execute any statement after the failed SQL. The default value is: false.
- TSDBDriver.PROPERTY_KEY_CONFIG_DIR: Only works when using JDBC native connection. Client configuration file directory path, default value `/etc/taos` on Linux OS, default value `C:/TDengine/cfg` on Windows OS.
- TSDBDriver.PROPERTY_KEY_CHARSET: takes effect only when using JDBC native connection. In the character set used by the client, the default value is the system character set.
- TSDBDriver.PROPERTY_KEY_CHARSET: In the character set used by the client, the default value is the system character set.
- TSDBDriver.PROPERTY_KEY_LOCALE: this only takes effect when using JDBC native connection. Client language environment, the default value is system current locale.
- TSDBDriver.PROPERTY_KEY_TIME_ZONE: only takes effect when using JDBC native connection. In the time zone used by the client, the default value is the system's current time zone.
For JDBC native connections, you can specify other parameters, such as log level, SQL length, etc., by specifying URL and Properties. For more detailed configuration, please refer to [Client Configuration](/reference/config/#Client-Only).
For JDBC native connections, you can specify other parameters, such as log level, SQL length, etc., by specifying URL and Properties. For more detailed configuration, please refer to [Client Configuration](/reference/config/#Client-Only).
### Priority of configuration parameters
......@@ -350,7 +351,7 @@ There are three types of error codes that the JDBC connector can report:
For specific error codes, please refer to.
- [TDengine Java Connector](https://github.com/taosdata/TDengine/blob/develop/src/connector/jdbc/src/main/java/com/taosdata/jdbc/TSDBErrorNumbers.java)
- [TDengine Java Connector](https://github.com/taosdata/taos-connector-jdbc/blob/main/src/main/java/com/taosdata/jdbc/TSDBErrorNumbers.java)
- [TDengine_ERROR_CODE](https://github.com/taosdata/TDengine/blob/develop/src/inc/taoserror.h)
### Writing data via parameter binding
......@@ -808,11 +809,11 @@ Please refer to: [JDBC example](https://github.com/taosdata/TDengine/tree/develo
## Recent update logs
| taos-jdbcdriver version | major changes |
| :------------------: | :----------------------------: |
| 2.0.38 | JDBC REST connections add bulk pull function |
| 2.0.37 | Added support for json tags |
| 2.0.36 | Add support for schemaless writing |
| taos-jdbcdriver version | major changes |
| :---------------------: | :------------------------------------------: |
| 2.0.38 | JDBC REST connections add bulk pull function |
| 2.0.37 | Added support for json tags |
| 2.0.36 | Add support for schemaless writing |
## Frequently Asked Questions
......
---
sidebar_position: 1
sidebar_label: PHP
title: PHP Connector
---
`php-tdengine` is the TDengine PHP connector provided by TDengine community. In particular, it supports Swoole coroutine.
PHP Connector relies on TDengine client driver.
Project Repository:<https://github.com/Yurunsoft/php-tdengine>
After TDengine client or server is installed, `taos.h` is located at:
- Linux:`/usr/local/taos/include`
- Windows:`C:\TDengine\include`
TDengine client driver is located at:
- Linux: `/usr/local/taos/driver/libtaos.so`
- Windows: `C:\TDengine\taos.dll`
## Supported Platforms
- Windows、Linux、MacOS
- PHP >= 7.4
- TDengine >= 2.0
- Swoole >= 4.8 (Optional)
## Supported Versions
Because the version of TDengine client driver is tightly associated with that of TDengine server, it's strongly suggested to use the client driver of same version as TDengine server, even though the client driver can work with TDengine server if the first 3 sections of the versions are same.
## Installation
### Install TDengine Client Driver
Regarding how to install TDengine client driver please refer to [Install Client Driver](/reference/connector#installation-steps)
### Install php-tdengine
**Download Source Code Package and Unzip:**
```shell
curl -L -o php-tdengine.tar.gz https://github.com/Yurunsoft/php-tdengine/archive/refs/tags/v1.0.2.tar.gz \
&& mkdir php-tdengine \
&& tar -xzf php-tdengine.tar.gz -C php-tdengine --strip-components=1
```
> Version number `v1.0.2` is only for example, it can be replaced to any newer version, please find available versions in [TDengine PHP Connector Releases](https://github.com/Yurunsoft/php-tdengine/releases).
**Non-Swoole Environment:**
```shell
phpize && ./configure && make -j && make install
```
**Specify TDengine location:**
```shell
phpize && ./configure --with-tdengine-dir=/usr/local/Cellar/tdengine/2.4.0.0 && make -j && make install
```
> `--with-tdengine-dir=` is followed by TDengine location.
> It's useful in case TDengine installatio location can't be found automatically or MacOS.
**Swoole Environment:**
```shell
phpize && ./configure --enable-swoole && make -j && make install
```
**Enable Extension:**
Option One: Add `extension=tdengine` in `php.ini`.
Option Two: Use CLI `php -dextension=tdengine test.php`.
## Sample Programs
In this section a few sample programs which use TDengine PHP connector to access TDengine cluster are demonstrated.
> Any error would throw exception: `TDengine\Exception\TDengineException`
### Establish Conection
<details>
<summary>Establish Connection</summary>
```c
{{#include docs-examples/php/connect.php}}
```
</details>
### Insert Data
<details>
<summary>Insert Data</summary>
```c
{{#include docs-examples/php/insert.php}}
```
</details>
### Synchronous Query
<details>
<summary>Synchronous Query</summary>
```c
{{#include docs-examples/php/query.php}}
```
</details>
### Parameter Binding
<details>
<summary>Parameter Binding</summary>
```c
{{#include docs-examples/php/insert_stmt.php}}
```
</details>
## Constants
| Constant | Description |
| ----------------------------------- | ----------- |
| `TDengine\TSDB_DATA_TYPE_NULL` | null |
| `TDengine\TSDB_DATA_TYPE_BOOL` | bool |
| `TDengine\TSDB_DATA_TYPE_TINYINT` | tinyint |
| `TDengine\TSDB_DATA_TYPE_SMALLINT` | smallint |
| `TDengine\TSDB_DATA_TYPE_INT` | int |
| `TDengine\TSDB_DATA_TYPE_BIGINT` | bigint |
| `TDengine\TSDB_DATA_TYPE_FLOAT` | float |
| `TDengine\TSDB_DATA_TYPE_DOUBLE` | double |
| `TDengine\TSDB_DATA_TYPE_BINARY` | binary |
| `TDengine\TSDB_DATA_TYPE_TIMESTAMP` | timestamp |
| `TDengine\TSDB_DATA_TYPE_NCHAR` | nchar |
| `TDengine\TSDB_DATA_TYPE_UTINYINT` | utinyint |
| `TDengine\TSDB_DATA_TYPE_USMALLINT` | usmallint |
| `TDengine\TSDB_DATA_TYPE_UINT` | uint |
| `TDengine\TSDB_DATA_TYPE_UBIGINT` | ubigint |
......@@ -199,10 +199,9 @@ The `connect()` function returns a `taos.TaosConnection` instance. In client-sid
All arguments to the `connect()` function are optional keyword arguments. The following are the connection parameters specified.
- `host`: The host to connect to. The default is localhost.
- `url`: The URL of taosAdapter REST service. The default is <http://localhost:6041>.
- `user`: TDengine user name. The default is `root`.
- `password`: TDengine user password. The default is `taosdata`.
- `port`: The port on which the taosAdapter REST service listens. Default is 6041.
- `timeout`: HTTP request timeout in seconds. The default is `socket._GLOBAL_DEFAULT_TIMEOUT`. Usually, no configuration is needed.
</TabItem>
......
......@@ -21,7 +21,7 @@ There are two ways to install taosBenchmark:
### Configuration and running methods
taosBenchmark supports two configuration methods: [Command-line arguments](#Command-line arguments in detailed) and [JSON configuration file](#Configuration file arguments in detailed). These two methods are mutually exclusive. Users can use `-f <json file>` to specify a configuration file. When running taosBenchmark with command-line arguments to control its behavior, users should use other parameters for configuration, but not the `-f` parameter. In addition, taosBenchmark offers a special way of running without parameters.
TaosBenchmark needs to be executed on the terminal of the operating system, it supports two configuration methods: [Command-line arguments](#Command-line arguments in detailed) and [JSON configuration file](#Configuration file arguments in detailed). These two methods are mutually exclusive. Users can use `-f <json file>` to specify a configuration file. When running taosBenchmark with command-line arguments to control its behavior, users should use other parameters for configuration, but not the `-f` parameter. In addition, taosBenchmark offers a special way of running without parameters.
taosBenchmark supports complete performance testing of TDengine. taosBenchmark supports the TDengine functions in three categories: write, query, and subscribe. These three functions are mutually exclusive, and users can select only one of them each time taosBenchmark runs. It is important to note that the type of functionality to be tested is not configurable when using the command-line configuration method, which can only test writing performance. To test the query and subscription performance of the TDengine, you must use the configuration file method and specify the function type to test via the parameter `filetype` in the configuration file.
......
......@@ -134,7 +134,7 @@ TDengine uses 13 continuous ports, both TCP and UDP, starting with the port spec
| Applicable | Server Only |
| Meaning | The switch for monitoring inside server. The workload of the hosts, including CPU, memory, disk, network, TTP requests, are collected and stored in a system builtin database `LOG` |
| Value Range | 0: monitoring disabled, 1: monitoring enabled |
| Default Value | 0 |
| Default Value | 1 |
### monitorInterval
......
......@@ -28,7 +28,7 @@ grafana-cli plugins install tdengine-datasource
sudo -u grafana grafana-cli plugins install tdengine-datasource
```
Alternatively, you can manually download the .zip file from [GitHub](https://github.com/taosdata/grafanaplugin/releases/tag/latest) or [Grafana](https://grafana.com/grafana/plugins/tdengine-datasource/?tab=installation) and unpack it into your grafana plugins directory.
Alternatively, you can manually download the .zip file from [GitHub](https://github.com/taosdata/grafanaplugin/tags) or [Grafana](https://grafana.com/grafana/plugins/tdengine-datasource/?tab=installation) and unpack it into your grafana plugins directory.
```bash
GF_VERSION=3.2.2
......
......@@ -16,22 +16,15 @@ The following preparations are required for EMQX to add TDengine data sources co
Depending on the current operating system, users can download the installation package from the [EMQX official website](https://www.emqx.io/downloads) and execute the installation. After installation, use `sudo emqx start` or `sudo systemctl start emqx` to start the EMQX service.
## Create the appropriate database and table schema in TDengine for receiving MQTT data
### Take the Docker installation of TDengine as an example
## Create Database and Table
```bash
docker exec -it tdengine bash
taos
```
### Create Database and Table
In this step we create the appropriate database and table schema in TDengine for receiving MQTT data. Open TDengine CLI and execute SQL bellow:
```sql
CREATE DATABASE test;
USE test;
CREATE TABLE sensor_data (ts timestamp, temperature float, humidity float, volume float, PM10 float, pm25 float, SO2 float, NO2 float, CO float, sensor_id NCHAR(255), area TINYINT, coll_time timestamp);
CREATE TABLE sensor_data (ts TIMESTAMP, temperature FLOAT, humidity FLOAT, volume FLOAT, pm10 FLOAT, pm25 FLOAT, so2 FLOAT, no2 FLOAT, co FLOAT, sensor_id NCHAR(255), area TINYINT, coll_time TIMESTAMP);
```
Note: The table schema is based on the blog [(In Chinese) Data Transfer, Storage, Presentation, EMQX + TDengine Build MQTT IoT Data Visualization Platform](https://www.taosdata.com/blog/2020/08/04/1722.html) as an example. Subsequent operations are carried out with this blog scenario too. Please modify it according to your actual application scenario.
......@@ -54,6 +47,15 @@ Select "Rule" in the "Rule Engine" on the left and click the "Create" button: !
### Edit SQL fields
Copy SQL bellow and paste it to the SQL edit area:
```sql
SELECT
payload
FROM
"sensor/data"
```
![TDengine Database EMQX create rule](./emqx/create-rule.webp)
### Add "action handler"
......@@ -68,97 +70,45 @@ Select "Data to Web Service" and click the "New Resource" button.
### Edit "Resource"
Select "Data to Web Service" and fill in the request URL as the address and port of the server running taosAdapter (default is 6041). Leave the other properties at their default values.
Select "WebHook" and fill in the request URL as the address and port of the server running taosAdapter (default is 6041). Leave the other properties at their default values.
![TDengine Database EMQX edit resource](./emqx/edit-resource.webp)
### Edit "action"
Edit the resource configuration to add the key/value pairing for Authorization. Please refer to the [ TDengine REST API documentation ](https://docs.taosdata.com/reference/rest-api/) for the authorization in details. Enter the rule engine replacement template in the message body.
Edit the resource configuration to add the key/value pairing for Authorization. If you use the default TDengine username and password then the value of key Authorization is:
```
Basic cm9vdDp0YW9zZGF0YQ==
```
Please refer to the [ TDengine REST API documentation ](/reference/rest-api/) for the authorization in details.
Enter the rule engine replacement template in the message body:
```sql
INSERT INTO test.sensor_data VALUES(
now,
${payload.temperature},
${payload.humidity},
${payload.volume},
${payload.PM10},
${payload.pm25},
${payload.SO2},
${payload.NO2},
${payload.CO},
'${payload.id}',
${payload.area},
${payload.ts}
)
```
![TDengine Database EMQX edit action](./emqx/edit-action.webp)
Finally, click the "Create" button at bottom left corner saving the rule.
## Compose program to mock data
```javascript
// mock.js
const mqtt = require('mqtt')
const Mock = require('mockjs')
const EMQX_SERVER = 'mqtt://localhost:1883'
const CLIENT_NUM = 10
const STEP = 5000 // Data interval in ms
const AWAIT = 5000 // Sleep time after data be written once to avoid data writing too fast
const CLIENT_POOL = []
startMock()
function sleep(timer = 100) {
return new Promise(resolve => {
setTimeout(resolve, timer)
})
}
async function startMock() {
const now = Date.now()
for (let i = 0; i < CLIENT_NUM; i++) {
const client = await createClient(`mock_client_${i}`)
CLIENT_POOL.push(client)
}
// last 24h every 5s
const last = 24 * 3600 * 1000
for (let ts = now - last; ts <= now; ts += STEP) {
for (const client of CLIENT_POOL) {
const mockData = generateMockData()
const data = {
...mockData,
id: client.clientId,
area: 0,
ts,
}
client.publish('sensor/data', JSON.stringify(data))
}
const dateStr = new Date(ts).toLocaleTimeString()
console.log(`${dateStr} send success.`)
await sleep(AWAIT)
}
console.log(`Done, use ${(Date.now() - now) / 1000}s`)
}
/**
* Init a virtual mqtt client
* @param {string} clientId ClientID
*/
function createClient(clientId) {
return new Promise((resolve, reject) => {
const client = mqtt.connect(EMQX_SERVER, {
clientId,
})
client.on('connect', () => {
console.log(`client ${clientId} connected`)
resolve(client)
})
client.on('reconnect', () => {
console.log('reconnect')
})
client.on('error', (e) => {
console.error(e)
reject(e)
})
})
}
/**
* Generate mock data
*/
function generateMockData() {
return {
"temperature": parseFloat(Mock.Random.float(22, 100).toFixed(2)),
"humidity": parseFloat(Mock.Random.float(12, 86).toFixed(2)),
"volume": parseFloat(Mock.Random.float(20, 200).toFixed(2)),
"PM10": parseFloat(Mock.Random.float(0, 300).toFixed(2)),
"pm25": parseFloat(Mock.Random.float(0, 300).toFixed(2)),
"SO2": parseFloat(Mock.Random.float(0, 50).toFixed(2)),
"NO2": parseFloat(Mock.Random.float(0, 50).toFixed(2)),
"CO": parseFloat(Mock.Random.float(0, 50).toFixed(2)),
"area": Mock.Random.integer(0, 20),
"ts": 1596157444170,
}
}
{{#include docs-examples/other/mock.js}}
```
Note: `CLIENT_NUM` in the code can be set to a smaller value at the beginning of the test to avoid hardware performance be not capable to handle a more significant number of concurrent clients.
......
......@@ -45,7 +45,7 @@ When the client is unable to connect to the server, you can try the following wa
Check whether a TCP port on server side is open: `nc -l {port}`
Check whether a TCP port on client side is open: `nc {hostIP} {port}`
- On Windows system `Net-TestConnection -ComputerName {fqdn} -Port {port}` on PowerShell can be used to check whether the port on server side is open for access.
- On Windows system `Test-NetConnection -ComputerName {fqdn} -Port {port}` on PowerShell can be used to check whether the port on server side is open for access.
7. TDengine CLI `taos` can also be used to check network, please refer to [TDengine CLI](/reference/taos-shell).
......
---
title: 2.6
---
[2.6.0.1](https://github.com/taosdata/TDengine/releases/tag/ver-2.6.0.1)
[2.6.0.0](https://github.com/taosdata/TDengine/releases/tag/ver-2.6.0.0)
\ No newline at end of file
---
title: 2.4
---
[2.4.0.25](https://github.com/taosdata/TDengine/releases/tag/ver-2.4.0.25)
[2.4.0.24](https://github.com/taosdata/TDengine/releases/tag/ver-2.4.0.24)
[2.4.0.20](https://github.com/taosdata/TDengine/releases/tag/ver-2.4.0.20)
[2.4.0.18](https://github.com/taosdata/TDengine/releases/tag/ver-2.4.0.18)
[2.4.0.16](https://github.com/taosdata/TDengine/releases/tag/ver-2.4.0.16)
[2.4.0.14](https://github.com/taosdata/TDengine/releases/tag/ver-2.4.0.14)
[2.4.0.12](https://github.com/taosdata/TDengine/releases/tag/ver-2.4.0.12)
[2.4.0.10](https://github.com/taosdata/TDengine/releases/tag/ver-2.4.0.10)
[2.4.0.7](https://github.com/taosdata/TDengine/releases/tag/ver-2.4.0.7)
[2.4.0.5](https://github.com/taosdata/TDengine/releases/tag/ver-2.4.0.5)
[2.4.0.4](https://github.com/taosdata/TDengine/releases/tag/ver-2.4.0.4)
[2.4.0.0](https://github.com/taosdata/TDengine/releases/tag/ver-2.4.0.0)
\ No newline at end of file
---
title: Releases
---
```mdx-code-block
import DocCardList from '@theme/DocCardList';
import {useCurrentSidebarCategory} from '@docusaurus/theme-common';
<DocCardList items={useCurrentSidebarCategory().items}/>
```
\ No newline at end of file
// mock.js
const mqtt = require('mqtt')
const Mock = require('mockjs')
const EMQX_SERVER = 'mqtt://localhost:1883'
const CLIENT_NUM = 10
const STEP = 5000 // Data interval in ms
const AWAIT = 5000 // Sleep time after data be written once to avoid data writing too fast
const CLIENT_POOL = []
startMock()
function sleep(timer = 100) {
return new Promise(resolve => {
setTimeout(resolve, timer)
})
}
async function startMock() {
const now = Date.now()
for (let i = 0; i < CLIENT_NUM; i++) {
const client = await createClient(`mock_client_${i}`)
CLIENT_POOL.push(client)
}
// last 24h every 5s
const last = 24 * 3600 * 1000
for (let ts = now - last; ts <= now; ts += STEP) {
for (const client of CLIENT_POOL) {
const mockData = generateMockData()
const data = {
...mockData,
id: client.clientId,
area: 0,
ts,
}
client.publish('sensor/data', JSON.stringify(data))
}
const dateStr = new Date(ts).toLocaleTimeString()
console.log(`${dateStr} send success.`)
await sleep(AWAIT)
}
console.log(`Done, use ${(Date.now() - now) / 1000}s`)
}
/**
* Init a virtual mqtt client
* @param {string} clientId ClientID
*/
function createClient(clientId) {
return new Promise((resolve, reject) => {
const client = mqtt.connect(EMQX_SERVER, {
clientId,
})
client.on('connect', () => {
console.log(`client ${clientId} connected`)
resolve(client)
})
client.on('reconnect', () => {
console.log('reconnect')
})
client.on('error', (e) => {
console.error(e)
reject(e)
})
})
}
/**
* Generate mock data
*/
function generateMockData() {
return {
"temperature": parseFloat(Mock.Random.float(22, 100).toFixed(2)),
"humidity": parseFloat(Mock.Random.float(12, 86).toFixed(2)),
"volume": parseFloat(Mock.Random.float(20, 200).toFixed(2)),
"PM10": parseFloat(Mock.Random.float(0, 300).toFixed(2)),
"pm25": parseFloat(Mock.Random.float(0, 300).toFixed(2)),
"SO2": parseFloat(Mock.Random.float(0, 50).toFixed(2)),
"NO2": parseFloat(Mock.Random.float(0, 50).toFixed(2)),
"CO": parseFloat(Mock.Random.float(0, 50).toFixed(2)),
"area": Mock.Random.integer(0, 20),
"ts": 1596157444170,
}
}
\ No newline at end of file
......@@ -22,7 +22,7 @@ try {
// set table name and tags
$stmt->setTableNameTags('d1001', [
// 支持格式同参数绑定
// same format as parameter binding
[TDengine\TSDB_DATA_TYPE_BINARY, 'California.SanFrancisco'],
[TDengine\TSDB_DATA_TYPE_INT, 2],
]);
......
# ANCHOR: connect
from taosrest import connect, TaosRestConnection, TaosRestCursor
conn: TaosRestConnection = connect(host="localhost",
conn: TaosRestConnection = connect(url="http://localhost:6041",
user="root",
password="taosdata",
port=6041,
timeout=30)
# ANCHOR_END: connect
......
from taosrest import RestClient
client = RestClient("localhost", 6041, "root", "taosdata")
client = RestClient("http://localhost:6041", user="root", password="taosdata")
res: dict = client.sql("SELECT ts, current FROM power.meters LIMIT 1")
print(res)
......
<!DOCTYPE html><html lang='cn'><head><title>文档 | 涛思数据</title><meta name='description' content='TDengine是一个开源的专为物联网、车联网、工业互联网、IT运维等设计和优化的大数据平台。除核心的快10倍以上的时序数据库功能外,还提供缓存、数据订阅、流式计算等功能,最大程度减少研发和运维的工作量。'><meta name='keywords' content='大数据,Big Data,开源,物联网,车联网,工业互联网,IT运维, 时序数据库,缓存,数据订阅,消息队列,流式计算,开源,涛思数据,TAOS Data, TDengine'><meta name='title' content='文档 | 涛思数据'><meta property='og:site_name' content='涛思数据'/><meta property='og:title' content='文档 | 涛思数据'/><meta property='og:type' content='article'/><meta property='og:url' content='https://www.taosdata.com/cn/documentation/administrator-ch/index.php'/><meta property='og:description' content='TDengine是一个开源的专为物联网、车联网、工业互联网、IT运维等设计和优化的大数据平台。除核心的快10倍以上的时序数据库功能外,还提供缓存、数据订阅、流式计算等功能,最大程度减少研发和运维的工作量。' /><link rel='canonical' href='https://www.taosdata.com/cn/documentation/administrator-ch/index.php'/><script src='../lib/jquery-3.4.1.min.js' type='application/javascript'></script><link href='../lib/bootstrap.min.css' rel='stylesheet'><link href='../styles/base.min.css' rel='stylesheet'><link rel='stylesheet' href='../lib/docs/taosdataprettify.css'><link rel='stylesheet' href='../lib/docs/docs.css'><script src='../lib/docs/prettify.js'></script><script src='../lib/docs/prettyprint-sql.js'></script></head><body><script>$('#documentation-href').addClass('active')</script><div class='container-fluid'><main class='content-wrapper'><section class='documentation'><a href='../index.html'>回去</a><h1>系统管理</h1>
<a class='anchor' id='文件目录结构'></a><h2>文件目录结构</h2>
<p>安装TDengine后,默认会在操作系统中生成下列目录或文件:</p>
<figure><table>
<thead>
<tr>
<th>目录/文件</th>
<th style="text-align:left;">说明</th>
</tr>
</thead>
<tbody>
<tr>
<td>/etc/taos/taos.cfg</td>
<td style="text-align:left;">TDengine默认[配置文件]</td>
</tr>
<tr>
<td>/usr/local/taos/driver</td>
<td style="text-align:left;">TDengine动态链接库目录</td>
</tr>
<tr>
<td>/var/lib/taos</td>
<td style="text-align:left;">TDengine默认数据文件目录,可通过[配置文件]修改位置.</td>
</tr>
<tr>
<td>/var/log/taos</td>
<td style="text-align:left;">TDengine默认日志文件目录,可通过[配置文件]修改位置</td>
</tr>
<tr>
<td>/usr/local/taos/bin</td>
<td style="text-align:left;">TDengine可执行文件目录</td>
</tr>
</tbody>
</table></figure>
<a class='anchor' id='可执行文件'></a><h3>可执行文件</h3>
<p>TDengine的所有可执行文件默认存放在 <em>/usr/local/taos/bin</em> 目录下。其中包括:</p>
<ul>
<li><em>taosd</em>:TDengine服务端可执行文件</li>
<li><em>taos</em>: TDengine Shell可执行文件</li>
<li><em>taosdump</em>:数据导出工具</li>
<li><em>rmtaos</em>: 一个卸载TDengine的脚本, 请谨慎执行</li>
</ul>
<p>您可以通过修改系统配置文件taos.cfg来配置不同的数据目录和日志目录</p>
<a class='anchor' id='服务端配置'></a><h2>服务端配置</h2>
<p>TDengine系统后台服务由taosd提供,可以在配置文件taos.cfg里修改配置参数,以满足不同场景的需求。配置文件的缺省位置在/etc/taos目录,可以通过taosd命令行执行参数-c指定配置文件目录。比如taosd -c /home/user来指定配置文件位于/home/user这个目录。</p>
<p>下面仅仅列出一些重要的配置参数,更多的参数请看配置文件里的说明。各个参数的详细介绍及作用请看前述章节。<strong>注意:配置修改后,需要重启<em>taosd</em>服务才能生效。</strong></p>
<ul>
<li>internalIp: 对外提供服务的IP地址,默认取第一个IP地址</li>
<li>mgmtShellPort:管理节点与客户端通信使用的TCP/UDP端口号(默认值是6030)。此端口号在内向后连续的5个端口都会被UDP通信占用,即UDP占用[6030-6034],同时TCP通信也会使用端口[6030]。</li>
<li>vnodeShellPort:数据节点与客户端通信使用的TCP/UDP端口号(默认值是6035)。此端口号在内向后连续的5个端口都会被UDP通信占用,即UDP占用[6035-6039],同时TCP通信也会使用端口[6035]</li>
<li>httpPort:数据节点对外提供RESTful服务使用TCP,端口号[6020]</li>
<li>dataDir: 数据文件目录,缺省是/var/lib/taos</li>
<li>maxUsers:用户的最大数量</li>
<li>maxDbs:数据库的最大数量</li>
<li>maxTables:数据表的最大数量</li>
<li>enableMonitor: 系统监测标志位,0:关闭,1:打开</li>
<li>logDir: 日志文件目录,缺省是/var/log/taos</li>
<li>numOfLogLines:日志文件的最大行数</li>
<li>debugFlag: 系统debug日志开关,131:仅错误和报警信息,135:调试信息,143:非常详细的调试信息</li>
</ul>
<p>不同应用场景的数据往往具有不同的数据特征,比如保留天数、副本数、采集频次、记录大小、采集点的数量、压缩等都可完全不同。为获得在存储上的最高效率,TDengine提供如下存储相关的系统配置参数:</p>
<ul>
<li>days:一个数据文件覆盖的时间长度,单位为天</li>
<li>keep:数据库中数据保留的天数</li>
<li>rows: 文件块中记录条数</li>
<li>comp: 文件压缩标志位,0:关闭,1:一阶段压缩,2:两阶段压缩</li>
<li>ctime:数据从写入内存到写入硬盘的最长时间间隔,单位为秒</li>
<li>clog:数据提交日志(WAL)的标志位,0为关闭,1为打开</li>
<li>tables:每个vnode允许创建表的最大数目</li>
<li>cache: 内存块的大小(字节数)</li>
<li>tblocks: 每张表最大的内存块数</li>
<li>ablocks: 每张表平均的内存块数</li>
<li>precision:时间戳为微秒的标志位,ms表示毫秒,us表示微秒</li>
</ul>
<p>对于一个应用场景,可能有多种数据特征的数据并存,最佳的设计是将具有相同数据特征的表放在一个库里,这样一个应用有多个库,而每个库可以配置不同的存储参数,从而保证系统有最优的性能。TDengine容许应用在创建库时指定上述存储参数,如果指定,该参数就将覆盖对应的系统配置参数。举例,有下述SQL: </p>
<pre><code> create database demo days 10 cache 16000 ablocks 4</code></pre>
<p>该SQL创建了一个库demo, 每个数据文件保留10天数据,内存块为16000字节,每个表平均占用4个内存块,而其他参数与系统配置完全一致。</p>
<a class='anchor' id='客户端配置'></a><h2>客户端配置</h2>
<p>TDengine系统的前台交互客户端应用程序为taos,它与taosd共享同一个配置文件taos.cfg。运行taos时,使用参数-c指定配置文件目录,如taos -c /home/cfg,表示使用/home/cfg/目录下的taos.cfg配置文件中的参数,缺省目录是/etc/taos。更多taos的使用方法请见<a href="#_TDengine_Shell命令行程序">Shell命令行程序</a>。本节主要讲解taos客户端应用在配置文件taos.cfg文件中使用到的参数。</p>
<p>客户端配置参数列表及解释</p>
<ul>
<li>masterIP:客户端默认发起请求的服务器的IP地址</li>
<li>charset:指明客户端所使用的字符集,默认值为UTF-8。TDengine存储nchar类型数据时使用的是unicode存储,因此客户端需要告知服务自己所使用的字符集,也即客户端所在系统的字符集。</li>
<li>locale:设置系统语言环境。Linux上客户端与服务端共享</li>
<li>defaultUser:默认登录用户,默认值root</li>
<li>defaultPass:默认登录密码,默认值taosdata</li>
</ul>
<p>TCP/UDP端口,以及日志的配置参数,与server的配置参数完全一样。</p>
<p>启动taos时,你也可以从命令行指定IP地址、端口号,用户名和密码,否则就从taos.cfg读取。</p>
<a class='anchor' id='用户管理'></a><h2>用户管理</h2>
<p>系统管理员可以在CLI界面里添加、删除用户,也可以修改密码。CLI里SQL语法如下:</p>
<pre><code>CREATE USER user_name PASS ‘password’</code></pre>
<p>创建用户,并制定用户名和密码,密码需要用单引号引起来</p>
<pre><code>DROP USER user_name</code></pre>
<p>删除用户,限root用户使用</p>
<pre><code>ALTER USER user_name PASS ‘password’ </code></pre>
<p>修改用户密码, 为避免被转换为小写,密码需要用单引号引用</p>
<pre><code>SHOW USERS</code></pre>
<p>显示所有用户</p>
<a class='anchor' id='数据导入'></a><h2>数据导入</h2>
<p>TDengine提供两种方便的数据导入功能,一种按脚本文件导入,一种按数据文件导入。</p>
<p><strong>按脚本文件导入</strong></p>
<p>TDengine的shell支持source filename命令,用于批量运行文件中的SQL语句。用户可将建库、建表、写数据等SQL命令写在同一个文件中,每条命令单独一行,在shell中运行source命令,即可按顺序批量运行文件中的SQL语句。以‘#’开头的SQL语句被认为是注释,shell将自动忽略。</p>
<p><strong>按数据文件导入</strong></p>
<p>TDengine也支持在shell对已存在的表从CSV文件中进行数据导入。每个CSV文件只属于一张表且CSV文件中的数据格式需与要导入表的结构相同。其语法如下</p>
<pre><code class="mysql language-mysql">insert into tb1 file a.csv b.csv tb2 c.csv …
import into tb1 file a.csv b.csv tb2 c.csv …</code></pre>
<a class='anchor' id='数据导出'></a><h2>数据导出</h2>
<p>为方便数据导出,TDengine提供了两种导出方式,分别是按表导出和用taosdump导出。</p>
<p><strong>按表导出CSV文件</strong></p>
<p>如果用户需要导出一个表或一个STable中的数据,可在shell中运行</p>
<pre><code>select * from &lt;tb_name&gt; &gt;&gt; a.csv</code></pre>
<p>这样,表tb中的数据就会按照CSV格式导出到文件a.csv中。</p>
<p><strong>用taosdump导出数据</strong></p>
<p>TDengine提供了方便的数据库导出工具taosdump。用户可以根据需要选择导出所有数据库、一个数据库或者数据库中的一张表,所有数据或一时间段的数据,甚至仅仅表的定义。其用法如下:</p>
<ul>
<li>导出数据库中的一张或多张表:taosdump [OPTION…] dbname tbname …</li>
<li>导出一个或多个数据库: taosdump [OPTION…] --databases dbname…</li>
<li>导出所有数据库(不含监控数据库):taosdump [OPTION…] --all-databases</li>
</ul>
<p>用户可通过运行taosdump --help获得更详细的用法说明</p>
<a class='anchor' id='系统连接、任务查询管理'></a><h2>系统连接、任务查询管理</h2>
<p>系统管理员可以从CLI查询系统的连接、正在进行的查询、流式计算,并且可以关闭连接、停止正在进行的查询和流式计算。CLI里SQL语法如下:</p>
<pre><code>SHOW CONNECTIONS</code></pre>
<p>显示数据库的连接,其中一列显示ip:port, 为连接的IP地址和端口号。</p>
<pre><code>KILL CONNECTION &lt;connection-id&gt;</code></pre>
<p>强制关闭数据库连接,其中的connection-id是SHOW CONNECTIONS中显示的 ip:port字串,如“192.168.0.1:42198”,拷贝粘贴即可。</p>
<pre><code>SHOW QUERIES</code></pre>
<p>显示数据查询,其中一列显示ip:port:id, 为发起该query应用的IP地址,端口号,以及系统分配的ID。</p>
<pre><code>KILL QUERY &lt;query-id&gt;</code></pre>
<p>强制关闭数据查询,其中query-id是SHOW QUERIES中显示的ip:port:id字串,如“192.168.0.1:42198:11”,拷贝粘贴即可。</p>
<pre><code>SHOW STREAMS</code></pre>
<p>显示流式计算,其中一列显示ip:port:id, 为启动该stream的IP地址、端口和系统分配的ID。</p>
<pre><code>KILL STREAM &lt;stream-id&gt;</code></pre>
<p>强制关闭流式计算,其中的中stream-id是SHOW STREAMS中显示的ip:port:id字串,如“192.168.0.1:42198:18”,拷贝粘贴即可。</p>
<a class='anchor' id='系统监控'></a><h2>系统监控</h2>
<p>TDengine启动后,会自动创建一个监测数据库SYS,并自动将服务器的CPU、内存、硬盘空间、带宽、请求数、磁盘读写速度、慢查询等信息定时写入该数据库。TDengine还将重要的系统操作(比如登录、创建、删除数据库等)日志以及各种错误报警信息记录下来存放在SYS库里。系统管理员可以从CLI直接查看这个数据库,也可以在WEB通过图形化界面查看这些监测信息。</p>
<p>这些监测信息的采集缺省是打开的,但可以修改配置文件里的选项enableMonitor将其关闭或打开。</p><a href='../index.html'>回去</a></section></main></div><?php include($s.'/footer.php'); ?><script>$('pre').addClass('prettyprint linenums');PR.prettyPrint()</script><script src='lib/docs/liner.js'></script></body></html>
\ No newline at end of file
<!DOCTYPE html><html lang='cn'><head><title>文档 | 涛思数据</title><meta name='description' content='TDengine是一个开源的专为物联网、车联网、工业互联网、IT运维等设计和优化的大数据平台。除核心的快10倍以上的时序数据库功能外,还提供缓存、数据订阅、流式计算等功能,最大程度减少研发和运维的工作量。'><meta name='keywords' content='大数据,Big Data,开源,物联网,车联网,工业互联网,IT运维, 时序数据库,缓存,数据订阅,消息队列,流式计算,开源,涛思数据,TAOS Data, TDengine'><meta name='title' content='文档 | 涛思数据'><meta property='og:site_name' content='涛思数据'/><meta property='og:title' content='文档 | 涛思数据'/><meta property='og:type' content='article'/><meta property='og:url' content='https://www.taosdata.com/cn/documentation/advanced-features-ch/index.php'/><meta property='og:description' content='TDengine是一个开源的专为物联网、车联网、工业互联网、IT运维等设计和优化的大数据平台。除核心的快10倍以上的时序数据库功能外,还提供缓存、数据订阅、流式计算等功能,最大程度减少研发和运维的工作量。' /><link rel='canonical' href='https://www.taosdata.com/cn/documentation/advanced-features-ch/index.php'/><script src='../lib/jquery-3.4.1.min.js' type='application/javascript'></script><link href='../lib/bootstrap.min.css' rel='stylesheet'><link href='../styles/base.min.css' rel='stylesheet'><link rel='stylesheet' href='../lib/docs/taosdataprettify.css'><link rel='stylesheet' href='../lib/docs/docs.css'><script src='../lib/docs/prettify.js'></script><script src='../lib/docs/prettyprint-sql.js'></script></head><body><script>$('#documentation-href').addClass('active')</script><div class='container-fluid'><main class='content-wrapper'><section class='documentation'><a href='../index.html'>回去</a><h1>高级功能</h1>
<a class='anchor' id='连续查询(Continuous-Query)'></a><h2>连续查询(Continuous Query)</h2>
<p>连续查询是TDengine定期自动执行的查询,采用滑动窗口的方式进行计算,是一种简化的时间驱动的流式计算。针对库中的表或超级表,TDengine可提供定期自动执行的连续查询,用户可让TDengine推送查询的结果,也可以将结果再写回到TDengine中。每次执行的查询是一个时间窗口,时间窗口随着时间流动向前滑动。在定义连续查询的时候需要指定时间窗口(time window, 参数interval )大小和每次前向增量时间(forward sliding times, 参数sliding)。</p>
<p>TDengine的连续查询采用时间驱动模式,可以直接使用TAOS SQL进行定义,不需要额外的操作。使用连续查询,可以方便快捷地按照时间窗口生成结果,从而对原始采集数据进行降采样(down sampling)。用户通过TAOS SQL定义连续查询以后,TDengine自动在最后的一个完整的时间周期末端拉起查询,并将计算获得的结果推送给用户或者写回TDengine。</p>
<p>TDengine提供的连续查询与普通流计算中的时间窗口计算具有以下区别:</p>
<ul>
<li><p>不同于流计算的实时反馈计算结果,连续查询只在时间窗口关闭以后才开始计算。例如时间周期是1天,那么当天的结果只会在23:59:59以后才会生成。</p></li>
<li><p>如果有历史记录写入到已经计算完成的时间区间,连续查询并不会重新进行计算,也不会重新将结果推送给用户。对于写回TDengine的模式,也不会更新已经存在的计算结果。</p></li>
<li><p>使用连续查询推送结果的模式,服务端并不缓存客户端计算状态,也不提供Exactly-Once的语意保证。如果用户的应用端崩溃,再次拉起的连续查询将只会从再次拉起的时间开始重新计算最近的一个完整的时间窗口。如果使用写回模式,TDengine可确保数据写回的有效性和连续性。</p></li>
</ul>
<h4>使用连续查询</h4>
<p>使用TAOS SQL定义连续查询的过程,需要调用API taos_stream在应用端启动连续查询。例如要对统计表FOO_TABLE 每1分钟统计一次记录数量,前向滑动的时间是30秒,SQL语句如下:</p>
<pre><code class="sql language-sql">SELECT COUNT(*)
FROM FOO_TABLE
INTERVAL(1M) SLIDING(30S)</code></pre>
<p>其中查询的时间窗口(time window)是1分钟,前向增量(forward sliding time)时间是30秒。也可以不使用sliding来指定前向滑动时间,此时系统将自动向前滑动一个查询时间窗口再开始下一次计算,即时间窗口长度等于前向滑动时间。</p>
<pre><code class="sql language-sql">SELECT COUNT(*)
FROM FOO_TABLE
INTERVAL(1M)</code></pre>
<p>如果需要将连续查询的计算结果写回到数据库中,可以使用如下的SQL语句</p>
<pre><code class="sql language-sql">CREATE TABLE QUERY_RES
AS
SELECT COUNT(*)
FROM FOO_TABLE
INTERVAL(1M) SLIDING(30S)</code></pre>
<p>此时系统将自动创建表QUERY_RES,然后将连续查询的结果写入到该表。需要注意的是,前向滑动时间不能大于时间窗口的范围。如果用户指定的前向滑动时间超过时间窗口范围,系统将自动将其设置为时间窗口的范围值。如上所示SQL语句,如果用户设置前向滑动时间超过1分钟,系统将强制将其设置为1分钟。 </p>
<p>此外,TDengine还支持用户指定连续查询的结束时间,默认如果不输入结束时间,连续查询将永久运行,如果用户指定了结束时间,连续查询在系统时间达到指定的时间以后停止运行。如SQL所示,连续查询将运行1个小时,1小时之后连续查询自动停止。</p>
<pre><code class="sql language-sql">CREATE TABLE QUERY_RES
AS
SELECT COUNT(*)
FROM FOO_TABLE
WHERE TS &gt; NOW AND TS &lt;= NOW + 1H
INTERVAL(1M) SLIDING(30S) </code></pre>
<p>此外,还需要注意的是查询时间窗口的最小值是10毫秒,没有时间窗口范围的上限。</p>
<h4>管理连续查询</h4>
<p>用户可在控制台中通过 <em>show streams</em> 命令来查看系统中全部运行的连续查询,并可以通过 <em>kill stream</em> 命令杀掉对应的连续查询。在写回模式中,如果用户可以直接将写回的表删除,此时连续查询也会自动停止并关闭。后续版本会提供更细粒度和便捷的连续查询管理命令。</p>
<a class='anchor' id='数据订阅(Publisher/Subscriber)'></a><h2>数据订阅(Publisher/Subscriber)</h2>
<p>基于数据天然的时间序列特性,TDengine的数据写入(insert)与消息系统的数据发布(pub)逻辑上一致,均可视为系统中插入一条带时间戳的新记录。同时,TDengine在内部严格按照数据时间序列单调递增的方式保存数据。本质上来说,TDengine中里每一张表均可视为一个标准的消息队列。</p>
<p>TDengine内嵌支持轻量级的消息订阅与推送服务。使用系统提供的API,用户可订阅数据库中的某一张表(或超级表)。订阅的逻辑和操作状态的维护均是由客户端完成,客户端定时轮询服务器是否有新的记录到达,有新的记录到达就会将结果反馈到客户。</p>
<p>TDengine的订阅与推送服务的状态是客户端维持,TDengine服务器并不维持。因此如果应用重启,从哪个时间点开始获取最新数据,由应用决定。</p>
<h4>API说明</h4>
<p>使用订阅的功能,主要API如下:</p>
<ul>
<li><p><code>TAOS_SUB *taos_subscribe(char *host, char *user, char *pass, char *db, char *table, int64_t time, int mseconds)</code></p><p>该函数负责启动订阅服务。其中参数说明:</p></li><ul>
<li><p>host:主机IP地址</p></li>
<li><p>user:数据库登录用户名</p></li>
<li><p>pass:密码</p></li>
<li><p>db:数据库名称</p></li>
<li><p>table:(超级) 表的名称</p></li>
<li><p>time:启动时间,Unix Epoch时间,单位为毫秒。从1970年1月1日起计算的毫秒数。如果设为0,表示从当前时间开始订阅</p></li>
<li><p>mseconds:查询数据库更新的时间间隔,单位为毫秒。一般设置为1000毫秒。返回值为指向TDengine_SUB 结构的指针,如果返回为空,表示失败。</p></li>
</ul><li><p><code>TAOS_ROW taos_consume(TAOS_SUB *tsub)</code>
</p><p>该函数用来获取订阅的结果,用户应用程序将其置于一个无限循环语句。如果数据库有新记录到达,该API将返回该最新的记录。如果没有新的记录,该API将阻塞。如果返回值为空,说明系统出错。参数说明:</p></li><ul><li><p>tsub:taos_subscribe的结构体指针。</p></li></ul><li><p><code>void taos_unsubscribe(TAOS_SUB *tsub)</code></p><p>取消订阅。应用程序退出时,务必调用该函数以避免资源泄露。</p></li>
<li><p><code>int taos_num_fields(TAOS_SUB *tsub)</code></p><p>获取返回的一行记录中数据包含多少列。</p></li>
<li><p><code>TAOS_FIELD *taos_fetch_fields(TAOS_SUB *tsub)</code></p><p>获取每列数据的属性(数据类型、名字、长度),与taos_num_subfileds配合使用,可解析返回的每行数据。</p></li></ul>
<p>示例代码:请看安装包中的的示范程序</p>
<a class='anchor' id='缓存-(Cache)'></a><h2>缓存 (Cache)</h2>
<p>TDengine采用时间驱动缓存管理策略(First-In-First-Out,FIFO),又称为写驱动的缓存管理机制。这种策略有别于读驱动的数据缓存模式(Least-Recent-Use,LRU),直接将最近写入的数据保存在系统的缓存中。当缓存达到临界值的时候,将最早的数据批量写入磁盘。一般意义上来说,对于物联网数据的使用,用户最为关心最近产生的数据,即当前状态。TDengine充分利用了这一特性,将最近到达的(当前状态)数据保存在缓存中。</p>
<p>TDengine通过查询函数向用户提供毫秒级的数据获取能力。直接将最近到达的数据保存在缓存中,可以更加快速地响应用户针对最近一条或一批数据的查询分析,整体上提供更快的数据库查询响应能力。从这个意义上来说,可通过设置合适的配置参数将TDengine作为数据缓存来使用,而不需要再部署额外的缓存系统,可有效地简化系统架构,降低运维的成本。需要注意的是,TDengine重启以后系统的缓存将被清空,之前缓存的数据均会被批量写入磁盘,缓存的数据将不会像专门的Key-value缓存系统再将之前缓存的数据重新加载到缓存中。</p>
<p>TDengine分配固定大小的内存空间作为缓存空间,缓存空间可根据应用的需求和硬件资源配置。通过适当的设置缓存空间,TDengine可以提供极高性能的写入和查询的支持。TDengine中每个虚拟节点(virtual node)创建时分配独立的缓存池。每个虚拟节点管理自己的缓存池,不同虚拟节点间不共享缓存池。每个虚拟节点内部所属的全部表共享该虚拟节点的缓存池。</p>
<p>一个缓存池了有很多个缓存块,缓存的大小由缓存块的个数以及缓存块的大小决定。参数cacheBlockSize决定每个缓存块的大小,参数cacheNumOfBlocks决定每个虚拟节点可用缓存块数量。因此单个虚拟节点总缓存开销为cacheBlockSize x cacheNumOfBlocks。参数numOfBlocksPerMeter决定每张表可用缓存块的数量,TDengine要求每张表至少有2个缓存块可供使用,因此cacheNumOfBlocks的数值不应该小于虚拟节点中所包含的表数量的两倍,即cacheNumOfBlocks ≤ sessionsPerVnode x 2。一般情况下cacheBlockSize可以不用调整,使用系统默认值即可,缓存块需要存储至少几十条记录才能确保TDengine更有效率地进行数据写入。</p>
<p>你可以通过函数last快速获取一张表或一张超级表的最后一条记录,这样很便于在大屏显示各设备的实时状态或采集值。例如:</p>
<pre><code class="mysql language-mysql">select degree from thermometer where location='beijing';</code></pre>
<p>该SQL语句将获取所有位于北京的传感器最后记录的温度值。</p><a href='../index.html'>回去</a></section></main></div><?php include($s.'/footer.php'); ?><script>$('pre').addClass('prettyprint linenums');PR.prettyPrint()</script><script src='lib/docs/liner.js'></script></body></html>
\ No newline at end of file
<!DOCTYPE html><html lang='cn'><head><title>文档 | 涛思数据</title><meta name='description' content='TDengine是一个开源的专为物联网、车联网、工业互联网、IT运维等设计和优化的大数据平台。除核心的快10倍以上的时序数据库功能外,还提供缓存、数据订阅、流式计算等功能,最大程度减少研发和运维的工作量。'><meta name='keywords' content='大数据,Big Data,开源,物联网,车联网,工业互联网,IT运维, 时序数据库,缓存,数据订阅,消息队列,流式计算,开源,涛思数据,TAOS Data, TDengine'><meta name='title' content='文档 | 涛思数据'><meta property='og:site_name' content='涛思数据'/><meta property='og:title' content='文档 | 涛思数据'/><meta property='og:type' content='article'/><meta property='og:url' content='https://www.taosdata.com/cn/documentation/connections-with-other-tools-ch/index.php'/><meta property='og:description' content='TDengine是一个开源的专为物联网、车联网、工业互联网、IT运维等设计和优化的大数据平台。除核心的快10倍以上的时序数据库功能外,还提供缓存、数据订阅、流式计算等功能,最大程度减少研发和运维的工作量。' /><link rel='canonical' href='https://www.taosdata.com/cn/documentation/connections-with-other-tools-ch/index.php'/><script src='../lib/jquery-3.4.1.min.js' type='application/javascript'></script><link href='../lib/bootstrap.min.css' rel='stylesheet'><link href='../styles/base.min.css' rel='stylesheet'><link rel='stylesheet' href='../lib/docs/taosdataprettify.css'><link rel='stylesheet' href='../lib/docs/docs.css'><script src='../lib/docs/prettify.js'></script><script src='../lib/docs/prettyprint-sql.js'></script></head><body><script>$('#documentation-href').addClass('active')</script><div class='container-fluid'><main class='content-wrapper'><section class='documentation'><a href='../index.html'>回去</a><h1>与其他工具的连接</h1>
<a class='anchor' id='Telegraf'></a><h2>Telegraf</h2>
<p>TDengine能够与开源数据采集系统<a href="https://www.influxdata.com/time-series-platform/telegraf/">Telegraf</a>快速集成,整个过程无需任何代码开发。</p>
<a class='anchor' id='安装Telegraf'></a><h3>安装Telegraf</h3>
<p>目前TDengine支持Telegraf 1.7.4以上的版本。用户可以根据当前的操作系统,到Telegraf官网下载安装包,并执行安装。下载地址如下:https://portal.influxdata.com/downloads</p>
<a class='anchor' id='配置Telegraf'></a><h3>配置Telegraf</h3>
<p>修改Telegraf配置文件/etc/telegraf/telegraf.conf中与TDengine有关的配置项。 </p>
<p>在output plugins部分,增加[[outputs.http]]配置项: </p>
<ul>
<li>url:http://ip:6020/telegraf/udb,其中ip为TDengine集群的中任意一台服务器的IP地址,6020为TDengine RESTful接口的端口号,telegraf为固定关键字,udb为用于存储采集数据的数据库名称,可预先创建。</li>
<li>method: "POST" </li>
<li>username: 登录TDengine的用户名</li>
<li>password: 登录TDengine的密码</li>
<li>data_format: "json"</li>
<li>json_timestamp_units: "1ms"</li>
</ul>
<p>在agent部分:</p>
<ul>
<li>hostname: 区分不同采集设备的机器名称,需确保其唯一性</li>
<li>metric_batch_size: 30,允许Telegraf每批次写入记录最大数量,增大其数量可以降低Telegraf的请求发送频率,但对于TDengine,该数值不能超过50</li>
</ul>
<p>关于如何使用Telegraf采集数据以及更多有关使用Telegraf的信息,请参考Telegraf官方的<a href="https://docs.influxdata.com/telegraf/v1.11/">文档</a></p>
<a class='anchor' id='Grafana'></a><h2>Grafana</h2>
<p>TDengine能够与开源数据可视化系统<a href="https://www.grafana.com/">Grafana</a>快速集成搭建数据监测报警系统,整个过程无需任何代码开发,TDengine中数据表中内容可以在仪表盘(DashBoard)上进行可视化展现。</p>
<a class='anchor' id='安装Grafana'></a><h3>安装Grafana</h3>
<p>目前TDengine支持Grafana 5.2.4以上的版本。用户可以根据当前的操作系统,到Grafana官网下载安装包,并执行安装。下载地址如下:https://grafana.com/grafana/download</p>
<a class='anchor' id='配置Grafana'></a><h3>配置Grafana</h3>
<p>TDengine的Grafana插件在安装包的/usr/local/taos/connector/grafana目录下。</p>
<p>以CentOS 7.2操作系统为例,将tdengine目录拷贝到/var/lib/grafana/plugins目录下,重新启动grafana即可。</p>
<a class='anchor' id='使用Grafana'></a><h3>使用Grafana</h3>
<p>用户可以直接通过localhost:3000的网址,登录Grafana服务器(用户名/密码:admin/admin),配置TDengine数据源,如下图所示,此时可以在下拉列表中看到TDengine数据源。 </p>
<p><img src="../assets/clip_image001.png" alt="img" /></p>
<p>TDengine数据源中的HTTP配置里面的Host地址要设置为TDengine集群的中任意一台服务器的IP地址与TDengine RESTful接口的端口号(6020)。假设TDengine数据库与Grafana部署在同一机器,那么应输入:http://localhost:6020。</p>
<p>此外,还需配置登录TDengine的用户名与密码,然后点击下图中的Save&amp;Test按钮保存。 </p>
<p><img src="../assets/clip_image001-2474914.png" alt="img" /></p>
<p>然后,就可以在Grafana的数据源列表中看到刚创建好的TDengine的数据源:</p>
<p><img src="../assets/clip_image001-2474939.png" alt="img" /></p>
<p>基于上面的步骤,就可以在创建Dashboard的时候使用TDengine数据源,如下图所示: </p>
<p><img src="../assets/clip_image001-2474961.png" alt="img" /></p>
<p>然后,可以点击Add Query按钮增加一个新查询。</p>
<p>在INPUT SQL输入框中输入查询SQL语句,该SQL语句的结果集应为两行多列的曲线数据,例如SELECT count(*) FROM sys.cpu WHERE ts&gt;=from and ts&lt;​to interval(interval)。其中,from、to和interval为TDengine插件的内置变量,表示从Grafana插件面板获取的查询范围和时间间隔。</p>
<p>ALIAS BY输入框为查询的别名,点击GENERATE SQL 按钮可以获取发送给TDengine的SQL语句。如下图所示: </p>
<p><img src="../assets/clip_image001-2474987.png" alt="img" /></p>
<p>关于如何使用Grafana创建相应的监测界面以及更多有关使用Grafana的信息,请参考Grafana官方的<a href="https://grafana.com/docs/">文档</a></p>
<a class='anchor' id='Matlab'></a><h2>Matlab</h2>
<p>MatLab可以通过安装包内提供的JDBC Driver直接连接到TDengine获取数据到本地工作空间。</p>
<a class='anchor' id='MatLab的JDBC接口适配'></a><h3>MatLab的JDBC接口适配</h3>
<p>MatLab的适配有下面几个步骤,下面以Windows10上适配MatLab2017a为例:</p>
<ul>
<li>将TDengine安装包内的驱动程序JDBCDriver-1.0.0-dist.jar拷贝到${matlab_root}\MATLAB\R2017a\java\jar\toolbox</li>
<li>将TDengine安装包内的taos.lib文件拷贝至${matlab_ root _dir}\MATLAB\R2017a\lib\win64</li>
<li>将新添加的驱动jar包加入MatLab的classpath。在${matlab_ root _dir}\MATLAB\R2017a\toolbox\local\classpath.txt文件中添加下面一行</li>
</ul>
<p><code>$matlabroot/java/jar/toolbox/JDBCDriver-1.0.0-dist.jar</code></p>
<ul>
<li>在${user_home}\AppData\Roaming\MathWorks\MATLAB\R2017a\下添加一个文件javalibrarypath.txt, 并在该文件中添加taos.dll的路径,比如您的taos.dll是在安装时拷贝到了C:\Windows\System32下,那么就应该在javalibrarypath.txt中添加如下一行:</li>
</ul>
<p><code>C:\Windows\System32</code></p>
<a class='anchor' id='在MatLab中连接TDengine获取数据'></a><h3>在MatLab中连接TDengine获取数据</h3>
<p>在成功进行了上述配置后,打开MatLab。</p>
<ul>
<li><p>创建一个连接:</p>
<p><code>conn = database(‘db’, ‘root’, ‘taosdata’, ‘com.taosdata.jdbc.TSDBDriver’, ‘jdbc:TSDB://127.0.0.1:0/’)</code></p></li>
<li><p>执行一次查询:</p>
<p><code>sql0 = [‘select * from tb’]</code></p>
<p><code>data = select(conn, sql0);</code></p></li>
<li><p>插入一条记录:</p>
<p><code>sql1 = [‘insert into tb values (now, 1)’]</code></p>
<p><code>exec(conn, sql1)</code></p></li>
</ul>
<p>更多例子细节请参考安装包内examples\Matlab\TDengineDemo.m文件。</p>
<a class='anchor' id='R'></a><h2>R</h2>
<p>R语言支持通过JDBC接口来连接TDengine数据库。首先需要安装R语言的JDBC包。启动R语言环境,然后执行以下命令安装R语言的JDBC支持库:</p>
<pre><code class="R language-R">install.packages('rJDBC', repos='http://cran.us.r-project.org')</code></pre>
<p>安装完成以后,通过执行<code>library('RJDBC')</code>命令加载 <em>RJDBC</em> 包:</p>
<p>然后加载TDengine的JDBC驱动:</p>
<pre><code class="R language-R">drv&lt;-JDBC("com.taosdata.jdbc.TSDBDriver","JDBCDriver-1.0.0-dist.jar", identifier.quote="\"")</code></pre>
<p>如果执行成功,不会出现任何错误信息。之后通过以下命令尝试连接数据库:</p>
<pre><code class="R language-R">conn&lt;-dbConnect(drv,"jdbc:TSDB://192.168.0.1:0/?user=root&amp;password=taosdata","root","taosdata")</code></pre>
<p>注意将上述命令中的IP地址替换成正确的IP地址。如果没有任务错误的信息,则连接数据库成功,否则需要根据错误提示调整连接的命令。TDengine支持以下的 <em>RJDBC</em> 包中函数:</p>
<ul>
<li>dbWriteTable(conn, "test", iris, overwrite=FALSE, append=TRUE):将数据框iris写入表test中,overwrite必须设置为false,append必须设为TRUE,且数据框iris要与表test的结构一致。</li>
<li>dbGetQuery(conn, "select count(*) from test"):查询语句</li>
<li>dbSendUpdate(conn, "use db"):执行任何非查询sql语句。例如dbSendUpdate(conn, "use db"), 写入数据dbSendUpdate(conn, "insert into t1 values(now, 99)")等。</li>
<li>dbReadTable(conn, "test"):读取表test中数据</li>
<li>dbDisconnect(conn):关闭连接</li>
<li>dbRemoveTable(conn, "test"):删除表test</li>
</ul>
<p>TDengine客户端暂不支持如下函数:</p>
<ul>
<li>dbExistsTable(conn, "test"):是否存在表test</li>
<li>dbListTables(conn):显示连接中的所有表</li>
</ul><a href='../index.html'>回去</a></section></main></div><?php include($s.'/footer.php'); ?><script>$('pre').addClass('prettyprint linenums');PR.prettyPrint()</script><script src='lib/docs/liner.js'></script></body></html>
\ No newline at end of file
<!DOCTYPE html><html lang='cn'><head><title>文档 | 涛思数据</title><meta name='description' content='TDengine是一个开源的专为物联网、车联网、工业互联网、IT运维等设计和优化的大数据平台。除核心的快10倍以上的时序数据库功能外,还提供缓存、数据订阅、流式计算等功能,最大程度减少研发和运维的工作量。'><meta name='keywords' content='大数据,Big Data,开源,物联网,车联网,工业互联网,IT运维, 时序数据库,缓存,数据订阅,消息队列,流式计算,开源,涛思数据,TAOS Data, TDengine'><meta name='title' content='文档 | 涛思数据'><meta property='og:site_name' content='涛思数据'/><meta property='og:title' content='文档 | 涛思数据'/><meta property='og:type' content='article'/><meta property='og:url' content='https://www.taosdata.com/cn/documentation/data-model-and-architecture-ch/index.php'/><meta property='og:description' content='TDengine是一个开源的专为物联网、车联网、工业互联网、IT运维等设计和优化的大数据平台。除核心的快10倍以上的时序数据库功能外,还提供缓存、数据订阅、流式计算等功能,最大程度减少研发和运维的工作量。' /><link rel='canonical' href='https://www.taosdata.com/cn/documentation/data-model-and-architecture-ch/index.php'/><script src='../lib/jquery-3.4.1.min.js' type='application/javascript'></script><link href='../lib/bootstrap.min.css' rel='stylesheet'><link href='../styles/base.min.css' rel='stylesheet'><link rel='stylesheet' href='../lib/docs/taosdataprettify.css'><link rel='stylesheet' href='../lib/docs/docs.css'><script src='../lib/docs/prettify.js'></script><script src='../lib/docs/prettyprint-sql.js'></script></head><body><script>$('#documentation-href').addClass('active')</script><div class='container-fluid'><main class='content-wrapper'><section class='documentation'><a href='../index.html'>回去</a><h1>数据模型和设计</h1>
<a class='anchor' id='数据模型'></a><h2>数据模型</h2>
<a class='anchor' id='物联网典型场景'></a><h3>物联网典型场景</h3>
<p>在典型的物联网、车联网、运维监测场景中,往往有多种不同类型的数据采集设备,采集一个到多个不同的物理量。而同一种采集设备类型,往往又有多个具体的采集设备分布在不同的地点。大数据处理系统就是要将各种采集的数据汇总,然后进行计算和分析。对于同一类设备,其采集的数据类似如下的表格:</p>
<figure><table>
<thead>
<tr>
<th style="text-align:center;">Device ID</th>
<th style="text-align:center;">Time Stamp</th>
<th style="text-align:center;">Value 1</th>
<th style="text-align:center;">Value 2</th>
<th style="text-align:center;">Value 3</th>
<th style="text-align:center;">Tag 1</th>
<th style="text-align:center;">Tag 2</th>
</tr>
</thead>
<tbody>
<tr>
<td style="text-align:center;">D1001</td>
<td style="text-align:center;">1538548685000</td>
<td style="text-align:center;">10.3</td>
<td style="text-align:center;">219</td>
<td style="text-align:center;">0.31</td>
<td style="text-align:center;">Red</td>
<td style="text-align:center;">Tesla</td>
</tr>
<tr>
<td style="text-align:center;">D1002</td>
<td style="text-align:center;">1538548684000</td>
<td style="text-align:center;">10.2</td>
<td style="text-align:center;">220</td>
<td style="text-align:center;">0.23</td>
<td style="text-align:center;">Blue</td>
<td style="text-align:center;">BMW</td>
</tr>
<tr>
<td style="text-align:center;">D1003</td>
<td style="text-align:center;">1538548686500</td>
<td style="text-align:center;">11.5</td>
<td style="text-align:center;">221</td>
<td style="text-align:center;">0.35</td>
<td style="text-align:center;">Black</td>
<td style="text-align:center;">Honda</td>
</tr>
<tr>
<td style="text-align:center;">D1004</td>
<td style="text-align:center;">1538548685500</td>
<td style="text-align:center;">13.4</td>
<td style="text-align:center;">223</td>
<td style="text-align:center;">0.29</td>
<td style="text-align:center;">Red</td>
<td style="text-align:center;">Volvo</td>
</tr>
<tr>
<td style="text-align:center;">D1001</td>
<td style="text-align:center;">1538548695000</td>
<td style="text-align:center;">12.6</td>
<td style="text-align:center;">218</td>
<td style="text-align:center;">0.33</td>
<td style="text-align:center;">Red</td>
<td style="text-align:center;">Tesla</td>
</tr>
<tr>
<td style="text-align:center;">D1004</td>
<td style="text-align:center;">1538548696600</td>
<td style="text-align:center;">11.8</td>
<td style="text-align:center;">221</td>
<td style="text-align:center;">0.28</td>
<td style="text-align:center;">Black</td>
<td style="text-align:center;">Honda</td>
</tr>
</tbody>
</table></figure>
<p>每一条记录都有设备ID,时间戳,采集的物理量,还有与每个设备相关的静态标签。每个设备是受外界的触发,或按照设定的周期采集数据。采集的数据点是时序的,是一个数据流。</p>
<a class='anchor' id='数据特征'></a><h3>数据特征</h3>
<p>除时序特征外,仔细研究发现,物联网、车联网、运维监测类数据还具有很多其他明显的特征。</p>
<ol>
<li>数据是结构化的;</li>
<li>数据极少有更新或删除操作;</li>
<li>无需传统数据库的事务处理;</li>
<li>相对互联网应用,写多读少;</li>
<li>流量平稳,根据设备数量和采集频次,可以预测出来;</li>
<li>用户关注的是一段时间的趋势,而不是某一特点时间点的值;</li>
<li>数据是有保留期限的;</li>
<li>数据的查询分析一定是基于时间段和地理区域的;</li>
<li>除存储查询外,还往往需要各种统计和实时计算操作;</li>
<li>数据量巨大,一天采集的数据就可以超过100亿条。</li>
</ol>
<p>充分利用上述特征,TDengine采取了一特殊的优化的存储和计算设计来处理时序数据,能将系统处理能力显著提高。</p>
<a class='anchor' id='关系型数据库模型'></a><h3>关系型数据库模型</h3>
<p>因为采集的数据一般是结构化数据,而且为降低学习门槛,TDengine采用传统的关系型数据库模型管理数据。因此用户需要先创建库,然后创建表,之后才能插入或查询数据。</p>
<a class='anchor' id='一个设备一张表'></a><h3>一个设备一张表</h3>
<p>为充分利用其数据的时序性和其他数据特点,TDengine要求<strong>对每个数据采集点单独建表</strong>(比如有一千万个智能电表,就需创建一千万张表,上述表格中的D1001, D1002, D1003, D1004都需单独建表),用来存储这个采集点所采集的时序数据。这种设计能保证一个采集点的数据在存储介质上是一块一块连续的,大幅减少随机读取操作,成数量级的提升读取和查询速度。而且由于不同数据采集设备产生数据的过程完全独立,每个设备只产生属于自己的数据,一张表也就只有一个写入者。这样每个表就可以采用无锁方式来写,写入速度就能大幅提升。同时,对于一个数据采集点而言,其产生的数据是时序的,因此写的操作可用追加的方式实现,进一步大幅提高数据写入速度。</p>
<a class='anchor' id='数据建模最佳实践'></a><h3>数据建模最佳实践</h3>
<p><strong>表(Table)</strong>:TDengine 建议用数据采集点的名字(如上表中的D1001)来做表名。每个数据采集点可能同时采集多个物理量(如上表中的value1, value2, value3),每个物理量对应一张表中的一列,数据类型可以是整型、浮点型、字符串等。除此之外,表的第一列必须是时间戳,即数据类型为 timestamp。有的设备有多组采集量,每一组的采集频次是不一样的,这是需要对同一个设备建多张表。对采集的数据,TDengine将自动按照时间戳建立索引,但对采集的物理量不建任何索引。数据是用列式存储方式保存。 </p>
<p><strong>超级表(Super Table)</strong>:对于同一类型的采集点,为保证Schema的一致性,而且为便于聚合统计操作,可以先定义超级表STable(详见第10章),然后再定义表。每个采集点往往还有静态标签信息(如上表中的Tag 1, Tag 2),比如设备型号、颜色等,这些静态信息不会保存在存储采集数据的数据节点中,而是通过超级表保存在元数据节点中。这些静态标签信息将作为过滤条件,用于采集点之间的数据聚合统计操作。</p>
<p><strong>库(DataBase)</strong>:不同的数据采集点往往具有不同的数据特征,包括数据采集频率高低,数据保留时间长短,备份数目,单个字段大小等等。为让各种场景下TDengine都能最大效率的工作,TDengine建议将不同数据特征的表创建在不同的库里。创建一个库时,除SQL标准的选项外,应用还可以指定保留时长、数据备份的份数、cache大小、文件块大小、是否压缩等多种参数(详见第19章)。</p>
<p><strong>Schemaless vs Schema</strong>: 与NoSQL的各种引擎相比,由于应用需要定义schema,插入数据的灵活性降低。但对于物联网、金融这些典型的时序数据场景,schema会很少变更,因此这个灵活性不够的设计就不成问题。相反,TDengine采用结构化数据来进行处理的方式将让查询、分析的性能成数量级的提升。</p>
<p>TDengine对库的数量、超级表的数量以及表的数量没有做任何限制,而且其多少不会对性能产生影响,应用按照自己的场景创建即可。</p>
<a class='anchor' id='主要模块'></a><h2>主要模块</h2>
<p>如图所示,TDengine服务主要包含两大模块:<strong>管理节点模块(MGMT)</strong><strong>数据节点模块(DNODE)</strong>。整个TDengine还包含<strong>客户端模块</strong></p>
<p><center> <img src="../assets/structure.png"> </center>
<center> 图 1 TDengine架构示意图 </center></p>
<a class='anchor' id='管理节点模块'></a><h3>管理节点模块</h3>
<p>管理节点模块主要负责元数据的存储和查询等工作,其中包括用户信息的管理、数据库和表信息的创建、删除以及查询等。应用连接TDengine时会首先连接到管理节点。在创建/删除数据库和表时,请求也会首先发送请求到管理节点模块。由管理节点模块首先创建/删除元数据信息,然后发送请求到数据节点模块进行分配/删除所需要的资源。在数据写入和查询时,应用同样会首先访问管理节点模块,获取元数据信息。然后根据元数据管理信息访问数据节点模块。</p>
<a class='anchor' id='数据节点模块'></a><h3>数据节点模块</h3>
<p>写入数据的存储和查询工作是由数据节点模块负责。 为了更高效地利用资源,以及方便将来进行水平扩展,TDengine内部对数据节点进行了虚拟化,引入了虚拟节点(virtual node, 简称vnode)的概念,作为存储、资源分配以及数据备份的单元。如图2所示,在一个dnode上,通过虚拟化,可以将该dnode视为多个虚拟节点的集合。</p>
<p>创建一个库时,系统会自动分配vnode。每个vnode存储一定数量的表中的数据,但一个表只会存在于一个vnode里,不会跨vnode。一个vnode只会属于一个库,但一个库会有一到多个vnode。不同的vnode之间资源互不共享。每个虚拟节点都有自己的缓存,在硬盘上也有自己的存储目录。而同一vnode内部无论是缓存还是硬盘的存储都是共享的。通过虚拟化,TDengine可以将dnode上有限的物理资源合理地分配给不同的vnode,大大提高资源的利用率和并发度。一台物理机器上的虚拟节点个数可以根据其硬件资源进行配置。</p>
<p><center> <img src="../assets/vnode.png"> </center>
<center> 图 2 TDengine虚拟化 </center></p>
<a class='anchor' id='客户端模块'></a><h3>客户端模块</h3>
<p>TDengine客户端模块主要负责将应用传来的请求(SQL语句)进行解析,转化为内部结构体再发送到服务端。TDengine的各种接口都是基于TDengine的客户端模块进行开发的。客户端模块与管理模块使用TCP/UDP通讯,端口号由系统参数mgmtShellPort配置, 缺省值为6030。客户端与数据节点模块也是使用TCP/UDP通讯,端口号由系统参数vnodeShellPort配置, 缺省值为6035。两个端口号均可通过<a href="../administrator/#Configuration-on-Server">系统配置文件taos.cfg</a>进行个性化设置。</p>
<a class='anchor' id='写入流程'></a><h2>写入流程</h2>
<p>TDengine的完整写入流程如图3所示。为了保证写入数据的安全性和完整性,TDengine在写入数据时采用[预写日志算法]。客户端发来的数据在经过验证以后,首先会写入预写日志中,以保证TDengine能够在断电等因素导致的服务重启时从预写日志中恢复数据,避免数据的丢失。写入预写日志后,数据会被写到对应的vnode的缓存中。随后,服务端会发送确认信息给客户端表示写入成功。TDengine中存在两种机制可以促使缓存中的数据写入到硬盘上进行持久化存储:</p>
<p><center> <img src="../assets/write_process.png"> </center>
<center> 图 3 TDengine写入流程 </center></p>
<ol>
<li><strong>时间驱动的落盘</strong>:TDengine服务会定时将vnode缓存中的数据写入到硬盘上,默认为一个小时落一次盘。落盘间隔可在配置文件taos.cfg中通过参数commitTime配置。</li>
<li><strong>数据驱动的落盘</strong>:当vnode中缓存的数据达到一定规模时,为了不阻塞后续数据的写入,TDengine也会拉起落盘线程将缓存中的数据清空。数据驱动的落盘会刷新定时落盘的时间。</li>
</ol>
<p>TDengine在数据落盘时会打开新的预写日志文件,在落盘后则会删除老的预写日志文件,避免日志文件无限制的增长。TDengine对缓存按照先进先出的原则进行管理,以保证每个表的最新数据都在缓存中。</p>
<a class='anchor' id='数据存储'></a><h2>数据存储</h2>
<p>TDengine将所有数据存储在/var/lib/taos/目录下,您可以通过系统配置参数dataDir进行个性化配置。</p>
<p>TDengine中的元数据信息包括TDengine中的数据库、表、用户等信息。每个超级表、以及每个表的标签数据也存放在这里。为提高访问速度,元数据全部有缓存。</p>
<p>TDengine中写入的数据在硬盘上是按时间维度进行分片的。同一个vnode中的表在同一时间范围内的数据都存放在同一文件组中。这一数据分片方式可以大大简化数据在时间维度的查询,提高查询速度。在默认配置下,硬盘上的每个数据文件存放10天数据。用户可根据需要修改系统配置参数daysPerFile进行个性化配置。</p>
<p>表中的数据都有保存时间,一旦超过保存时间(缺省是3650天),数据将被系统自动删除。您可以通过系统配置参数daysToKeep进行个性化设置。</p>
<p>数据在文件中是按块存储的。每个数据块只包含一张表的数据,且数据是按照时间主键递增排列的。数据在数据块中按列存储,这样使得同列的数据存放在一起,对于不同的数据类型还采用不同的压缩方法,大大提高压缩的比例,节省存储空间。</p>
<p>数据文件总共有三类文件,一类是data文件,它存放了真实的数据块,该文件只进行追加操作;一类文件是head文件, 它存放了其对应的data文件中数据块的索引信息;第三类是last文件,专门存储最后写入的数据,每次落盘操作时,这部分数据会与内存里的数据合并,并决定是否写入data文件还是last文件。</p><a href='../index.html'>回去</a></section></main></div><?php include($s.'/footer.php'); ?><script>$('pre').addClass('prettyprint linenums');PR.prettyPrint()</script><script src='lib/docs/liner.js'></script></body></html>
\ No newline at end of file
<!DOCTYPE html><html lang='cn'><head><title>文档 | 涛思数据</title><meta name='description' content='TDengine是一个开源的专为物联网、车联网、工业互联网、IT运维等设计和优化的大数据平台。除核心的快10倍以上的时序数据库功能外,还提供缓存、数据订阅、流式计算等功能,最大程度减少研发和运维的工作量。'><meta name='keywords' content='大数据,Big Data,开源,物联网,车联网,工业互联网,IT运维, 时序数据库,缓存,数据订阅,消息队列,流式计算,开源,涛思数据,TAOS Data, TDengine'><meta name='title' content='文档 | 涛思数据'><meta property='og:site_name' content='涛思数据'/><meta property='og:title' content='文档 | 涛思数据'/><meta property='og:type' content='article'/><meta property='og:url' content='https://www.taosdata.com/cn/documentation/faq-ch/index.php'/><meta property='og:description' content='TDengine是一个开源的专为物联网、车联网、工业互联网、IT运维等设计和优化的大数据平台。除核心的快10倍以上的时序数据库功能外,还提供缓存、数据订阅、流式计算等功能,最大程度减少研发和运维的工作量。' /><link rel='canonical' href='https://www.taosdata.com/cn/documentation/faq-ch/index.php'/><script src='../lib/jquery-3.4.1.min.js' type='application/javascript'></script><link href='../lib/bootstrap.min.css' rel='stylesheet'><link href='../styles/base.min.css' rel='stylesheet'><link rel='stylesheet' href='../lib/docs/taosdataprettify.css'><link rel='stylesheet' href='../lib/docs/docs.css'><script src='../lib/docs/prettify.js'></script><script src='../lib/docs/prettyprint-sql.js'></script></head><body><script>$('#documentation-href').addClass('active')</script><div class='container-fluid'><main class='content-wrapper'><section class='documentation'><a href='../index.html'>回去</a><h1>常见问题</h1>
<h4>1. 遇到错误"failed to connect to server", 我怎么办?</h4>
<p>客户端遇到链接故障,请按照下面的步骤进行检查:</p>
<ol>
<li>在服务器,执行 <code>systemctl status taosd</code> 检查<em>taosd</em>运行状态。如果没有运行,启动<em>taosd</em></li>
<li>确认客户端连接时指定了正确的服务器IP地址</li>
<li>ping服务器IP,如果没有反应,请检查你的网络</li>
<li>检查防火墙设置,确认TCP/UDP 端口6030-6039 是打开的</li>
<li>对于Linux上的JDBC(ODBC, Python, Go等接口类似)连接, 确保<em>libtaos.so</em>在目录<em>/usr/local/lib/taos</em>里, 并且<em>/usr/local/lib/taos</em>在系统库函数搜索路径<em>LD_LIBRARY_PATH</em></li>
<li>对于windows上的JDBC, ODBC, Python, Go等连接,确保<em>driver/c/taos.dll</em>在你的系统搜索目录里 (建议<em>taos.dll</em>放在目录 <em>C:\Windows\System32</em>)</li>
<li>如果仍不能排除连接故障,请使用命令行工具nc来分别判断指定端口的TCP和UDP连接是否通畅
检查UDP端口连接是否工作:<code>nc -vuz {hostIP} {port}</code>
检查服务器侧TCP端口连接是否工作:<code>nc -l {port}</code>
检查客户端侧TCP端口链接是否工作:<code>nc {hostIP} {port}</code></li>
</ol>
<h4>2. 虽然语法正确,为什么我还是得到 "Invalid SQL" 错误</h4>
<p>如果你确认语法正确,请检查SQL语句长度是否超过64K。如果超过,也会返回这个错误。</p>
<h4>3. 为什么我删除超级表总是失败?</h4>
<p>请确保超级表下已经没有其他表,否则系统不允许删除该超级表。</p>
<h4>4. 是否支持validation queries?</h4>
<p>TDengine还没有一组专用的validation queries。然而建议你使用系统监测的数据库”log"来做。</p>
<h4>5. 我可以删除或更新一条记录吗?</h4>
<p>不能。因为TDengine是为联网设备采集的数据设计的,不容许修改。但TDengine提供数据保留策略,只要数据记录超过保留时长,就会被自动删除。</p>
<h4>6. 我怎么创建超过250列的表?</h4>
<p>TDengine最大允许创建250列的表。但是如果确实超过,我们建议按照数据特性,逻辑地将这个宽表分解成几个小表。</p>
<h4>7. 最有效的写入数据的方法是什么?</h4>
<p>批量插入。每条写入语句可以一张表同时插入多条记录,也可以同时插入多张表的记录。</p>
<h4>8. windows系统下插入的nchar类数据中的汉字被解析成了乱码如何解决?</h4>
<p>windows下插入nchar类的数据中如果有中文,请先确认系统的地区设置成了中国(在Control Panel里可以设置),这时cmd中的<code>taos</code>客户端应该已经可以正常工作了;如果是在IDE里开发Java应用,比如Eclipse, Intellij,请确认IDE里的文件编码为GBK(这是Java默认的编码类型),然后在生成Connection时,初始化客户端的配置,具体语句如下:</p>
<p>​ Class.forName("com.taosdata.jdbc.TSDBDriver");</p>
<p>​ Properties properties = new Properties();</p>
<p>​ properties.setProperty(TSDBDriver.LOCALE_KEY, "UTF-8");</p>
<p>​ Connection = DriverManager.getConnection(url, properties);</p><a href='../index.html'>回去</a></section></main></div><?php include($s.'/footer.php'); ?><script>$('pre').addClass('prettyprint linenums');PR.prettyPrint()</script><script src='lib/docs/liner.js'></script></body></html>
\ No newline at end of file
<!DOCTYPE html><html lang='cn'><head><title>文档 | 涛思数据</title><meta name='description' content='TDengine是一个开源的专为物联网、车联网、工业互联网、IT运维等设计和优化的大数据平台。除核心的快10倍以上的时序数据库功能外,还提供缓存、数据订阅、流式计算等功能,最大程度减少研发和运维的工作量。'><meta name='keywords' content='大数据,Big Data,开源,物联网,车联网,工业互联网,IT运维, 时序数据库,缓存,数据订阅,消息队列,流式计算,开源,涛思数据,TAOS Data, TDengine'><meta name='title' content='文档 | 涛思数据'><meta property='og:site_name' content='涛思数据'/><meta property='og:title' content='文档 | 涛思数据'/><meta property='og:type' content='article'/><meta property='og:url' content='https://www.taosdata.com/cn/documentation/getting-started-ch/index.php'/><meta property='og:description' content='TDengine是一个开源的专为物联网、车联网、工业互联网、IT运维等设计和优化的大数据平台。除核心的快10倍以上的时序数据库功能外,还提供缓存、数据订阅、流式计算等功能,最大程度减少研发和运维的工作量。' /><link rel='canonical' href='https://www.taosdata.com/cn/documentation/getting-started-ch/index.php'/><script src='../lib/jquery-3.4.1.min.js' type='application/javascript'></script><link href='../lib/bootstrap.min.css' rel='stylesheet'><link href='../styles/base.min.css' rel='stylesheet'><link rel='stylesheet' href='../lib/docs/taosdataprettify.css'><link rel='stylesheet' href='../lib/docs/docs.css'><script src='../lib/docs/prettify.js'></script><script src='../lib/docs/prettyprint-sql.js'></script></head><body><script>$('#documentation-href').addClass('active')</script><div class='container-fluid'><main class='content-wrapper'><section class='documentation'><a href='../index.html'>回去</a><h1>立即开始</h1>
<a class='anchor' id='快速上手'></a><h2>快速上手</h2>
<p>TDengine目前只支持在Linux系统上安装和运行。用户可根据需求选择通过<a href="#通过源码安装">源码</a>或者<a href="#通过安装包安装">安装包</a>来安装。</p>
<a class='anchor' id='通过源码安装'></a><h3>通过源码安装</h3>
<p>请参考我们的<a href="https://github.com/taosdata/TDengine">TDengine github主页</a>下载源码并安装.</p>
<a class='anchor' id='通过安装包安装'></a><h3>通过安装包安装</h3>
<p>我们提供三种安装包,请选择你所需要的。TDengine的安装非常简单,从下载到安装成功仅仅只要几秒钟。</p>
<ul id='packageList'>
<li><a id='tdengine-rpm' style='color:var(--b2)'>TDengine RPM package (1.5M)</a></li>
<li><a id='tdengine-deb' style='color:var(--b2)'>TDengine DEB package (1.7M)</a></li>
<li><a id='tdengine-tar' style='color:var(--b2)'>TDengine Tarball (3.0M)</a></li>
</ul>
<p>目前,TDengine只支持在使用<a href="https://en.wikipedia.org/wiki/Systemd"><code>systemd</code></a>做进程服务管理的linux系统上安装。其他linux系统的支持正在开发中。用<code>which</code>命令来检测系统中是否存在<code>systemd</code>:</p>
<pre><code class="cmd language-cmd">which systemd</code></pre>
<p>如果系统中不存在<code>systemd</code>命令,请考虑<a href="#通过源码安装">通过源码安装</a>TDengine。</p>
<a class='anchor' id='启动并体验TDengine'></a><h2>启动并体验TDengine</h2>
<p>安装成功后,用户可使用<code>systemctl</code>命令来启动TDengine的服务进程。</p>
<pre><code class="cmd language-cmd">systemctl start taosd</code></pre>
<p>检查服务是否正常工作。</p>
<pre><code class="cmd language-cmd">systemctl status taosd</code></pre>
<p>如果TDengine服务正常工作,那么您可以通过TDengine的命令行程序<code>taos</code>来访问并体验TDengine。</p>
<p><strong>注:<em>systemctl</em> 命令需要 <em>root</em> 权限来运行,如果您非 <em>root</em> 用户,请在命令前添加 <em>sudo</em></strong></p>
<a class='anchor' id='TDengine命令行程序'></a><h2>TDengine命令行程序</h2>
<p>执行TDengine命令行程序,您只要在Linux终端执行<code>taos</code>即可</p>
<pre><code class="cmd language-cmd">taos</code></pre>
<p>如果TDengine终端链接服务成功,将会打印出欢迎消息和版本信息。如果失败,则会打印错误消息出来(请参考<a href="https://www.taosdata.com/cn/faq/">FAQ</a>来解决终端链接服务端失败的问题)。TDengine终端的提示符号如下:</p>
<pre><code class="cmd language-cmd">taos&gt;</code></pre>
<p>在TDengine终端中,用户可以通过SQL命令来创建/删除数据库、表等,并进行插入查询操作。在终端中运行的SQL语句需要以分号结束来运行。示例:</p>
<pre><code class="mysql language-mysql">create database db;
use db;
create table t (ts timestamp, speed int);
insert into t values ('2019-07-15 00:00:00', 10);
insert into t values ('2019-07-15 01:00:00', 20);
select * from t;
ts | speed |
===================================
19-07-15 00:00:00.000| 10|
19-07-15 01:00:00.000| 20|
Query OK, 2 row(s) in set (0.001700s)</code></pre>
<p>除执行SQL语句外,系统管理员还可以从TDengine终端检查系统运行状态,添加删除用户账号等。</p>
<a class='anchor' id='命令行参数'></a><h3>命令行参数</h3>
<p>您可通过配置命令行参数来改变TDengine终端的行为。以下为常用的几个命令行参数:</p>
<ul>
<li>-c, --config-dir: 指定配置文件目录,默认为<em>/etc/taos</em></li>
<li>-h, --host: 指定服务的IP地址,默认为本地服务</li>
<li>-s, --commands: 在不进入终端的情况下运行TDengine命令</li>
<li>-u, -- user: 链接TDengine服务器的用户名,缺省为root</li>
<li>-p, --password: 链接TDengine服务器的密码,缺省为taosdata</li>
<li>-?, --help: 打印出所有命令行参数</li>
</ul>
<p>示例:</p>
<pre><code class="cmd language-cmd">taos -h 192.168.0.1 -s "use db; show tables;"</code></pre>
<a class='anchor' id='运行SQL命令脚本'></a><h3>运行SQL命令脚本</h3>
<p>TDengine终端可以通过<code>source</code>命令来运行SQL命令脚本.</p>
<pre><code>taos&gt; source &lt;filename&gt;;</code></pre>
<a class='anchor' id='Shell小技巧'></a><h3>Shell小技巧</h3>
<ul>
<li>可以使用上下光标键查看已经历史输入的命令</li>
<li>修改用户密码。在shell中使用alter user命令</li>
<li>ctrl+c 中止正在进行中的查询</li>
<li>执行<code>RESET QUERY CACHE</code>清空本地缓存的表的schema</li>
</ul>
<a class='anchor' id='主要功能'></a><h2>主要功能</h2>
<p>TDengine的核心功能是时序数据库。除此之外,为减少研发的复杂度、系统维护的难度,TDengine还提供缓存、消息队列、订阅、流式计算等功能。更详细的功能如下:</p>
<ul>
<li>使用类SQL语言插入或查询数据</li>
<li>支持C/C++, Java(JDBC), Python, Go, RESTful, and Node.JS 开发接口</li>
<li>可通过Python/R/Matlab or TDengine shell做Ad Hoc查询分析</li>
<li>通过定时连续查询支持基于滑动窗口的流式计算</li>
<li>使用超级表来更灵活高效的聚合多个时间线的数据</li>
<li>时间轴上聚合一个或多个时间线的数据</li>
<li>支持数据订阅,一旦有新数据,就立即通知应用</li>
<li>支持缓存,每个时间线或设备的最新数据都从内存里快速获取</li>
<li>历史数据与实时数据处理完全透明,不用区别对待</li>
<li>支持链接Telegraf, Grafana等第三方工具</li>
<li>成套的配置和工具,让你更好的管理TDengine </li>
</ul>
<p>对于企业版,TDengine还提供如下高级功能:</p>
<ul>
<li>线性水平扩展能力,以提供更高的处理速度和数据容量</li>
<li>高可靠,无单点故障,提供运营商级别的服务</li>
<li>多个副本自动同步,而且可以跨机房</li>
<li>多级存储,让历史数据处理的成本更低</li>
<li>用户友好的管理后台和工具,让管理更轻松简单 </li>
</ul>
<p>TDengine是专为物联网、车联网、工业互联网、运维监测等场景优化设计的时序数据处理引擎。与其他方案相比,它的插入查询速度都快10倍以上。单核一秒钟就能插入100万数据点,读出1000万数据点。由于采用列式存储和优化的压缩算法,存储空间不及普通数据库的1/10.</p>
<a class='anchor' id='深入了解TDengine'></a><h2>深入了解TDengine</h2>
<p>请继续阅读<a href="../documentation">文档</a>来深入了解TDengine。</p><a href='../index.html'>回去</a></section></main></div><?php include($s.'/footer.php'); ?><script>$('pre').addClass('prettyprint linenums');PR.prettyPrint()</script><script src='lib/docs/liner.js'></script></body></html>
<!DOCTYPE html><html lang='cn'><head><title>文档 | 涛思数据</title><meta name='description' content='TDengine是一个开源的专为物联网、车联网、工业互联网、IT运维等设计和优化的大数据平台。除核心的快10倍以上的时序数据库功能外,还提供缓存、数据订阅、流式计算等功能,最大程度减少研发和运维的工作量。'><meta name='keywords' content='大数据,Big Data,开源,物联网,车联网,工业互联网,IT运维, 时序数据库,缓存,数据订阅,消息队列,流式计算,开源,涛思数据,TAOS Data, TDengine'><meta name='title' content='文档 | 涛思数据'><meta property='og:site_name' content='涛思数据'/><meta property='og:title' content='文档 | 涛思数据'/><meta property='og:type' content='article'/><meta property='og:url' content='https://www.taosdata.com/cn/documentation'/><meta property='og:description' content='TDengine是一个开源的专为物联网、车联网、工业互联网、IT运维等设计和优化的大数据平台。除核心的快10倍以上的时序数据库功能外,还提供缓存、数据订阅、流式计算等功能,最大程度减少研发和运维的工作量。' /><link rel='canonical' href='https://www.taosdata.com/cn/documentation'/><script src='lib/jquery-3.4.1.min.js' type='application/javascript'></script><link href='lib/bootstrap.min.css' rel='stylesheet'><link href='styles/base.min.css' rel='stylesheet'><link rel='stylesheet' href='lib/docs/taosdataprettify.css'><link rel='stylesheet' href='lib/docs/docs.css'><link rel='stylesheet' href='styles/documentation/index.min.css'><script src='lib/docs/prettify.js'></script><script src='lib/docs/prettyprint-sql.js'></script></head><body><script>$('#documentation-href').addClass('active')</script><div class='container-fluid'><main class='content-wrapper'><section class='documentation'><h1>TDengine文档</h1><p>TDengine是一个高效的存储、查询、分析时序大数据的平台,专为物联网、车联网、工业互联网、运维监测等优化而设计。您可以像使用关系型数据库MySQL一样来使用它,但建议您在使用前仔细阅读一遍下面的文档,特别是<a href="data-model-and-architecture">数据模型</a><a href="super-table">超级表</a>一节。除本文档之外,欢迎<a href="https://www.taosdata.com/downloads/TDengine%20White%20Paper.pdf">下载产品白皮书</a></p><a href='getting-started/index.html'><h2>立即开始</h2></a><ul><li><a href='getting-started/index.html#快速上手'>快速上手</a>:下载、安装、体验,三秒钟搞定</li><li><a href='getting-started/index.html#TDengine命令行程序'>TDengine命令行程序</a>:访问TDengine的简便方式 </li><li><a href='getting-started/index.html#主要功能'>主要功能</a>:插入、查询、聚合、分析、缓存、订阅、流式计算等等</li></ul><a href='data-model-and-architecture/index.html'><h2>数据模型和设计</h2></a><ul><li><a href='data-model-and-architecture/index.html#数据模型'>数据模型</a>:关系型数据库模型,但要求每个采集设备单独建表 </li><li><a href='data-model-and-architecture/index.html#主要模块'>主要模块</a>:包含管理节点、数据节点和客户端,数据节点支持虚拟化</li><li><a href='data-model-and-architecture/index.html#写入流程'>写入流程</a>:先写入WAL、之后写入缓存,再给应用确认</li><li><a href='data-model-and-architecture/index.html#数据存储'>数据存储</a>:数据按时间段切片、采取列存、不同数据类型不同压缩算法 </li></ul><a href='taos-sql/index.html'><h2>TAOS SQL</h2></a><ul><li><a href='taos-sql/index.html#支持的数据类型'>支持的数据类型</a>:支持时间戳、整型、浮点型、布尔型、字符型等多种数据类型 </li><li><a href='taos-sql/index.html#数据库管理'>数据库管理</a>:添加、删除、查看数据库</li><li><a href='taos-sql/index.html#表管理'>表管理</a>:添加、删除、查看、修改表</li><li><a href='taos-sql/index.html#数据写入'>数据写入</a>:支持单表单条、多条、多表多条写入,支持历史数据写入</li><li><a href='taos-sql/index.html#数据查询'>数据查询</a>:支持时间段、值过滤、排序、查询结果手动分页等</li><li><a href='taos-sql/index.html#SQL函数'>SQL函数</a>:支持各种聚合函数、选择函数、计算函数,如avg, min, diff等</li><li><a href='taos-sql/index.html#时间维度聚合'>时间维度聚合</a>:将表中数据按照时间段进行切割后聚合,降维处理</li></ul><a href='super-table/index.html'><h2>超级表STable:多表聚合</h2></a><ul><li><a href='super-table/index.html#什么是超级表'>什么是超级表</a>:一种创新的方式来管理和聚合同一类设备</li><li><a href='super-table/index.html#超级表管理'>超级表管理</a>:创建/删除、改变超级表 </li><li><a href='super-table/index.html#写数据时自动建子表'>写数据时自动建子表</a>:用超级表做模板,自动建表</li><li><a href='super-table/index.html#STable中TAG管理'>STable中TAG管理</a>:增加、删除、修改超级表或表的标签</li><li><a href='super-table/index.html#STable多表聚合'>STable多表聚合</a>:通过设置标签过滤条件,将一组表进行聚合</li><li><a href='super-table/index.html#STable使用示例'>STable使用示例</a>:解释超级表的使用</li></ul><a href='advanced-features/index.html'><h2>高级功能</h2></a><ul><li><a href='advanced-features/index.html#连续查询(Continuous-Query)'>连续查询(Continuous Query)</a>:基于滑动窗口,定时自动的对数据流进行查询计算</li><li><a href='advanced-features/index.html#数据订阅(Publisher/Subscriber)'>数据订阅(Publisher/Subscriber)</a>:象典型的消息队列,应用可订阅接收到的最新数据</li><li><a href='advanced-features/index.html#缓存-(Cache)'>缓存 (Cache)</a>:每个设备最新的数据都会缓存在内存中,可快速获取</li></ul><a href='connector/index.html'><h2>连接器</h2></a><ul><li><a href='connector/index.html#C/C++-Connector'>C/C++ Connector</a>:通过libtaos客户端的库,连接TDengine服务器的主要方法</li><li><a href='connector/index.html#Java-Connector'>Java Connector(JDBC)</a>:通过标准的JDBC API,给Java应用提供到TDengine的连接</li><li><a href='connector/index.html#Python-Connector'>Python Connector</a>:给Python应用提供一个连接TDengine服务器的驱动 </li><li><a href='connector/index.html#RESTful-Connector'>RESTful Connector</a>:提供一最简单的连接TDengine服务器的方式</li><li><a href='connector/index.html#Go-Connector'>Go Connector</a>:给Go应用提供一个连接TDengine服务器的驱动</li><li><a href='connector/index.html#Node.js-Connector'>Node.js Connector</a>:给node应用提供一个链接TDengine服务器的驱动</li></ul><a href='connections-with-other-tools/index.html'><h2>与其他工具的连接</h2></a><ul><li><a href='connections-with-other-tools/index.html#Telegraf'>Telegraf</a>:将DevOps采集的数据发送到TDengine </li><li><a href='connections-with-other-tools/index.html#Grafana'>Grafana</a>:获取并可视化保存在TDengine的数据</li><li><a href='connections-with-other-tools/index.html#Matlab'>Matlab</a>:通过配置Matlab的JDBC数据源访问保存在TDengine的数据</li><li><a href='connections-with-other-tools/index.html#R'>R</a>:通过配置R的JDBC数据源访问保存在TDengine的数据 </li></ul><a href='administrator/index.html'><h2>系统管理</h2></a><ul><li><a href='administrator/index.html#文件目录结构'>文件目录结构</a>:TDengine数据文件、配置文件等所在目录</li><li><a href='administrator/index.html#服务端配置'>服务端配置</a>:端口,缓存大小,文件块大小和其他系统配置</li><li><a href='administrator/index.html#客户端配置'>客户端配置</a>:字符集、链接IP地址、缺省用户名、密码等配置</li><li><a href='administrator/index.html#用户管理'>用户管理</a>:添加、删除TDengine用户,修改用户密码</li><li><a href='administrator/index.html#数据导入'>数据导入</a>:可按脚本文件导入,也可按数据文件导入</li><li><a href='administrator/index.html#数据导出'>数据导出</a>:从shell按表导出,也可用taosdump工具做各种导出</li><li><a href='administrator/index.html#系统连接、任务查询管理'>系统连接、任务查询管理</a>:查询或停止现有的连接、查询和流式计算</li><li><a href='administrator/index.html#系统监控'>系统监控</a>:检查系统现有的连接、查询、流式计算,日志和事件等 </li></ul><a href='more-on-system-architecture/index.html'><h2>TDengine的技术设计</h2></a><ul><li><a href='more-on-system-architecture/index.html#存储设计'>存储设计</a>:为时序数据专门优化设计的列式存储格式</li><li><a href='more-on-system-architecture/index.html#查询处理'>查询处理</a>:高效的查询计算时序数据的方法</li><li><a href='more-on-system-architecture/index.html#集群设计'>集群设计</a>:吸取NoSQL的优点,支持高可靠,支持线性扩展</li><li><a href='https://www.taosdata.com/cn/blog/?categories=3'>技术博客</a>:更多的技术分析和架构设计文章</li></ul><a href='https://www.taosdata.com/cn/faq'><h2>培训和FAQ</h2></a><ul><li><a href='https://www.taosdata.com/en/faq'>FAQ</a>:常见问题与答案</li><li><a href='https://www.taosdata.com/en/blog/?categories=4'>应用案列</a>:一些使用实例来解释如何使用TDengine</li></ul><a href='../index.html'>回去</a></section></main></div><?php include($s.'/footer.php'); ?><script>$('pre').addClass('prettyprint linenums');PR.prettyPrint()</script><script src='lib/docs/liner.js'></script></body></html>
\ No newline at end of file
.documentation strong {
font-weight:600;
}
.documentation {
overflow:hidden;
margin-bottom: 10rem;
}
.documentation a {
font-size:1em;
text-decoration: none;
}
.documentation > a > h2 {
cursor:pointer;
color:var(--sg1);
}
.documentation > a >h2:hover {
color:var(--b2);
}
.documentation a:hover {
text-decoration: none;
}
.documentation pre {
margin-top: 0;
margin-bottom: 7px;
overflow: auto;
-ms-overflow-style: scrollbar;
margin-top: 7px;
}
pre * {
font-family:monospace !important
}
.documentation a {
color:var(--b2);
padding-bottom: 2px;
position: relative;
font-style: normal;
cursor: pointer;
}
.documentation a:hover,a:focus {
text-decoration: none;
color:var(--b2);
}
.documentation a::before {
content: "";
left: 0;
background-color: var(--b2);
width: 0%;
height: 1px;
top:-webkit-calc(1em + 8px);
top:calc(1em + 8px);
position: absolute;
z-index: 2;
-webkit-transition: background-color 0.2s, height 0.2s, top 0.2s, width 0.2s;
-o-transition: background-color 0.2s, height 0.2s, top 0.2s, width 0.2s;
transition: background-color 0.2s, height 0.2s, top 0.2s, width 0.2s;;
}
.documentation a:hover::before, .documentation a:focus::before {
content: "";
left: 0;
background-color: var(--b2);
width: 100%;
height: 1px;
top:-webkit-calc(1em + 8px);
top:calc(1em + 8px);
position: absolute;
z-index: 2;
-webkit-transition: background-color 0.2s, height 0.2s, top 0.2s, width 0.2s;
-o-transition: background-color 0.2s, height 0.2s, top 0.2s, width 0.2s;
transition: background-color 0.2s, height 0.2s, top 0.2s, width 0.2s;
text-decoration: none;
}
.documentation img {
width:100%;
max-width:640px;
margin-left: 50%;
-webkit-transform: translate(-50%,0);
-ms-transform: translate(-50%,0);
transform: translate(-50%,0);
}
h1,
h2,
h3,
h4,
h5,
h6 {
position: relative;
margin-bottom: 0.5rem;
font-weight: 500;
line-height: 1.4;
cursor: text;
}
h1:hover a.anchor,
h2:hover a.anchor,
h3:hover a.anchor,
h4:hover a.anchor,
h5:hover a.anchor,
h6:hover a.anchor {
text-decoration: none;
}
h1 tt,
h1 code {
font-size: inherit;
}
h2 tt,
h2 code {
font-size: inherit;
}
h3 tt,
h3 code {
font-size: inherit;
}
h4 tt,
h4 code {
font-size: inherit;
}
h5 tt,
h5 code {
font-size: inherit;
}
h6 tt,
h6 code {
font-size: inherit;
}
h1 {
font-size: 2.5rem;
line-height: 1.8;
}
h2 {
font-size: 1.7rem;
line-height: 1.8;
padding-left: 0.5em;
}
.documentation h2::before {
content:"";
height:1em;;
display: block;
width:3px;
margin-left: -0.5em;
margin-top: 0.4em;
position: absolute;
background-color: var(--b1);
}
h3 {
font-size: 1.4rem;
line-height: 1.43;
}
h4 {
font-size: 1.25rem;
}
h5 {
font-size: 1rem;
}
h6 {
font-size: 1rem;
color: #777;
}
p {
margin-bottom:0.5rem;
font-size:1em;
margin-top:0;
font-weight:300;
}
ol,ul,dl {
margin-top:0;
margin-bottom: 1rem;
}
li p {
margin-bottom: 0;
}
blockquote,
table{
margin: 0.8em 0;
width:100%;
}
figure table{
overflow: scroll;
}
hr {
height: 2px;
padding: 0;
margin: 16px 0;
background-color: #e7e7e7;
border: 0 none;
overflow: hidden;
-webkit-box-sizing: content-box;
box-sizing: content-box;
}
li p.first {
display: inline-block;
}
ul,
ol {
padding-left: 30px;
}
ul:first-child,
ol:first-child {
margin-top: 0;
}
ul:last-child,
ol:last-child {
margin-bottom: 0;
}
blockquote {
border-left: 4px solid #dfe2e5;
padding: 0 15px;
color: #777777;
}
blockquote blockquote {
padding-right: 0;
}
table {
padding: 0;
word-break: initial;
}
table tr {
border-top: 1px solid #dfe2e5;
margin: 0;
padding: 0;
}
table tr:nth-child(2n),
thead {
background-color: #f8f8f8;
}
table tr th {
font-weight: bold;
border: 1px solid #dfe2e5;
border-bottom: 0;
text-align: left;
margin: 0;
padding: 6px 13px;
}
table tr td {
border: 1px solid #dfe2e5;
text-align: left;
margin: 0;
padding: 6px 13px;
}
table tr th:first-child,
table tr td:first-child {
margin-top: 0;
}
table tr th:last-child,
table tr td:last-child {
margin-bottom: 0;
}
h1 code,h2 code, h3 code, h4 code, h5 code, h6 code,
p code, li code, td code,
tt {
border: 1px solid #e7eaed;
background-color: #f8f8f8;
-webkit-border-radius: 3px;
border-radius: 3px;
padding: 0;
font-size: 0.9em;
color:var(--sg1);
font-family:monospace;
background-color: #f3f4f4;
padding: 0 2px 0 2px;
}
/*Tell prettyprinted code not to follow above*/
.prettyprint code{
border:none;
background-color:transparent;
font-size:inherit;
padding:0 1px 0 0px;
}
\ No newline at end of file
/*JS to determine how many lines used in pre/code block, sets CSS appropriately. MUST be placed after elements with prettyprint class are loaded*/
$('.prettyprint').toArray().forEach(function(element){
let linenums = element.clientHeight / 25.2;
if (linenums > 99) {
$(element).addClass('threec');
}
else if (linenums > 9) {
$(element).addClass('twoc');
}
});
$('.prettyprint').toArray().forEach(function(element){
let linenums = element.clientHeight / 25.2;
if (linenums > 99) {
$(element).addClass('threec');
}
else if (linenums > 9) {
$(element).addClass('twoc');
}
});
\ No newline at end of file
!function(){/*
Copyright (C) 2006 Google Inc.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
"undefined"!==typeof window&&(window.PR_SHOULD_USE_CONTINUATION=!0);
(function(){function T(a){function d(e){var a=e.charCodeAt(0);if(92!==a)return a;var c=e.charAt(1);return(a=w[c])?a:"0"<=c&&"7">=c?parseInt(e.substring(1),8):"u"===c||"x"===c?parseInt(e.substring(2),16):e.charCodeAt(1)}function f(e){if(32>e)return(16>e?"\\x0":"\\x")+e.toString(16);e=String.fromCharCode(e);return"\\"===e||"-"===e||"]"===e||"^"===e?"\\"+e:e}function c(e){var c=e.substring(1,e.length-1).match(RegExp("\\\\u[0-9A-Fa-f]{4}|\\\\x[0-9A-Fa-f]{2}|\\\\[0-3][0-7]{0,2}|\\\\[0-7]{1,2}|\\\\[\\s\\S]|-|[^-\\\\]","g"));
e=[];var a="^"===c[0],b=["["];a&&b.push("^");for(var a=a?1:0,g=c.length;a<g;++a){var h=c[a];if(/\\[bdsw]/i.test(h))b.push(h);else{var h=d(h),k;a+2<g&&"-"===c[a+1]?(k=d(c[a+2]),a+=2):k=h;e.push([h,k]);65>k||122<h||(65>k||90<h||e.push([Math.max(65,h)|32,Math.min(k,90)|32]),97>k||122<h||e.push([Math.max(97,h)&-33,Math.min(k,122)&-33]))}}e.sort(function(e,a){return e[0]-a[0]||a[1]-e[1]});c=[];g=[];for(a=0;a<e.length;++a)h=e[a],h[0]<=g[1]+1?g[1]=Math.max(g[1],h[1]):c.push(g=h);for(a=0;a<c.length;++a)h=
c[a],b.push(f(h[0])),h[1]>h[0]&&(h[1]+1>h[0]&&b.push("-"),b.push(f(h[1])));b.push("]");return b.join("")}function m(e){for(var a=e.source.match(RegExp("(?:\\[(?:[^\\x5C\\x5D]|\\\\[\\s\\S])*\\]|\\\\u[A-Fa-f0-9]{4}|\\\\x[A-Fa-f0-9]{2}|\\\\[0-9]+|\\\\[^ux0-9]|\\(\\?[:!=]|[\\(\\)\\^]|[^\\x5B\\x5C\\(\\)\\^]+)","g")),b=a.length,d=[],g=0,h=0;g<b;++g){var k=a[g];"("===k?++h:"\\"===k.charAt(0)&&(k=+k.substring(1))&&(k<=h?d[k]=-1:a[g]=f(k))}for(g=1;g<d.length;++g)-1===d[g]&&(d[g]=++E);for(h=g=0;g<b;++g)k=a[g],
"("===k?(++h,d[h]||(a[g]="(?:")):"\\"===k.charAt(0)&&(k=+k.substring(1))&&k<=h&&(a[g]="\\"+d[k]);for(g=0;g<b;++g)"^"===a[g]&&"^"!==a[g+1]&&(a[g]="");if(e.ignoreCase&&q)for(g=0;g<b;++g)k=a[g],e=k.charAt(0),2<=k.length&&"["===e?a[g]=c(k):"\\"!==e&&(a[g]=k.replace(/[a-zA-Z]/g,function(a){a=a.charCodeAt(0);return"["+String.fromCharCode(a&-33,a|32)+"]"}));return a.join("")}for(var E=0,q=!1,l=!1,n=0,b=a.length;n<b;++n){var p=a[n];if(p.ignoreCase)l=!0;else if(/[a-z]/i.test(p.source.replace(/\\u[0-9a-f]{4}|\\x[0-9a-f]{2}|\\[^ux]/gi,
""))){q=!0;l=!1;break}}for(var w={b:8,t:9,n:10,v:11,f:12,r:13},r=[],n=0,b=a.length;n<b;++n){p=a[n];if(p.global||p.multiline)throw Error(""+p);r.push("(?:"+m(p)+")")}return new RegExp(r.join("|"),l?"gi":"g")}function U(a,d){function f(a){var b=a.nodeType;if(1==b){if(!c.test(a.className)){for(b=a.firstChild;b;b=b.nextSibling)f(b);b=a.nodeName.toLowerCase();if("br"===b||"li"===b)m[l]="\n",q[l<<1]=E++,q[l++<<1|1]=a}}else if(3==b||4==b)b=a.nodeValue,b.length&&(b=d?b.replace(/\r\n?/g,"\n"):b.replace(/[ \t\r\n]+/g,
" "),m[l]=b,q[l<<1]=E,E+=b.length,q[l++<<1|1]=a)}var c=/(?:^|\s)nocode(?:\s|$)/,m=[],E=0,q=[],l=0;f(a);return{a:m.join("").replace(/\n$/,""),c:q}}function J(a,d,f,c,m){f&&(a={h:a,l:1,j:null,m:null,a:f,c:null,i:d,g:null},c(a),m.push.apply(m,a.g))}function V(a){for(var d=void 0,f=a.firstChild;f;f=f.nextSibling)var c=f.nodeType,d=1===c?d?a:f:3===c?W.test(f.nodeValue)?a:d:d;return d===a?void 0:d}function G(a,d){function f(a){for(var l=a.i,n=a.h,b=[l,"pln"],p=0,q=a.a.match(m)||[],r={},e=0,t=q.length;e<
t;++e){var z=q[e],v=r[z],g=void 0,h;if("string"===typeof v)h=!1;else{var k=c[z.charAt(0)];if(k)g=z.match(k[1]),v=k[0];else{for(h=0;h<E;++h)if(k=d[h],g=z.match(k[1])){v=k[0];break}g||(v="pln")}!(h=5<=v.length&&"lang-"===v.substring(0,5))||g&&"string"===typeof g[1]||(h=!1,v="src");h||(r[z]=v)}k=p;p+=z.length;if(h){h=g[1];var A=z.indexOf(h),C=A+h.length;g[2]&&(C=z.length-g[2].length,A=C-h.length);v=v.substring(5);J(n,l+k,z.substring(0,A),f,b);J(n,l+k+A,h,K(v,h),b);J(n,l+k+C,z.substring(C),f,b)}else b.push(l+
k,v)}a.g=b}var c={},m;(function(){for(var f=a.concat(d),l=[],n={},b=0,p=f.length;b<p;++b){var w=f[b],r=w[3];if(r)for(var e=r.length;0<=--e;)c[r.charAt(e)]=w;w=w[1];r=""+w;n.hasOwnProperty(r)||(l.push(w),n[r]=null)}l.push(/[\0-\uffff]/);m=T(l)})();var E=d.length;return f}function x(a){var d=[],f=[];a.tripleQuotedStrings?d.push(["str",/^(?:\'\'\'(?:[^\'\\]|\\[\s\S]|\'{1,2}(?=[^\']))*(?:\'\'\'|$)|\"\"\"(?:[^\"\\]|\\[\s\S]|\"{1,2}(?=[^\"]))*(?:\"\"\"|$)|\'(?:[^\\\']|\\[\s\S])*(?:\'|$)|\"(?:[^\\\"]|\\[\s\S])*(?:\"|$))/,
null,"'\""]):a.multiLineStrings?d.push(["str",/^(?:\'(?:[^\\\']|\\[\s\S])*(?:\'|$)|\"(?:[^\\\"]|\\[\s\S])*(?:\"|$)|\`(?:[^\\\`]|\\[\s\S])*(?:\`|$))/,null,"'\"`"]):d.push(["str",/^(?:\'(?:[^\\\'\r\n]|\\.)*(?:\'|$)|\"(?:[^\\\"\r\n]|\\.)*(?:\"|$))/,null,"\"'"]);a.verbatimStrings&&f.push(["str",/^@\"(?:[^\"]|\"\")*(?:\"|$)/,null]);var c=a.hashComments;c&&(a.cStyleComments?(1<c?d.push(["com",/^#(?:##(?:[^#]|#(?!##))*(?:###|$)|.*)/,null,"#"]):d.push(["com",/^#(?:(?:define|e(?:l|nd)if|else|error|ifn?def|include|line|pragma|undef|warning)\b|[^\r\n]*)/,
null,"#"]),f.push(["str",/^<(?:(?:(?:\.\.\/)*|\/?)(?:[\w-]+(?:\/[\w-]+)+)?[\w-]+\.h(?:h|pp|\+\+)?|[a-z]\w*)>/,null])):d.push(["com",/^#[^\r\n]*/,null,"#"]));a.cStyleComments&&(f.push(["com",/^\/\/[^\r\n]*/,null]),f.push(["com",/^\/\*[\s\S]*?(?:\*\/|$)/,null]));if(c=a.regexLiterals){var m=(c=1<c?"":"\n\r")?".":"[\\S\\s]";f.push(["lang-regex",RegExp("^(?:^^\\.?|[+-]|[!=]=?=?|\\#|%=?|&&?=?|\\(|\\*=?|[+\\-]=|->|\\/=?|::?|<<?=?|>>?>?=?|,|;|\\?|@|\\[|~|{|\\^\\^?=?|\\|\\|?=?|break|case|continue|delete|do|else|finally|instanceof|return|throw|try|typeof)\\s*("+
("/(?=[^/*"+c+"])(?:[^/\\x5B\\x5C"+c+"]|\\x5C"+m+"|\\x5B(?:[^\\x5C\\x5D"+c+"]|\\x5C"+m+")*(?:\\x5D|$))+/")+")")])}(c=a.types)&&f.push(["typ",c]);c=(""+a.keywords).replace(/^ | $/g,"");c.length&&f.push(["kwd",new RegExp("^(?:"+c.replace(/[\s,]+/g,"|")+")\\b"),null]);d.push(["pln",/^\s+/,null," \r\n\t\u00a0"]);c="^.[^\\s\\w.$@'\"`/\\\\]*";a.regexLiterals&&(c+="(?!s*/)");f.push(["lit",/^@[a-z_$][a-z_$@0-9]*/i,null],["typ",/^(?:[@_]?[A-Z]+[a-z][A-Za-z_$@0-9]*|\w+_t\b)/,null],["pln",/^[a-z_$][a-z_$@0-9]*/i,
null],["lit",/^(?:0x[a-f0-9]+|(?:\d(?:_\d+)*\d*(?:\.\d*)?|\.\d\+)(?:e[+\-]?\d+)?)[a-z]*/i,null,"0123456789"],["pln",/^\\[\s\S]?/,null],["pun",new RegExp(c),null]);return G(d,f)}function L(a,d,f){function c(a){var b=a.nodeType;if(1==b&&!t.test(a.className))if("br"===a.nodeName.toLowerCase())m(a),a.parentNode&&a.parentNode.removeChild(a);else for(a=a.firstChild;a;a=a.nextSibling)c(a);else if((3==b||4==b)&&f){var e=a.nodeValue,d=e.match(q);d&&(b=e.substring(0,d.index),a.nodeValue=b,(e=e.substring(d.index+
d[0].length))&&a.parentNode.insertBefore(l.createTextNode(e),a.nextSibling),m(a),b||a.parentNode.removeChild(a))}}function m(a){function c(a,b){var e=b?a.cloneNode(!1):a,k=a.parentNode;if(k){var k=c(k,1),d=a.nextSibling;k.appendChild(e);for(var f=d;f;f=d)d=f.nextSibling,k.appendChild(f)}return e}for(;!a.nextSibling;)if(a=a.parentNode,!a)return;a=c(a.nextSibling,0);for(var e;(e=a.parentNode)&&1===e.nodeType;)a=e;b.push(a)}for(var t=/(?:^|\s)nocode(?:\s|$)/,q=/\r\n?|\n/,l=a.ownerDocument,n=l.createElement("li");a.firstChild;)n.appendChild(a.firstChild);
for(var b=[n],p=0;p<b.length;++p)c(b[p]);d===(d|0)&&b[0].setAttribute("value",d);var w=l.createElement("ol");w.className="linenums";d=Math.max(0,d-1|0)||0;for(var p=0,r=b.length;p<r;++p)n=b[p],n.className="L"+(p+d)%10,n.firstChild||n.appendChild(l.createTextNode("\u00a0")),w.appendChild(n);a.appendChild(w)}function t(a,d){for(var f=d.length;0<=--f;){var c=d[f];I.hasOwnProperty(c)?D.console&&console.warn("cannot override language handler %s",c):I[c]=a}}function K(a,d){a&&I.hasOwnProperty(a)||(a=/^\s*</.test(d)?
"default-markup":"default-code");return I[a]}function M(a){var d=a.j;try{var f=U(a.h,a.l),c=f.a;a.a=c;a.c=f.c;a.i=0;K(d,c)(a);var m=/\bMSIE\s(\d+)/.exec(navigator.userAgent),m=m&&8>=+m[1],d=/\n/g,t=a.a,q=t.length,f=0,l=a.c,n=l.length,c=0,b=a.g,p=b.length,w=0;b[p]=q;var r,e;for(e=r=0;e<p;)b[e]!==b[e+2]?(b[r++]=b[e++],b[r++]=b[e++]):e+=2;p=r;for(e=r=0;e<p;){for(var x=b[e],z=b[e+1],v=e+2;v+2<=p&&b[v+1]===z;)v+=2;b[r++]=x;b[r++]=z;e=v}b.length=r;var g=a.h;a="";g&&(a=g.style.display,g.style.display="none");
try{for(;c<n;){var h=l[c+2]||q,k=b[w+2]||q,v=Math.min(h,k),A=l[c+1],C;if(1!==A.nodeType&&(C=t.substring(f,v))){m&&(C=C.replace(d,"\r"));A.nodeValue=C;var N=A.ownerDocument,u=N.createElement("span");u.className=b[w+1];var B=A.parentNode;B.replaceChild(u,A);u.appendChild(A);f<h&&(l[c+1]=A=N.createTextNode(t.substring(v,h)),B.insertBefore(A,u.nextSibling))}f=v;f>=h&&(c+=2);f>=k&&(w+=2)}}finally{g&&(g.style.display=a)}}catch(y){D.console&&console.log(y&&y.stack||y)}}var D="undefined"!==typeof window?
window:{},B=["break,continue,do,else,for,if,return,while"],F=[[B,"auto,case,char,const,default,double,enum,extern,float,goto,inline,int,long,register,restrict,short,signed,sizeof,static,struct,switch,typedef,union,unsigned,void,volatile"],"catch,class,delete,false,import,new,operator,private,protected,public,this,throw,true,try,typeof"],H=[F,"alignas,alignof,align_union,asm,axiom,bool,concept,concept_map,const_cast,constexpr,decltype,delegate,dynamic_cast,explicit,export,friend,generic,late_check,mutable,namespace,noexcept,noreturn,nullptr,property,reinterpret_cast,static_assert,static_cast,template,typeid,typename,using,virtual,where"],
O=[F,"abstract,assert,boolean,byte,extends,finally,final,implements,import,instanceof,interface,null,native,package,strictfp,super,synchronized,throws,transient"],P=[F,"abstract,add,alias,as,ascending,async,await,base,bool,by,byte,checked,decimal,delegate,descending,dynamic,event,finally,fixed,foreach,from,get,global,group,implicit,in,interface,internal,into,is,join,let,lock,null,object,out,override,orderby,params,partial,readonly,ref,remove,sbyte,sealed,select,set,stackalloc,string,select,uint,ulong,unchecked,unsafe,ushort,value,var,virtual,where,yield"],
F=[F,"abstract,async,await,constructor,debugger,enum,eval,export,from,function,get,import,implements,instanceof,interface,let,null,of,set,undefined,var,with,yield,Infinity,NaN"],Q=[B,"and,as,assert,class,def,del,elif,except,exec,finally,from,global,import,in,is,lambda,nonlocal,not,or,pass,print,raise,try,with,yield,False,True,None"],R=[B,"alias,and,begin,case,class,def,defined,elsif,end,ensure,false,in,module,next,nil,not,or,redo,rescue,retry,self,super,then,true,undef,unless,until,when,yield,BEGIN,END"],
B=[B,"case,done,elif,esac,eval,fi,function,in,local,set,then,until"],S=/^(DIR|FILE|array|vector|(de|priority_)?queue|(forward_)?list|stack|(const_)?(reverse_)?iterator|(unordered_)?(multi)?(set|map)|bitset|u?(int|float)\d*)\b/,W=/\S/,X=x({keywords:[H,P,O,F,"caller,delete,die,do,dump,elsif,eval,exit,foreach,for,goto,if,import,last,local,my,next,no,our,print,package,redo,require,sub,undef,unless,until,use,wantarray,while,BEGIN,END",Q,R,B],hashComments:!0,cStyleComments:!0,multiLineStrings:!0,regexLiterals:!0}),
I={};t(X,["default-code"]);t(G([],[["pln",/^[^<?]+/],["dec",/^<!\w[^>]*(?:>|$)/],["com",/^<\!--[\s\S]*?(?:-\->|$)/],["lang-",/^<\?([\s\S]+?)(?:\?>|$)/],["lang-",/^<%([\s\S]+?)(?:%>|$)/],["pun",/^(?:<[%?]|[%?]>)/],["lang-",/^<xmp\b[^>]*>([\s\S]+?)<\/xmp\b[^>]*>/i],["lang-js",/^<script\b[^>]*>([\s\S]*?)(<\/script\b[^>]*>)/i],["lang-css",/^<style\b[^>]*>([\s\S]*?)(<\/style\b[^>]*>)/i],["lang-in.tag",/^(<\/?[a-z][^<>]*>)/i]]),"default-markup htm html mxml xhtml xml xsl".split(" "));t(G([["pln",/^[\s]+/,
null," \t\r\n"],["atv",/^(?:\"[^\"]*\"?|\'[^\']*\'?)/,null,"\"'"]],[["tag",/^^<\/?[a-z](?:[\w.:-]*\w)?|\/?>$/i],["atn",/^(?!style[\s=]|on)[a-z](?:[\w:-]*\w)?/i],["lang-uq.val",/^=\s*([^>\'\"\s]*(?:[^>\'\"\s\/]|\/(?=\s)))/],["pun",/^[=<>\/]+/],["lang-js",/^on\w+\s*=\s*\"([^\"]+)\"/i],["lang-js",/^on\w+\s*=\s*\'([^\']+)\'/i],["lang-js",/^on\w+\s*=\s*([^\"\'>\s]+)/i],["lang-css",/^style\s*=\s*\"([^\"]+)\"/i],["lang-css",/^style\s*=\s*\'([^\']+)\'/i],["lang-css",/^style\s*=\s*([^\"\'>\s]+)/i]]),["in.tag"]);
t(G([],[["atv",/^[\s\S]+/]]),["uq.val"]);t(x({keywords:H,hashComments:!0,cStyleComments:!0,types:S}),"c cc cpp cxx cyc m".split(" "));t(x({keywords:"null,true,false"}),["json"]);t(x({keywords:P,hashComments:!0,cStyleComments:!0,verbatimStrings:!0,types:S}),["cs"]);t(x({keywords:O,cStyleComments:!0}),["java"]);t(x({keywords:B,hashComments:!0,multiLineStrings:!0}),["bash","bsh","csh","sh"]);t(x({keywords:Q,hashComments:!0,multiLineStrings:!0,tripleQuotedStrings:!0}),["cv","py","python"]);t(x({keywords:"caller,delete,die,do,dump,elsif,eval,exit,foreach,for,goto,if,import,last,local,my,next,no,our,print,package,redo,require,sub,undef,unless,until,use,wantarray,while,BEGIN,END",
hashComments:!0,multiLineStrings:!0,regexLiterals:2}),["perl","pl","pm"]);t(x({keywords:R,hashComments:!0,multiLineStrings:!0,regexLiterals:!0}),["rb","ruby"]);t(x({keywords:F,cStyleComments:!0,regexLiterals:!0}),["javascript","js","ts","typescript"]);t(x({keywords:"all,and,by,catch,class,else,extends,false,finally,for,if,in,is,isnt,loop,new,no,not,null,of,off,on,or,return,super,then,throw,true,try,unless,until,when,while,yes",hashComments:3,cStyleComments:!0,multilineStrings:!0,tripleQuotedStrings:!0,
regexLiterals:!0}),["coffee"]);t(G([],[["str",/^[\s\S]+/]]),["regex"]);var Y=D.PR={createSimpleLexer:G,registerLangHandler:t,sourceDecorator:x,PR_ATTRIB_NAME:"atn",PR_ATTRIB_VALUE:"atv",PR_COMMENT:"com",PR_DECLARATION:"dec",PR_KEYWORD:"kwd",PR_LITERAL:"lit",PR_NOCODE:"nocode",PR_PLAIN:"pln",PR_PUNCTUATION:"pun",PR_SOURCE:"src",PR_STRING:"str",PR_TAG:"tag",PR_TYPE:"typ",TAOSDATA_FUNCTION:"td-fun",TAOSDATA_DATATYPE:"td-dtp",TAOSDATA_TERMINAL:"tem",TAOSDATA_OPTION:"td-opt",prettyPrintOne:D.prettyPrintOne=function(a,d,f){f=f||!1;d=d||null;var c=document.createElement("div");c.innerHTML="<pre>"+a+"</pre>";
c=c.firstChild;f&&L(c,f,!0);M({j:d,m:f,h:c,l:1,a:null,i:null,c:null,g:null});return c.innerHTML},prettyPrint:D.prettyPrint=function(a,d){function f(){for(var c=D.PR_SHOULD_USE_CONTINUATION?b.now()+250:Infinity;p<x.length&&b.now()<c;p++){for(var d=x[p],l=g,n=d;n=n.previousSibling;){var m=n.nodeType,u=(7===m||8===m)&&n.nodeValue;if(u?!/^\??prettify\b/.test(u):3!==m||/\S/.test(n.nodeValue))break;if(u){l={};u.replace(/\b(\w+)=([\w:.%+-]+)/g,function(a,b,c){l[b]=c});break}}n=d.className;if((l!==g||r.test(n))&&
!e.test(n)){m=!1;for(u=d.parentNode;u;u=u.parentNode)if(v.test(u.tagName)&&u.className&&r.test(u.className)){m=!0;break}if(!m){d.className+=" prettyprinted";m=l.lang;if(!m){var m=n.match(w),q;!m&&(q=V(d))&&z.test(q.tagName)&&(m=q.className.match(w));m&&(m=m[1])}if(B.test(d.tagName))u=1;else var u=d.currentStyle,y=t.defaultView,u=(u=u?u.whiteSpace:y&&y.getComputedStyle?y.getComputedStyle(d,null).getPropertyValue("white-space"):0)&&"pre"===u.substring(0,3);y=l.linenums;(y="true"===y||+y)||(y=(y=n.match(/\blinenums\b(?::(\d+))?/))?
y[1]&&y[1].length?+y[1]:!0:!1);y&&L(d,y,u);M({j:m,h:d,m:y,l:u,a:null,i:null,c:null,g:null})}}}p<x.length?D.setTimeout(f,250):"function"===typeof a&&a()}for(var c=d||document.body,t=c.ownerDocument||document,c=[c.getElementsByTagName("pre"),c.getElementsByTagName("code"),c.getElementsByTagName("xmp")],x=[],q=0;q<c.length;++q)for(var l=0,n=c[q].length;l<n;++l)x.push(c[q][l]);var c=null,b=Date;b.now||(b={now:function(){return+new Date}});var p=0,w=/\blang(?:uage)?-([\w.]+)(?!\S)/,r=/\bprettyprint\b/,
e=/\bprettyprinted\b/,B=/pre|xmp/i,z=/^code$/i,v=/^(?:pre|code|xmp)$/i,g={};f()}},H=D.define;"function"===typeof H&&H.amd&&H("google-code-prettify",[],function(){return Y})})();}()
PR['registerLangHandler'](
PR['createSimpleLexer'](
[
// Whitespace
[PR['PR_PLAIN'], /^[\t\n\r \xA0]+/, null, '\t\n\r \xA0'],
// A double or single quoted, possibly multi-line, string.
[PR['PR_STRING'], /^(?:"(?:[^\"\\]|\\.)*"|'(?:[^\'\\]|\\.)*')/, null,
'"\'']
],
[
// A comment is either a line comment that starts with two dashes, or
// two dashes preceding a long bracketed block.
[PR['PR_COMMENT'], /^(?:--[^\r\n]*|\/\*[\s\S]*?(?:\*\/|$))/],
[PR['PR_KEYWORD'], /^(?:ADD|ALL|ALTER|AND|ANY|APPLY|AS|ASC|AUTHORIZATION|BACKUP|BEGIN|BETWEEN|BREAK|BROWSE|BULK|BY|CASCADE|CASE|CHECK|CHECKPOINT|CLOSE|CLUSTERED|COALESCE|COLLATE|COLUMN|COMMIT|COMPUTE|CONNECT|CONSTRAINT|CONTAINS|CONTAINSTABLE|CONTINUE|CONVERT|CREATE|CROSS|CURRENT|CURRENT_DATE|CURRENT_TIME|CURRENT_TIMESTAMP|CURRENT_USER|CURSOR|DATABASE|DBCC|DEALLOCATE|DECLARE|DEFAULT|DELETE|DENY|DESC|DISK|DISTINCT|DISTRIBUTED|DROP|DUMMY|DUMP|ELSE|END|ERRLVL|ESCAPE|EXCEPT|EXEC|EXECUTE|EXISTS|EXIT|FETCH|FILE|FILL|FILLFACTOR|FOLLOWING|FOR|FOREIGN|FREETEXT|FREETEXTTABLE|FROM|FULL|FUNCTION|GOTO|GRANT|GROUP|HAVING|HOLDLOCK|IDENTITY|IDENTITYCOL|IDENTITY_INSERT|IF|IN|INDEX|INNER|INSERT|INTERSECT|INTO|IS|JOIN|KEY|KILL|LEFT|LIKE|LINENO|LOAD|MATCH|MATCHED|MERGE|NATURAL|NATIONAL|NOCHECK|NONCLUSTERED|NOCYCLE|NOT|NULL|NULLIF|OF|OFF|OFFSETS|ON|OPEN|OPENDATASOURCE|OPENQUERY|OPENROWSET|OPENXML|OPTION|OR|ORDER|OUTER|OVER|PARTITION|PERCENT|PIVOT|PLAN|PRECEDING|PRIMARY|PRINT|PROC|PROCEDURE|PUBLIC|RAISERROR|READ|READTEXT|RECONFIGURE|REFERENCES|REPLICATION|RESTORE|RESTRICT|RETURN|REVOKE|RIGHT|ROLLBACK|ROWCOUNT|ROWGUIDCOL|RULE|SAVE|SCHEMA|SELECT|SESSION_USER|SET|SETUSER|SHUTDOWN|SLIDING|SOME|START|STATISTICS|SYSTEM_USER|TABLE|TAGS|TEXTSIZE|THEN|TO|TRAN|TRANSACTION|TRIGGER|TRUNCATE|TSEQUAL|UNBOUNDED|UNION|UNIQUE|UNPIVOT|UPDATE|UPDATETEXT|USE|USER|USING|VALUES|VARYING|VIEW|WAITFOR|WHEN|WHERE|WHILE|WITH|WITHIN|WRITETEXT|XML|ID|STRING|INTEGER|OR|AND|NOT|EQ|NE|ISNULL|NOTNULL|IS|LIKE|GLOB|BETWEEN|IN|GT|GE|LT|LE|BITAND|BITOR|LSHIFT|RSHIFT|PLUS|MINUS|DIVIDE|TIMES|STAR|SLASH|REM|CONCAT|UMINUS|UPLUS|BITNOT|SHOW|DATABASES|MNODES|USERS|MODULES|QUERIES|CONNECTIONS|STREAMS|CONFIGS|SCORES|GRANTS|DOT|TABLES|METRICS|VGROUPS|DROP|TABLE|DATABASE|IP|USER|USE|DESCRIBE|ALTER|PASS|PRIVILEGE|LOCAL|IF|EXISTS|REPLICA|DAYS|KEEP|ROWS|CACHE|ABLOCKS|TBLOCKS|CTIME|CLOG|COMP|LP|RP|TAGS|USING|AS|COMMA|SELECT|FROM|VARIABLE|INTERVAL|FILL|SLIDING|ORDER|BY|ASC|DESC|GROUP|LIMIT|OFFSET|WHERE|NOW|INSERT|INTO|VALUES|RESET|QUERY|ADD|COLUMN|TAG|CHANGE|SET|KILL|CONNECTION|STREAM|ABORT|AFTER|ATTACH|BEFORE|BEGIN|CASCADE|CLUSTER|CONFLICT|COPY|DEFERRED|DELIMITERS|DETACH|EACH|END|EXPLAIN|FAIL|FOR|IGNORE|IMMEDIATE|INITIALLY|INSTEAD|MATCH|KEY|OF|RAISE|REPLACE|RESTRICT|ROW|STATEMENT|TRIGGER|VIEW|ALL|SEMI|NONE|PREV|LINEAR|IMPORT|METRIC|TBNAME|JOIN|STABLE|STABLES|SLIMIT|SOFFSET|HAVING|PRECISION|STREAMS|NULL)(?=[^\w-]|$)/i, null],
//
[PR['TAOSDATA_FUNCTION'], /^(?:"APERCENTILE|AVG|BOTTOM|COUNT|DIFF|FIRST|HISTOGRAM|INTERP|LAST|LAST_ROW|LEASTSQUARES|MAX|MIN|PERCENTILE|SPREAD|STDDEV|SUM|TOP|WAVG")(?=[^\w-]|$)/i, null],
[PR['TAOSDATA_OPTION'],
/^(?:ABLOCKS|CACHE|CLOG|COMP|CTIME|DAYS|KEEP|PRECISION|REPLICA|ROWS|TABLES|TBLOCKS)(?=[^\w-]|$)/i,null],
[PR['TAOSDATA_DATATYPE'],
/^(?:BIGINT|BINARY|BOOL|DOUBLE|FLOAT|INT|NCHAR|SMALLINT|TINYINT[^\w-]|$)/i, null],
// A number is a hex integer literal, a decimal real literal, or in
// scientific notation.
[PR['PR_LITERAL'],
/^[+-]?(?:0x[\da-f]+|(?:(?:\.\d+|\d+(?:\.\d*)?)(?:e[+\-]?\d+)?))/i],
// An identifier
[PR['PR_PLAIN'], /^[a-z_][\w-]*/i],
// A run of punctuation
[PR['PR_PUNCTUATION'], /^[^\w\t\n\r \xA0\"\'][^\w\t\n\r \xA0+\-\"\']*/]
]
),
['sql','mysql']);
\ No newline at end of file
PR['registerLangHandler'](
PR['createSimpleLexer'](
[
// A comment is either a line comment that starts with two dashes, or
// two dashes preceding a long bracketed block.
[PR['TAOSDATA_TERMINAL'], /^(*?)/]
]
),
['terminal','term']);
\ No newline at end of file
pre.prettyprint ol {
list-style-type: none;
margin-left: 0;
}
pre.prettyprint ol > li {
counter-increment: customlistcounter;
}
pre.prettyprint ol > li:first-child:before {
border-top-left-radius: 0.25rem;
}
pre.prettyprint ol > li:last-child:before {
border-bottom-left-radius: 0.25rem;
}
pre.prettyprint ol > li:before {
content: counter(customlistcounter) " ";
font-weight: 300;
display: inline-block;
position: absolute;
transform:translateX(-38px);
width: 27px;
text-align: right;
background-color:var(--white);
padding-bottom: 0.1px;
}
pre.prettyprint ol > li:nth-last-child(1)::before {
padding-bottom: 0px !important;
}
pre.prettyprint.twoc ol > li:before {
transform:translateX(-45px);
width:34px;
}
pre.prettyprint.twoc {
padding-left:35px;
}
pre.prettyprint.threec ol > li:before {
transform:translateX(-53px);
width:42px;
}
pre.prettyprint.threec {
padding-left:43px;
}
ol:first-child {
counter-reset: customlistcounter;
}
pre.prettyprint ol {
padding-right: 4px;
}
pre .atn,
pre .kwd,
pre .tag {
font-weight: 400
}
pre * {
font-family:monospace;
}
pre.prettyprint li {
background-color:rgb(244,245,246);
}
pre.prettyprint {
display: block;
background-color:rgb(244,245,246);
border-radius:0.25rem;
padding-left: 27px;
/*each additional digit needs 8px*/
width:100%;
border:1px solid #e7eaed;
color:#d58936;
}
/* TAOSDATA Specific */
pre.lang-blank span {
color:var(--sg1);
}
pre.lang-blank {
}
pre.lang-term span{
color: var(--white) ;
}
pre.lang-term ol {
background-color: var(--sg1);
}
pre.lang-term ol.linenums {
border-left:1px solid var(--sg1);
}
pre.lang-term li {
background-color:var(--sg1);
}
/*Functions*/
pre .td-fun {
color:#f24352;
}
/*Options*/
pre .td-opt {
/*color:mediumpurple;*/
color:#5882bc;
}
/*Datatypes*/
pre .td-dtp {
color:darkcyan;
}
pre .nocode {
background-color: var(--white);
color: var(--sg1);
}
/*Strings*/
pre .str {
color: #690;
}
/*Keywords*/
pre .kwd {
color: #5882bc;
}
/*Comments*/
pre .com {
color: slategray;
}
/*Type*/
pre .typ {
color: #9c5fc6;
}
/*Literals*/
pre .lit {
color: #91001f;
}
/*Plain Text*/
pre .pln {
color: #d58936;
}
/*Punctuation*/
pre .pun {
color: rgb(51,66,78);
}
pre .tag {
color: khaki
}
pre .atn {
color: #bdb76b
}
pre .atv {
color: #ffa0a0
}
pre .dec {
color: #98fb98
}
ol.linenums {
margin-top: 0;
margin-bottom: 0;
color: #AEAEAE;
border-left:1px solid var(--b1);
padding-left: 0px;
}
pre li {
padding-left: 0.6rem;
}
li.L0,
li.L1,
li.L2,
li.L3,
li.L5,
li.L6,
li.L7,
li.L8 {
list-style-type: none
}
@media print {
pre.prettyprint {
background-color: none
}
code .str,
pre .str {
color: #690;
}
code .kwd,
pre .kwd {
color: #5882bc;
font-weight: 400
}
code .com,
pre .com {
color: #600;
font-style: italic
}
code .typ,
pre .typ {
color: #404;
font-weight: 400
}
code .lit,
pre .lit {
color: #044
}
code .pun,
pre .pun {
color: #440
}
code .pln,
pre .pln {
color: #000
}
code .tag,
pre .tag {
color: #006;
font-weight: 400
}
code .atn,
pre .atn {
color: #404
}
code .atv,
pre .atv {
color: #060
}
}
\ No newline at end of file
此差异已折叠。
:root{--b1:rgb(0,118,206);--b1t:rgba(0,118,206,0.15);--b2:rgb(72,159,223);--sg-1:#b3b4b9;--sg0:#585c66;--sg1:rgb(51,56,68);--sg2:#2F333E;--sg3:#21242c;--black:#212529;--white:#fefefe;--white2:rgb(251, 251, 253);--white3:rgb(240,242,244);--footer1:#fefefe;--footer2:#333844;--red:#ea4741;--green:#72c156;--p1:#72c156;--p1t:rgba(114,193,86,0.15);--p2:#43b3ae;--p2t:rgba(70,161,168,0.15);--p3:#4997d0;--p3t:rgba(73,151,208,0.15)}html{font-size:12pt;background-color:var(--white)}body,body *{font-family:"Open Sans",Helvetica,'Hiragino Sans GB',sans-serif,"Apple Color Emoji";-webkit-font-smoothing:auto!important;-moz-osx-font-smoothing:auto!important;font-smooth:auto!important;letter-spacing:normal;line-height:1.6}body{-webkit-box-sizing:border-box;box-sizing:border-box;font-weight:300;color:var(--sg1);font-family:"Open Sans",Helvetica,sans-serif!important;background-color:var(--white)}strong{font-weight:600}.anchor{display:block;position:relative;z-index:-1;top:-10px}input{outline:0;-webkit-box-shadow:inset 0 0 0 0 transparent;box-shadow:inset 0 0 0 0 transparent}input[type=submit],input[type=text],textarea{-webkit-appearance:none}input[l]{font-size:inherit;outline:0;color:var(--sg1);padding-left:.4em;width:-webkit-calc(100%);width:calc(100%);border:solid 1px;display:inline-block;border-left:1px solid;-webkit-border-radius:4px;border-radius:4px;-webkit-transition:border-left .2s;-o-transition:border-left .2s;transition:border-left .2s;vertical-align:top;font-weight:400;border-color:inherit;margin-bottom:.5rem}input[l]:focus{border-left:1rem solid}input[l]:focus{width:-webkit-calc(auto);width:calc(auto)}input[plain]:valid{border-color:var(--b1)}input[plain]:focus:valid{border-color:var(--b1)}textarea{-webkit-box-shadow:inset 0 0 0 0 transparent;box-shadow:inset 0 0 0 0 transparent}textarea[l]{font-size:inherit;outline:0;color:var(--sg1);padding-left:.4em;width:-webkit-calc(100%);width:calc(100%);border:solid 1px;display:inline-block;border-left:1px solid;-webkit-border-radius:4px;border-radius:4px;-webkit-transition:border-left .2s;-o-transition:border-left .2s;transition:border-left .2s;vertical-align:top;font-weight:400;border-color:inherit;margin-bottom:.5rem}ul{padding-left:30px}li,p{font-size:1em}p{margin-bottom:.5rem}h1{font-size:2.5rem;line-height:1.8}h2{font-size:1.7rem;line-height:1.8}h3{font-size:1.4rem;line-height:1.43}h4{font-size:1.25rem}h5{font-size:1rem}h6{font-size:1rem;color:#777}h1[b]::before,h2[b]::before,h3[b]::before{content:"";height:1em;display:block;width:3px;margin-left:-.5em;margin-top:.45em;position:absolute;background-color:var(--b1)}h1[b],h2[b],h3[b]{padding-left:.5em}.logo{height:2.5rem}a{font-size:1em}a:hover{text-decoration:none}a[l]{color:var(--b2);padding-bottom:2px;position:relative;font-style:normal;cursor:pointer}a[l]:focus,a[l]:hover{text-decoration:none}a[l]::before{content:"";left:0;background-color:var(--b2);width:0%;height:1px;top:-webkit-calc(1em + 8px);top:calc(1em + 8px);position:absolute;z-index:2;-webkit-transition:background-color .2s,height .2s,top .2s,width .2s;-o-transition:background-color .2s,height .2s,top .2s,width .2s;transition:background-color .2s,height .2s,top .2s,width .2s}a[l]:focus::before,a[l]:hover::before{content:"";left:0;background-color:var(--b2);width:100%;height:1px;top:-webkit-calc(1em + 8px);top:calc(1em + 8px);position:absolute;z-index:2;-webkit-transition:background-color .2s,height .2s,top .2s,width .2s;-o-transition:background-color .2s,height .2s,top .2s,width .2s;transition:background-color .2s,height .2s,top .2s,width .2s;text-decoration:none}.navbar-brand{margin-left:10%;padding-left:15px;color:var(--white)!important}.navbar-nav{top:0}.navbar{background-color:var(--sg1);z-index:10000;padding-left:0;padding-right:0;padding-top:.75rem;padding-bottom:.75rem}.navbar-toggler{margin-right:-webkit-calc(2rem + 15px);margin-right:calc(2rem + 15px)}.nav-link{color:var(--white)!important;line-height:3.65rem}.nav-item{height:4.65rem;font-size:1.1rem;padding-left:.15rem;padding-right:.15rem;-webkit-transition:all .2s;-o-transition:all .2s;transition:all .2s;border-bottom:0 solid var(--white)}.nav-item:hover{border-bottom:.45rem solid var(--white)}.dropdown-menu{top:4.1rem;z-index:1000;border-top:none;border:none;min-width:120px;margin-left:-1px;-webkit-border-top-left-radius:0;border-top-left-radius:0;-webkit-border-top-right-radius:0;border-top-right-radius:0;-webkit-border-bottom-left-radius:.25rem;border-bottom-left-radius:.25rem;-webkit-border-bottom-right-radius:.25rem;border-bottom-right-radius:.25rem}.dropdown-menu.show{-webkit-box-shadow:0 4px 24px rgba(100,109,146,.15);box-shadow:0 4px 24px rgba(100,109,146,.15)}.dropdown-item{color:var(--sg1);background-color:var(--white);-webkit-transition:all .2s;-o-transition:all .2s;transition:all .2s;cursor:pointer}.dropdown-item:active,.dropdown-item:hover{background-color:var(--sg1);color:var(--white)!important}.dropdown-toggle::after{display:none}.dropdown a::after{-webkit-transform:rotate(-90deg);-ms-transform:rotate(-90deg);transform:rotate(-90deg);-webkit-transition:-webkit-transform .2s;transition:-webkit-transform .2s;-o-transition:transform .2s;transition:transform .2s;transition:transform .2s,-webkit-transform .2s}.dropdown.show a::after{-webkit-transform:rotate(0);-ms-transform:rotate(0);transform:rotate(0)}.navbar-nav .active{border-bottom:.45rem solid var(--white)}.navbar-nav{position:absolute;right:-webkit-calc(10% + 15px);right:calc(10% + 15px)}#language-dropdown .dropdown-menu{width:50px}footer{background-color:var(--footer2);padding-top:1rem}.page-footer{padding-bottom:2rem}.footer-contact,.footer-content,.footer-legal{width:80%;margin-left:10%;padding-top:1rem;color:var(--footer1);font-size:.8em}.footer-content a{color:var(--footer1)}.footer-content a{color:var(--footer1)}.links-list{text-align:left;list-style:none;padding:0}.content-wrapper>.links-list{padding-left:15px}.links-list-title h4{font-size:1.2em;font-weight:400}.legal-links{position:absolute;right:-webkit-calc(10% + 15px);right:calc(10% + 15px)}.legal-links a{color:var(--footer1)}.links-list li{height:2em}.legal-links a::before,.links-list li a::before{background-color:var(--footer1)}.legal-links a:hover::before,.links-list li a:hover::before{background-color:var(--footer1)}.links-list .divider{border-bottom:1px solid var(--footer1);opacity:.15;height:0;margin-bottom:.3em}.footer-divider{border-bottom:1px solid var(--footer1);width:-webkit-calc(80% - 30px);width:calc(80% - 30px);margin-left:-webkit-calc(10% + 15px);margin-left:calc(10% + 15px)}#social-media-links li{height:2rem;line-height:2rem;display:inline-block;font-size:1em}#social-media-links li:last-child::after{content:""}#social-media-links li::after{content:" | "}#social-media-links svg{margin-left:2px;margin-right:.4rem;width:20px}#social-media-links svg path{fill:var(--footer1)}#social-media-links li a::before{left:1.9rem;background-color:var(--footer1)}#social-media-links li a:focus::before,#social-media-links li a:hover::before{left:1.9rem;width:-webkit-calc(100% - 1.9rem);width:calc(100% - 1.9rem);background-color:var(--footer1)}#social-media-links ion-icon{font-size:20px;margin-right:.5rem}#social-media-links svg{font-size:20px;margin-right:.5rem}#email-subscribe-form{width:-webkit-calc(100% - 160px);width:calc(100% - 160px)}#email-subscribe-form input{width:-webkit-calc(100% - 4rem);width:calc(100% - 4rem);font-size:1.2em;outline:0;height:1.8em;color:var(--sg1);padding-left:.6em;border:none;display:inline-block;border-left:0 solid var(--b1);-webkit-border-radius:4px;border-radius:4px;-webkit-transition:border-left .2s;-o-transition:border-left .2s;transition:border-left .2s;vertical-align:top;font-weight:400}#email-subscribe-form input:focus{border-left:1rem solid var(--b1);padding-top:2px}#email-subscribe-form input:invalid,#email-subscribe-form input:invalid:focus{border-color:var(--b1)}#email-subscribe-form input.invalid-input,#email-subscribe-form input.invalid-input:focus{border-color:var(--red)}#email-subscribe-form input:valid,#email-subscribe-form input:valid:focus{border-color:var(--green)}#email-subscribe-form button{font-size:1.2em;height:1.8em;line-height:1em;float:right;width:3rem;padding:0}form{border-color:var(--b1)}form input:invalid,form input:invalid:focus{border-color:inherit}form input.invalid-input,form input.invalid-input:focus,form textarea.invalid-input,form textarea.invalid-input:focus{border-color:var(--red)}form input:valid,form input:valid:focus{border-color:var(--green)}.sub-arrow{width:1.2em;fill:var(--b1)}@media only screen and (max-width:991px){.page-footer{padding-left:20px;padding-right:20px}.footer-legal{width:100%}#legal-1{padding-left:20px}.legal-links{right:20px}.footer-content .col-xl-4,.footer-content .col-xl-8{padding-left:20px;padding-right:20px}.footer-content{width:-webkit-calc(100% + 40px);width:calc(100% + 40px)}.footer-divider{width:100%;margin-left:0}}.content-wrapper{width:80%;margin-left:10%;margin-top:6rem;margin-bottom:3rem;min-height:-webkit-calc(100vh - 187.7px - 74.45px);min-height:calc(100vh - 187.7px - 74.45px)}.section-item-title,.section-title{color:var(--b1)}.container-fluid{background-color:var(--white)}.center{left:50%;position:relative}.btn-primary{color:var(--b1);background-color:var(--white);border-color:var(--b1);-webkit-box-shadow:0 0 0 0 rgba(255,255,255,.55);box-shadow:0 0 0 0 rgba(255,255,255,.55);-webkit-transition:all .2s;-o-transition:all .2s;transition:all .2s}.btn-primary:focus,.btn-primary:hover{color:var(--b1);background-color:var(--white);border-color:var(--b1);-webkit-box-shadow:4px 4px 0 0 var(--b1t);box-shadow:4px 4px 0 0 var(--b1t);-webkit-transform:translate(-2px,-2px);-ms-transform:translate(-2px,-2px);transform:translate(-2px,-2px)}.btn-primary:active{color:var(--b1)!important;background-color:var(--white)!important;border-color:var(--b1)!important;-webkit-box-shadow:2px 2px 0 0 var(--b1t);box-shadow:2px 2px 0 0 var(--b1t);-webkit-transform:translate(-1px,-1px);-ms-transform:translate(-1px,-1px);transform:translate(-1px,-1px)}.btn-white{color:var(--b1);background-color:var(--white);-webkit-transition:all .2s;-o-transition:all .2s;transition:all .2s;-webkit-box-shadow:0 0 0 0 rgba(255,255,255,.55);box-shadow:0 0 0 0 rgba(255,255,255,.55)}.btn-white:focus,.btn-white:hover{color:var(--b1);background-color:var(--white);-webkit-box-shadow:4px 4px 0 0 rgba(255,255,255,.55);box-shadow:4px 4px 0 0 rgba(255,255,255,.55);-webkit-transform:translate(-2px,-2px);-ms-transform:translate(-2px,-2px);transform:translate(-2px,-2px)}.btn-white:active{color:var(--b1)!important;background-color:var(--white)!important;-webkit-box-shadow:2px 2px 0 0 rgba(255,255,255,.55);box-shadow:2px 2px 0 0 rgba(255,255,255,.55);-webkit-transform:translate(-1px,-1px);-ms-transform:translate(-1px,-1px);transform:translate(-1px,-1px)}.btn-filled{color:var(--white)!important;background-color:var(--b1);border-color:var(--b1);-webkit-box-shadow:0 0 0 0 rgba(255,255,255,.55);box-shadow:0 0 0 0 rgba(255,255,255,.55);-webkit-transition:all .2s;-o-transition:all .2s;transition:all .2s}.btn-filled:hover{color:var(--white)!important;background-color:var(--b1);border-color:var(--b1);-webkit-box-shadow:4px 4px 0 0 var(--b1t);box-shadow:4px 4px 0 0 var(--b1t);-webkit-transform:translate(-2px,-2px);-ms-transform:translate(-2px,-2px);transform:translate(-2px,-2px)}.btn-filled:active{color:var(--white)!important;background-color:var(--b1)!important;border-color:var(--b1)!important;-webkit-box-shadow:2px 2px 0 0 var(--b1t);box-shadow:2px 2px 0 0 var(--b1t);-webkit-transform:translate(-1px,-1px);-ms-transform:translate(-1px,-1px);transform:translate(-1px,-1px)}#popup-wrapper{display:block;position:absolute;z-index:1000;-webkit-transition:opacity .5s;-o-transition:opacity .5s;transition:opacity .5s;opacity:1}#popup-page-cover{display:none;position:fixed;height:100vh;width:100vw;top:0;left:0;background-color:rgba(131,145,174,.32);z-index:1000;-webkit-transition:opacity .5s;-o-transition:opacity .5s;transition:opacity .5s;opacity:0}#popup{position:fixed;display:none;height:auto;width:100px;z-index:1001;max-width:-webkit-calc(100% - 30px);max-width:calc(100% - 30px);background-color:var(--white);left:50%;-webkit-transform:translate(-50%,-50%);-ms-transform:translate(-50%,-50%);transform:translate(-50%,-50%);top:50%;-webkit-transition:opacity .5s;-o-transition:opacity .5s;transition:opacity .5s;opacity:0;-webkit-border-radius:.25rem;border-radius:.25rem;-webkit-box-shadow:0 12px 48px 0 rgba(0,0,0,.24);box-shadow:0 12px 48px 0 rgba(0,0,0,.24)}#close-popup{position:absolute;right:1rem;z-index:1;cursor:pointer;top:0}#close-popup svg{margin-top:4px}#close-popup::before{content:"";width:0;display:block;position:absolute;top:50%;left:50%;height:0;background-color:rgba(0,0,0,.15);-webkit-border-radius:50%;border-radius:50%;z-index:-1;cursor:pointer;-webkit-transition:all .2s;-o-transition:all .2s;transition:all .2s}#close-popup:hover::before{content:"";width:32px;display:block;position:absolute;top:10px;left:0;height:32px;background-color:rgba(0,0,0,.15);-webkit-border-radius:50%;border-radius:50%;z-index:-1}#popup-title{padding-left:1rem;background-color:var(--b1);color:var(--white);font-weight:400;font-size:1.6em;width:100%;display:block;-webkit-border-radius:.25rem .25rem 0 0;border-radius:.25rem .25rem 0 0;padding-right:60px;position:relative}#popup-title-text{line-height:1.2;display:inline-block;padding-top:9px}#popup-content{padding:1rem;display:block}#popup-title path{fill:var(--white)}.banner-content{padding-right:32px}.banner-wrapper{width:100vw;position:fixed;top:4.3rem;left:0;z-index:1000}.banner{background-color:var(--b1);width:-webkit-calc(100% - 20px);width:calc(100% - 20px);margin:auto;-webkit-border-radius:.25rem;border-radius:.25rem;padding:.5rem;color:var(--white);font-size:1.6em;margin-top:1rem;-webkit-box-shadow:0 4px 12px 0 rgba(0,0,0,.24);box-shadow:0 4px 12px 0 rgba(0,0,0,.24);opacity:1;-webkit-animation:bannerOpaque .2s;animation:bannerOpaque .2s}@-webkit-keyframes bannerOpaque{from{opacity:0}to{opacity:1}}@keyframes bannerOpaque{from{opacity:0}to{opacity:1}}.close-banner{position:absolute;right:1rem;z-index:1;cursor:pointer;-webkit-transform:translate(0,-3px);-ms-transform:translate(0,-3px);transform:translate(0,-3px)}.close-banner::before{content:"";width:0;display:block;position:absolute;margin-top:26px;left:50%;height:0;background-color:rgba(0,0,0,.15);-webkit-border-radius:50%;border-radius:50%;z-index:-1;cursor:pointer;-webkit-transition:all .2s;-o-transition:all .2s;transition:all .2s}.close-banner:hover::before{content:"";width:32px;margin-top:7px;display:block;position:absolute;left:0;height:32px;background-color:rgba(0,0,0,.15);-webkit-border-radius:50%;border-radius:50%;z-index:-1}@media only screen and (max-width:991px){.banner{font-size:1.2rem}}#globe-svg{height:60px;fill:#fefefe}#page-cover{width:100vw;top:-100vh;left:0;-webkit-transition-delay:.3s;-o-transition-delay:.3s;transition-delay:.3s;-webkit-transition:all .7s;-o-transition:all .7s;transition:all .7s;height:100vh;position:fixed;z-index:1000;background-color:rgba(54,61,75,.25)}#menu-button{border:none;outline:0}#menu-bar{-webkit-transition:all .15s;-o-transition:all .15s;transition:all .15s}#close-bar{-webkit-transition:all .15s;-o-transition:all .15s;transition:all .15s;display:none}#rect1{-webkit-transition:all .2s;-o-transition:all .2s;transition:all .2s}#rect2{-webkit-transition:all .2s;-o-transition:all .2s;transition:all .2s}#rect3{-webkit-transition:all .2s;-o-transition:all .2s;transition:all .2s}@media only screen and (max-width:991px){.content-wrapper{width:-webkit-calc(100%);width:calc(100%);left:0;padding-left:0;margin-left:0;margin-top:4.7rem}.container-fluid{padding-left:20px;padding-right:20px}.row{margin-left:-20px;margin-right:-20px}#menu-button{margin-right:20px;padding:0}.navbar-brand{margin-left:20px;padding-left:0}}.bot-logo{margin-bottom:.5rem}@media only screen and (min-width:1200px){#page-cover{display:none}.bot-logo{margin-left:15px}}@media only screen and (max-width:1199px){#globe-svg{height:60px;fill:var(--sg1)}.navbar-collapse.show{-webkit-box-shadow:0 10px 24px rgba(0,0,0,.15);box-shadow:0 10px 24px rgba(0,0,0,.15)}.nav-item:first-child{border-top:1px solid rgba(255,255,255,.35)}#menu-button{margin-right:-webkit-calc(10% + 15px);margin-right:calc(10% + 15px);padding:0}#menu-button:hover{background-color:transparent}.nav-item{height:auto;border-bottom:1px solid rgba(0,0,0,.35);padding-left:-webkit-calc(10% + 15px);padding-left:calc(10% + 15px)}.nav-link{line-height:3rem;padding:0}.nav-link{color:var(--sg1)!important}.nav-item:hover{border-bottom:1px solid rgba(0,0,0,.35)}.navbar-nav{background-color:var(--white2);margin-top:15px}.navbar-nav .active{border-bottom:1px solid rgba(0,0,0,.35)}#language-dropdown .dropdown-menu{width:-webkit-calc(80% + 4rem);width:calc(80% + 4rem);background-color:var(--white)}.dropdown-menu{border:none;margin-top:-20px}.nav-item:last-child{border-bottom:none}.dropdown-menu.show{-webkit-box-shadow:0 4px 24px rgba(100,109,146,.15);box-shadow:0 4px 24px rgba(100,109,146,.15);margin-bottom:1rem;margin-top:-.5rem}.dropdown-item{padding-left:15px;font-weight:300}.navbar-nav{position:relative;right:0}.long-form input{width:100%}}@media only screen and (max-width:991px){.nav-item{padding-left:20px;padding-right:20px}#language-dropdown{padding-left:20px}#language-dropdown .dropdown-menu{width:100%}#menu-button{margin-right:20px;padding:0}.navbar{padding-top:.25rem;padding-bottom:.25rem}.logo{height:1.8rem}.anchor{top:-55px}}@media only screen and (max-width:556px){#legal-1{width:100%}.legal-links{position:inherit;margin-left:20px;margin-bottom:1em}}@media only screen and (max-width:375px){#legal-1 p{display:block}}.lds-ring{display:inline-block;position:relative;width:18px;height:18px;padding-top:2px}#email-subscribe-form .lds-ring{padding-top:1px}.lds-ring div{-webkit-box-sizing:border-box;box-sizing:border-box;display:block;position:absolute;width:18px;height:18px;border:2px solid var(--b2);-webkit-border-radius:50%;border-radius:50%;-webkit-animation:lds-ring 1.2s cubic-bezier(.5,0,.5,1) infinite;animation:lds-ring 1.2s cubic-bezier(.5,0,.5,1) infinite;border-color:var(--b2) transparent transparent transparent}.lds-ring div:nth-child(1){-webkit-animation-delay:-.45s;animation-delay:-.45s}.lds-ring div:nth-child(2){-webkit-animation-delay:-.3s;animation-delay:-.3s}.lds-ring div:nth-child(3){-webkit-animation-delay:-.15s;animation-delay:-.15s}@-webkit-keyframes lds-ring{0%{-webkit-transform:rotate(0);transform:rotate(0)}100%{-webkit-transform:rotate(360deg);transform:rotate(360deg)}}@keyframes lds-ring{0%{-webkit-transform:rotate(0);transform:rotate(0)}100%{-webkit-transform:rotate(360deg);transform:rotate(360deg)}}#email-subscribe-form .sub-arrow{padding-top:2px}.sub-arrow{display:inline-block}.sub-load{display:none}
\ No newline at end of file
<!DOCTYPE html><html lang='cn'><head><title>文档 | 涛思数据</title><meta name='description' content='TDengine是一个开源的专为物联网、车联网、工业互联网、IT运维等设计和优化的大数据平台。除核心的快10倍以上的时序数据库功能外,还提供缓存、数据订阅、流式计算等功能,最大程度减少研发和运维的工作量。'><meta name='keywords' content='大数据,Big Data,开源,物联网,车联网,工业互联网,IT运维, 时序数据库,缓存,数据订阅,消息队列,流式计算,开源,涛思数据,TAOS Data, TDengine'><meta name='title' content='文档 | 涛思数据'><meta property='og:site_name' content='涛思数据'/><meta property='og:title' content='文档 | 涛思数据'/><meta property='og:type' content='article'/><meta property='og:url' content='https://www.taosdata.com/cn/documentation/super-table-ch/index.php'/><meta property='og:description' content='TDengine是一个开源的专为物联网、车联网、工业互联网、IT运维等设计和优化的大数据平台。除核心的快10倍以上的时序数据库功能外,还提供缓存、数据订阅、流式计算等功能,最大程度减少研发和运维的工作量。' /><link rel='canonical' href='https://www.taosdata.com/cn/documentation/super-table-ch/index.php'/><script src='../lib/jquery-3.4.1.min.js' type='application/javascript'></script><link href='../lib/bootstrap.min.css' rel='stylesheet'><link href='../styles/base.min.css' rel='stylesheet'><link rel='stylesheet' href='../lib/docs/taosdataprettify.css'><link rel='stylesheet' href='../lib/docs/docs.css'><script src='../lib/docs/prettify.js'></script><script src='../lib/docs/prettyprint-sql.js'></script></head><body><script>$('#documentation-href').addClass('active')</script><div class='container-fluid'><main class='content-wrapper'><section class='documentation'><a href='../index.html'>回去</a><h1>超级表STable:多表聚合</h1>
<p>TDengine要求每个数据采集点单独建表,这样能极大提高数据的插入/查询性能,但是导致系统中表的数量猛增,让应用对表的维护以及聚合、统计操作难度加大。为降低应用的开发难度,TDengine引入了超级表STable (Super Table)的概念。</p>
<a class='anchor' id='什么是超级表'></a><h2>什么是超级表</h2>
<p>STable是同一类型数据采集点的抽象,是同类型采集实例的集合,包含多张数据结构一样的子表。每个STable为其子表定义了表结构和一组标签:表结构即表中记录的数据列及其数据类型;标签名和数据类型由STable定义,标签值记录着每个子表的静态信息,用以对子表进行分组过滤。子表本质上就是普通的表,由一个时间戳主键和若干个数据列组成,每行记录着具体的数据,数据查询操作与普通表完全相同;但子表与普通表的区别在于每个子表从属于一张超级表,并带有一组由STable定义的标签值。每种类型的采集设备可以定义一个STable。数据模型定义表的每列数据的类型,如温度、压力、电压、电流、GPS实时位置等,而标签信息属于Meta Data,如采集设备的序列号、型号、位置等,是静态的,是表的元数据。用户在创建表(数据采集点)时指定STable(采集类型)外,还可以指定标签的值,也可事后增加或修改。</p>
<p>TDengine扩展标准SQL语法用于定义STable,使用关键词tags指定标签信息。语法如下:</p>
<pre><code class="mysql language-mysql">CREATE TABLE &lt;stable_name&gt; (&lt;field_name&gt; TIMESTAMP, field_name1 field_type,…) TAGS(tag_name tag_type, …) </code></pre>
<p>其中tag_name是标签名,tag_type是标签的数据类型。标签可以使用时间戳之外的其他TDengine支持的数据类型,标签的个数最多为6个,名字不能与系统关键词相同,也不能与其他列名相同。如:</p>
<pre><code class="mysql language-mysql">create table thermometer (ts timestamp, degree float)
tags (location binary(20), type int)</code></pre>
<p>上述SQL创建了一个名为thermometer的STable,带有标签location和标签type。</p>
<p>为某个采集点创建表时,可以指定其所属的STable以及标签的值,语法如下:</p>
<pre><code class="mysql language-mysql">CREATE TABLE &lt;tb_name&gt; USING &lt;stb_name&gt; TAGS (tag_value1,...)</code></pre>
<p>沿用上面温度计的例子,使用超级表thermometer建立单个温度计数据表的语句如下:</p>
<pre><code class="mysql language-mysql">create table t1 using thermometer tags (‘beijing', 10)</code></pre>
<p>上述SQL以thermometer为模板,创建了名为t1的表,这张表的Schema就是thermometer的Schema,但标签location值为'beijing',标签type值为10。</p>
<p>用户可以使用一个STable创建数量无上限的具有不同标签的表,从这个意义上理解,STable就是若干具有相同数据模型,不同标签的表的集合。与普通表一样,用户可以创建、删除、查看超级表STable,大部分适用于普通表的查询操作都可运用到STable上,包括各种聚合和投影选择函数。除此之外,可以设置标签的过滤条件,仅对STbale中部分表进行聚合查询,大大简化应用的开发。</p>
<p>TDengine对表的主键(时间戳)建立索引,暂时不提供针对数据模型中其他采集量(比如温度、压力值)的索引。每个数据采集点会采集若干数据记录,但每个采集点的标签仅仅是一条记录,因此数据标签在存储上没有冗余,且整体数据规模有限。TDengine将标签数据与采集的动态数据完全分离存储,而且针对STable的标签建立了高性能内存索引结构,为标签提供全方位的快速操作支持。用户可按照需求对其进行增删改查(Create,Retrieve,Update,Delete,CRUD)操作。</p>
<p>STable从属于库,一个STable只属于一个库,但一个库可以有一到多个STable, 一个STable可有多个子表。</p>
<a class='anchor' id='超级表管理'></a><h2>超级表管理</h2>
<ul>
<li><p>创建超级表</p>
<pre><code class="mysql language-mysql">CREATE TABLE &lt;stable_name&gt; (&lt;field_name&gt; TIMESTAMP, field_name1 field_type,…) TAGS(tag_name tag_type, …)</code></pre>
<p>与创建表的SQL语法相似。但需指定TAGS字段的名称和类型。 </p>
<p>说明:</p>
<ol>
<li>TAGS列总长度不能超过512 bytes;</li>
<li>TAGS列的数据类型不能是timestamp类型;</li>
<li>TAGS列名不能与其他列名相同;</li>
<li>TAGS列名不能为预留关键字. </li></ol></li>
<li><p>显示已创建的超级表</p>
<pre><code class="mysql language-mysql">show stables;</code></pre>
<p>查看数据库内全部STable,及其相关信息,包括STable的名称、创建时间、列数量、标签(TAG)数量、通过该STable建表的数量。 </p></li>
<li><p>删除超级表</p>
<pre><code class="mysql language-mysql">DROP TABLE &lt;stable_name&gt;</code></pre>
<p>Note: 删除STable时,所有通过该STable创建的表都将被删除。</p></li>
<li><p>查看属于某STable并满足查询条件的表</p>
<pre><code class="mysql language-mysql">SELECT TBNAME,[TAG_NAME,…] FROM &lt;stable_name&gt; WHERE &lt;tag_name&gt; &lt;[=|=&lt;|&gt;=|&lt;&gt;] values..&gt; ([AND|OR] …)</code></pre>
<p>查看属于某STable并满足查询条件的表。说明:TBNAME为关键词,显示通过STable建立的子表表名,查询过程中可以使用针对标签的条件。</p>
<pre><code class="mysql language-mysql">SELECT COUNT(TBNAME) FROM &lt;stable_name&gt; WHERE &lt;tag_name&gt; &lt;[=|=&lt;|&gt;=|&lt;&gt;] values..&gt; ([AND|OR] …)</code></pre>
<p>统计属于某个STable并满足查询条件的子表的数量</p></li>
</ul>
<a class='anchor' id='写数据时自动建子表'></a><h2>写数据时自动建子表</h2>
<p>在某些特殊场景中,用户在写数据时并不确定某个设备的表是否存在,此时可使用自动建表语法来实现写入数据时用超级表定义的表结构自动创建不存在的子表,若该表已存在则不会建立新表。注意:自动建表语句只能自动建立子表而不能建立超级表,这就要求超级表已经被事先定义好。自动建表语法跟insert/import语法非常相似,唯一区别是语句中增加了超级表和标签信息。具体语法如下:</p>
<pre><code class="mysql language-mysql">INSERT INTO &lt;tb_name&gt; USING &lt;stb_name&gt; TAGS (&lt;tag1_value&gt;, ...) VALUES (field_value, ...) (field_value, ...) ...;</code></pre>
<p>向表tb_name中插入一条或多条记录,如果tb_name这张表不存在,则会用超级表stb_name定义的表结构以及用户指定的标签值(即tag1_value…)来创建名为tb_name新表,并将用户指定的值写入表中。如果tb_name已经存在,则建表过程会被忽略,系统也不会检查tb_name的标签是否与用户指定的标签值一致,也即不会更新已存在表的标签。</p>
<pre><code class="mysql language-mysql">INSERT INTO &lt;tb1_name&gt; USING &lt;stb1_name&gt; TAGS (&lt;tag1_value1&gt;, ...) VALUES (&lt;field1_value1&gt;, ...) (&lt;field1_value2&gt;, ...) ... &lt;tb_name2&gt; USING &lt;stb_name2&gt; TAGS(&lt;tag1_value2&gt;, ...) VALUES (&lt;field1_value1&gt;, ...) ...;</code></pre>
<p>向多张表tb1_name,tb2_name等插入一条或多条记录,并分别指定各自的超级表进行自动建表。</p>
<a class='anchor' id='STable中TAG管理'></a><h2>STable中TAG管理</h2>
<p>除了更新标签的值的操作是针对子表进行,其他所有的标签操作(添加标签、删除标签等)均只能作用于STable,不能对单个子表操作。对STable添加标签以后,依托于该STable建立的所有表将自动增加了一个标签,对于数值型的标签,新增加的标签的默认值是0.</p>
<ul>
<li><p>添加新的标签</p>
<pre><code class="mysql language-mysql">ALTER TABLE &lt;stable_name&gt; ADD TAG &lt;new_tag_name&gt; &lt;TYPE&gt;</code></pre>
<p>为STable增加一个新的标签,并指定新标签的类型。标签总数不能超过6个。</p></li>
<li><p>删除标签</p>
<pre><code class="mysql language-mysql">ALTER TABLE &lt;stable_name&gt; DROP TAG &lt;tag_name&gt;</code></pre>
<p>删除超级表的一个标签,从超级表删除某个标签后,该超级表下的所有子表也会自动删除该标签。</p>
<p>说明:第一列标签不能删除,至少需要为STable保留一个标签。</p></li>
<li><p>修改标签名</p>
<pre><code class="mysql language-mysql">ALTER TABLE &lt;stable_name&gt; CHANGE TAG &lt;old_tag_name&gt; &lt;new_tag_name&gt;</code></pre>
<p>修改超级表的标签名,从超级表修改某个标签名后,该超级表下的所有子表也会自动更新该标签名。</p></li>
<li><p>修改子表的标签值</p>
<pre><code class="mysql language-mysql">ALTER TABLE &lt;table_name&gt; SET TAG &lt;tag_name&gt;=&lt;new_tag_value&gt;</code></pre></li>
</ul>
<a class='anchor' id='STable多表聚合'></a><h2>STable多表聚合</h2>
<p>针对所有的通过STable创建的子表进行多表聚合查询,支持按照全部的TAG值进行条件过滤,并可将结果按照TAGS中的值进行聚合,暂不支持针对binary类型的模糊匹配过滤。语法如下:</p>
<pre><code class="mysql language-mysql">SELECT function&lt;field_name&gt;,…
FROM &lt;stable_name&gt;
WHERE &lt;tag_name&gt; &lt;[=|&lt;=|&gt;=|&lt;&gt;] values..&gt; ([AND|OR] …)
INTERVAL (&lt;time range&gt;)
GROUP BY &lt;tag_name&gt;, &lt;tag_name&gt;
ORDER BY &lt;tag_name&gt; &lt;asc|desc&gt;
SLIMIT &lt;group_limit&gt;
SOFFSET &lt;group_offset&gt;
LIMIT &lt;record_limit&gt;
OFFSET &lt;record_offset&gt;</code></pre>
<p><strong>说明</strong></p>
<p>超级表聚合查询,TDengine目前支持以下聚合\选择函数:sum、count、avg、first、last、min、max、top、bottom,以及针对全部或部分列的投影操作,使用方式与单表查询的计算过程相同。暂不支持其他类型的聚合计算和四则运算。当前所有的函数及计算过程均不支持嵌套的方式进行执行。</p>
<p>不使用GROUP BY的查询将会对超级表下所有满足筛选条件的表按时间进行聚合,结果输出默认是按照时间戳单调递增输出,用户可以使用ORDER BY _c0 ASC|DESC选择查询结果时间戳的升降排序;使用GROUP BY <tag_name> 的聚合查询会按照tags进行分组,并对每个组内的数据分别进行聚合,输出结果为各个组的聚合结果,组间的排序可以由ORDER BY <tag_name> 语句指定,每个分组内部,时间序列是单调递增的。 </p>
<p>使用SLIMIT/SOFFSET语句指定组间分页,即指定结果集中输出的最大组数以及对组起始的位置。使用LIMIT/OFFSET语句指定组内分页,即指定结果集中每个组内最多输出多少条记录以及记录起始的位置。</p>
<a class='anchor' id='STable使用示例'></a><h2>STable使用示例</h2>
<p>以温度传感器采集时序数据作为例,示范STable的使用。 在这个例子中,对每个温度计都会建立一张表,表名为温度计的ID,温度计读数的时刻记为ts,采集的值记为degree。通过tags给每个采集器打上不同的标签,其中记录温度计的地区和类型,以方便我们后面的查询。所有温度计的采集量都一样,因此我们用STable来定义表结构。</p>
<a class='anchor' id='定义STable表结构并使用它创建子表'></a><h3>定义STable表结构并使用它创建子表</h3>
<p>创建STable语句如下:</p>
<pre><code class="mysql language-mysql">CREATE TABLE thermometer (ts timestamp, degree double)
TAGS(location binary(20), type int)</code></pre>
<p>假设有北京,天津和上海三个地区的采集器共4个,温度采集器有3种类型,我们就可以对每个采集器建表如下: </p>
<pre><code class="mysql language-mysql">CREATE TABLE therm1 USING thermometer TAGS ('beijing', 1);
CREATE TABLE therm2 USING thermometer TAGS ('beijing', 2);
CREATE TABLE therm3 USING thermometer TAGS ('tianjin', 1);
CREATE TABLE therm4 USING thermometer TAGS ('shanghai', 3);</code></pre>
<p>其中therm1,therm2,therm3,therm4是超级表thermometer四个具体的子表,也即普通的Table。以therm1为例,它表示采集器therm1的数据,表结构完全由thermometer定义,标签location=”beijing”, type=1表示therm1的地区是北京,类型是第1类的温度计。</p>
<a class='anchor' id='写入数据'></a><h3>写入数据</h3>
<p>注意,写入数据时不能直接对STable操作,而是要对每张子表进行操作。我们分别向四张表therm1,therm2, therm3, therm4写入一条数据,写入语句如下:</p>
<pre><code class="mysql language-mysql">INSERT INTO therm1 VALUES ('2018-01-01 00:00:00.000', 20);
INSERT INTO therm2 VALUES ('2018-01-01 00:00:00.000', 21);
INSERT INTO therm3 VALUES ('2018-01-01 00:00:00.000', 24);
INSERT INTO therm4 VALUES ('2018-01-01 00:00:00.000', 23);</code></pre>
<a class='anchor' id='按标签聚合查询'></a><h3>按标签聚合查询</h3>
<p>查询位于北京(beijing)和天津(tianjing)两个地区的温度传感器采样值的数量count(*)、平均温度avg(degree)、最高温度max(degree)、最低温度min(degree),并将结果按所处地域(location)和传感器类型(type)进行聚合。</p>
<pre><code class="mysql language-mysql">SELECT COUNT(*), AVG(degree), MAX(degree), MIN(degree)
FROM thermometer
WHERE location='beijing' or location='tianjin'
GROUP BY location, type </code></pre>
<a class='anchor' id='按时间周期聚合查询'></a><h3>按时间周期聚合查询</h3>
<p>查询仅位于北京以外地区的温度传感器最近24小时(24h)采样值的数量count(*)、平均温度avg(degree)、最高温度max(degree)和最低温度min(degree),将采集结果按照10分钟为周期进行聚合,并将结果按所处地域(location)和传感器类型(type)再次进行聚合。</p>
<pre><code class="mysql language-mysql">SELECT COUNT(*), AVG(degree), MAX(degree), MIN(degree)
FROM thermometer
WHERE location&lt;&gt;'beijing' and ts&gt;=now-1d
INTERVAL(10M)
GROUP BY location, type</code></pre><a href='../index.html'>回去</a></section></main></div><?php include($s.'/footer.php'); ?><script>$('pre').addClass('prettyprint linenums');PR.prettyPrint()</script><script src='lib/docs/liner.js'></script></body></html>
此差异已折叠。
此差异已折叠。
/*JS to determine how many lines used in pre/code block, sets CSS appropriately. MUST be placed after elements with prettyprint class are loaded*/
$('.prettyprint').toArray().forEach(function(element){
let linenums = element.clientHeight / 25.2;
if (linenums > 99) {
$(element).addClass('threec');
}
else if (linenums > 9) {
$(element).addClass('twoc');
}
});
$('.prettyprint').toArray().forEach(function(element){
let linenums = element.clientHeight / 25.2;
if (linenums > 99) {
$(element).addClass('threec');
}
else if (linenums > 9) {
$(element).addClass('twoc');
}
});
\ No newline at end of file
PR['registerLangHandler'](
PR['createSimpleLexer'](
[
// A comment is either a line comment that starts with two dashes, or
// two dashes preceding a long bracketed block.
[PR['TAOSDATA_TERMINAL'], /^(*?)/]
]
),
['terminal','term']);
\ No newline at end of file
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册