diff --git a/documentation20/webdocs/markdowndocs/Evaluation-ch.md b/documentation20/webdocs/markdowndocs/Evaluation-ch.md
index 7d09d0dd33a332d4b74dd16bd64cb4e9503fd07d..9e7e0ec6aa8b60bfa9dbe603a45a265a1d1eba00 100644
--- a/documentation20/webdocs/markdowndocs/Evaluation-ch.md
+++ b/documentation20/webdocs/markdowndocs/Evaluation-ch.md
@@ -11,7 +11,7 @@ TDengine的模块之一是时序数据库。但除此之外,为减少研发的
* __全栈时序数据处理引擎__:将数据库、消息队列、缓存、流式计算等功能融为一体,应用无需再集成Kafka/Redis/HBase/Spark/HDFS等软件,大幅降低应用开发和维护的复杂度成本。
* __强大的分析功能__:无论是十年前还是一秒钟前的数据,指定时间范围即可查询。数据可在时间轴上或多个设备上进行聚合。即席查询可通过Shell, Python, R, Matlab随时进行。
* __与第三方工具无缝连接__:不用一行代码,即可与Telegraf, Grafana, EMQ, Prometheus, Matlab, R等集成。后续将支持OPC, Hadoop, Spark等, BI工具也将无缝连接。
-* __零运维成本、零学习成本__:安装、集群一秒搞定,无需分库分表,实时备份。标准SQL,支持JDBC, RESTful, 支持Python/Java/C/C++/Go, 与MySQL相似,零学习成本。
+* __零运维成本、零学习成本__:安装集群简单快捷,无需分库分表,实时备份。类似标准SQL,支持RESTful, 支持Python/Java/C/C++/C#/Go/Node.js, 与MySQL相似,零学习成本。
采用TDengine,可将典型的物联网、车联网、工业互联网大数据平台的总拥有成本大幅降低。但需要指出的是,因充分利用了物联网时序数据的特点,它无法用来处理网络爬虫、微博、微信、电商、ERP、CRM等通用型数据。
diff --git a/documentation20/webdocs/markdowndocs/Getting Started-ch.md b/documentation20/webdocs/markdowndocs/Getting Started-ch.md
index 0e751d8cd59603ddaf85330b0fe309f4373e5c09..beb0c639ae7f5d6b5535b194f70d806305208492 100644
--- a/documentation20/webdocs/markdowndocs/Getting Started-ch.md
+++ b/documentation20/webdocs/markdowndocs/Getting Started-ch.md
@@ -30,13 +30,13 @@ TDengine软件分为服务器、客户端和报警模块三部分,目前2.0版
- TDengine-alert-2.0.0-Linux-x64.tar.gz (8.1M)
-目前,TDengine只支持在使用[`systemd`](https://en.wikipedia.org/wiki/Systemd)做进程服务管理的linux系统上安装。其他linux系统的支持正在开发中。用`which`命令来检测系统中是否存在`systemd`:
+目前,TDengine只支持在使用[`systemd`](https://en.wikipedia.org/wiki/Systemd)做进程服务管理的linux系统上安装。其他linux系统的支持正在开发中。用`which systemctl`命令来检测系统中是否存在`systemd`包:
```cmd
-which systemd
+which systemctl
```
-如果系统中不存在`systemd`命令,请考虑[通过源码安装](#通过源码安装)TDengine。
+如果系统中不存在`systemd`包,请考虑[通过源码安装](#通过源码安装)TDengine。
具体的安装过程,请参见TDengine多种安装包的安装和卸载。
diff --git a/documentation20/webdocs/markdowndocs/Getting Started.md b/documentation20/webdocs/markdowndocs/Getting Started.md
index 00d97d3d9cd3d2ce8317938eb9e46ae74b48dab1..4d34cb49f4a84ac6c9d63e47bc8230c150b9013e 100644
--- a/documentation20/webdocs/markdowndocs/Getting Started.md
+++ b/documentation20/webdocs/markdowndocs/Getting Started.md
@@ -16,13 +16,13 @@ Three different packages are provided, please pick up the one you like.
TDengine DEB package (1.7M)
TDengine Tarball (3.0M)
-For the time being, TDengine only supports installation on Linux systems using [`systemd`](https://en.wikipedia.org/wiki/Systemd) as the service manager. To check if your system has *systemd*, use the _which_ command.
+For the time being, TDengine only supports installation on Linux systems using [`systemd`](https://en.wikipedia.org/wiki/Systemd) as the service manager. To check if your system has *systemd* package, use the _which systemctl_ command.
```cmd
-which systemd
+which systemctl
```
-If the `systemd` command is not found, please [install from source code](#Install-from-Source).
+If the `systemd` package is not found, please [install from source code](#Install-from-Source).
### Running TDengine
diff --git a/documentation20/webdocs/markdowndocs/Queries-ch.md b/documentation20/webdocs/markdowndocs/Queries-ch.md
index 1394338f5420d9b2e2dbc2206879ac36a5c52cf8..97383c78f7b51d1a99c7452593971ba7db48e204 100644
--- a/documentation20/webdocs/markdowndocs/Queries-ch.md
+++ b/documentation20/webdocs/markdowndocs/Queries-ch.md
@@ -29,23 +29,9 @@ Query OK, 2 row(s) in set (0.001100s)
具体的查询语法请看TAOS SQL 。
## 多表聚合查询
+物联网场景中,往往同一个类型的数据采集点有多个。TDengine采用超级表(STable)的概念来描述某一个类型的数据采集点,一张普通的表来描述一个具体的数据采集点。同时TDengine使用标签来描述数据采集点的静态属性,一个具体的数据采集点有具体的标签值。通过指定标签的过滤条件,TDengine提供了一高效的方法将超级表(某一类型的数据采集点)所属的子表进行聚合查询。对普通表的聚合函数以及绝大部分操作都适用于超级表,语法完全一样。
-TDengine对每个数据采集点单独建表,但在实际应用中经常需要对不同的采集点数据进行聚合。为高效的进行聚合操作,TDengine引入超级表(STable)的概念。超级表用来代表一特定类型的数据采集点,它是包含多张表的表集合,集合里每张表的模式(schema)完全一致,但每张表都带有自己的静态标签,标签可以多个,可以随时增加、删除和修改。
-
-应用可通过指定标签的过滤条件,对一个STable下的全部或部分表进行聚合或统计操作,这样大大简化应用的开发。其具体流程如下图所示:
-
-
-
- 多表聚合查询原理图
-
-1:应用将一个查询条件发往系统;2: taosc将超级表的名字发往 Meta Node(管理节点);3:管理节点将超级表所拥有的 vnode 列表发回 taosc;4:taosc将计算的请求连同标签过滤条件发往这些vnode对应的多个数据节点;5:每个vnode先在内存里查找出自己节点里符合标签过滤条件的表的集合,然后扫描存储的时序数据,完成相应的聚合计算,将结果返回给taosc;6:taosc将多个数据节点返回的结果做最后的聚合,将其返回给应用。
-
-由于TDengine在vnode内将标签数据与时序数据分离存储,通过先在内存里过滤标签数据,将需要扫描的数据集大幅减少,大幅提升聚合计算速度。同时,由于数据分布在多个vnode/dnode,聚合计算操作在多个vnode里并发进行,又进一步提升了聚合的速度。
-
-对普通表的聚合函数以及绝大部分操作都适用于超级表,语法完全一样,细节请看 TAOS SQL。
-
-比如:在TAOS Shell,查找所有智能电表采集的电压平均值,并按照location分组
-
+**示例1**:在TAOS Shell,查找北京所有智能电表采集的电压平均值,并按照location分组
```mysql
taos> SELECT AVG(voltage) FROM meters GROUP BY location;
avg(voltage) | location |
@@ -55,6 +41,18 @@ taos> SELECT AVG(voltage) FROM meters GROUP BY location;
Query OK, 2 row(s) in set (0.002136s)
```
+**示例2**:在TAOS shell, 查找groupId为2的所有智能电表过去24小时的记录条数,电流的最大值
+
+```mysql
+taos> SELECT count(*), max(current) FROM meters where groupId = 2 and ts > now - 24h;
+ cunt(*) | max(current) |
+==================================
+ 5 | 13.4 |
+Query OK, 1 row(s) in set (0.002136s)
+```
+
+TDengine仅容许对属于同一个超级表的表之间进行聚合查询,不同超级表之间的聚合查询不支持。在TAOS SQL 一章,查询类操作都会注明是否支持超级表。
+
## 降采样查询、插值
物联网场景里,经常需要通过降采样(down sampling)将采集的数据按时间段进行聚合。TDengine 提供了一个简便的关键词 interval 让按照时间窗口的查询操作变得极为简单。比如,将智能电表 d1001 采集的电流值每10秒钟求和
@@ -66,9 +64,9 @@ taos> SELECT sum(current) FROM d1001 INTERVAL(10s);
2018-10-03 14:38:10.000 | 24.900000572 |
Query OK, 2 row(s) in set (0.000883s)
```
-降采样操作也适用于超级表,比如:将所有智能电表采集的电流值每秒钟求和
+降采样操作也适用于超级表,比如:将北京所有智能电表采集的电流值每秒钟求和
```mysql
-taos> SELECT SUM(current) FROM meters INTERVAL(1s);
+taos> SELECT SUM(current) FROM meters where location like "Beijing%" INTERVAL(1s);
ts | sum(current) |
======================================================
2018-10-03 14:38:04.000 | 10.199999809 |
diff --git a/documentation20/webdocs/markdowndocs/TAOS SQL-ch.md b/documentation20/webdocs/markdowndocs/TAOS SQL-ch.md
index 66d17c6aa686a7ed07ff1b865000f7b4a43f3834..4082d72f112e8ff62d2e8b2c8b15391dd6f39d8a 100644
--- a/documentation20/webdocs/markdowndocs/TAOS SQL-ch.md
+++ b/documentation20/webdocs/markdowndocs/TAOS SQL-ch.md
@@ -124,7 +124,8 @@ TDengine缺省的时间戳是毫秒精度,但通过修改配置参数enableMic
说明:
1) 表的第一个字段必须是TIMESTAMP,并且系统自动将其设为主键;
2) 表名最大长度为193;
- 3) 表的每行长度不能超过16k个字符;
+ 3) 表的每行长度不能超过16k个字符;
+ 4) 子表名只能由字母、数字和下划线组成,且不能以数字开头
5) 使用数据类型binary或nchar,需指定其最长的字节数,如binary(20),表示20字节;
- **删除数据表**
diff --git a/documentation20/webdocs/markdowndocs/architecture-ch.md b/documentation20/webdocs/markdowndocs/architecture-ch.md
index c7f3eba9efa7ff34cafef9b52b32dec5b113da60..ba45bc4796e6f0fb544f7383f74528ee486d94e5 100644
--- a/documentation20/webdocs/markdowndocs/architecture-ch.md
+++ b/documentation20/webdocs/markdowndocs/architecture-ch.md
@@ -65,24 +65,24 @@ TDengine 的设计是基于单个硬件、软件系统不可靠,基于任何
TDengine 分布式架构的逻辑结构图如下:
图 1 TDengine架构示意图
-一个完整的 TDengine 系统是运行在一到多个物理节点上的,逻辑上,它包含数据节点(dnode)、TDengine客户端(taosc)以及应用(app)。系统中存在一到多个数据节点,这些数据节点组成一个集群(cluster)。应用通过taosc的API与TDengine集群进行互动。下面对每个逻辑单元进行简要介绍。
+一个完整的 TDengine 系统是运行在一到多个物理节点上的,逻辑上,它包含数据节点(dnode)、TDengine应用驱动(taosc)以及应用(app)。系统中存在一到多个数据节点,这些数据节点组成一个集群(cluster)。应用通过taosc的API与TDengine集群进行互动。下面对每个逻辑单元进行简要介绍。
-**物理节点(pnode):** pnode是一独立运行、拥有自己的计算、存储和网络能力的计算机,可以是安装有OS的物理机、虚拟机或容器。物理节点由其配置的 FQDN(Fully Qualified Domain Name)来标识。TDengine完全依赖FQDN来进行网络通讯,如果不了解FQDN,请看博文《[一篇文章说清楚TDengine的FQDN](https://www.taosdata.com/blog/2020/09/11/1824.html)》。
+**物理节点(pnode):** pnode是一独立运行、拥有自己的计算、存储和网络能力的计算机,可以是安装有OS的物理机、虚拟机或Docker容器。物理节点由其配置的 FQDN(Fully Qualified Domain Name)来标识。TDengine完全依赖FQDN来进行网络通讯,如果不了解FQDN,请看博文《[一篇文章说清楚TDengine的FQDN](https://www.taosdata.com/blog/2020/09/11/1824.html)》。
**数据节点(dnode):** dnode 是 TDengine 服务器侧执行代码 taosd 在物理节点上的一个运行实例,一个工作的系统必须有至少一个数据节点。dnode包含零到多个逻辑的虚拟节点(VNODE),零或者至多一个逻辑的管理节点(mnode)。dnode在系统中的唯一标识由实例的End Point (EP )决定。EP是dnode所在物理节点的FQDN (Fully Qualified Domain Name)和系统所配置的网络端口号(Port)的组合。通过配置不同的端口,一个物理节点(一台物理机、虚拟机或容器)可以运行多个实例,或有多个数据节点。
-**虚拟节点(vnode)**: 为更好的支持数据分片、负载均衡,防止数据过热或倾斜,数据节点被虚拟化成多个虚拟节点(vnode,图中V2, V3, V4等)。每个 vnode 都是一个相对独立的工作单元,是时序数据存储的基本单元,具有独立的运行线程、内存空间与持久化存储的路径。一个 vnode 包含一定数量的表(数据采集点)。当创建一张新表时,系统会检查是否需要创建新的 vnode。一个数据节点上能创建的 vnode 的数量取决于该数据节点所在物理节点的硬件资源。一个 vnode 只属于一个DB,但一个DB可以有多个 vnode。一个 vnode 除存储的时序数据外,也保存有所包含的表的SCHEMA、标签值等。一个虚拟节点由所属的数据节点的EP,以及所属的VGroup ID在系统内唯一标识,由管理节点创建并管理。
+**虚拟节点(vnode)**: 为更好的支持数据分片、负载均衡,防止数据过热或倾斜,数据节点被虚拟化成多个虚拟节点(vnode,图中V2, V3, V4等)。每个 vnode 都是一个相对独立的工作单元,是时序数据存储的基本单元,具有独立的运行线程、内存空间与持久化存储的路径。一个 vnode 包含一定数量的表(数据采集点)。当创建一张新表时,系统会检查是否需要创建新的 vnode。一个数据节点上能创建的 vnode 的数量取决于该数据节点所在物理节点的硬件资源。一个 vnode 只属于一个DB,但一个DB可以有多个 vnode。一个 vnode 除存储的时序数据外,也保存有所包含的表的schema、标签值等。一个虚拟节点由所属的数据节点的EP,以及所属的VGroup ID在系统内唯一标识,由管理节点创建并管理。
**管理节点(mnode):** 一个虚拟的逻辑单元,负责所有数据节点运行状态的监控和维护,以及节点之间的负载均衡(图中M)。同时,管理节点也负责元数据(包括用户、数据库、表、静态标签等)的存储和管理,因此也称为 Meta Node。TDengine 集群中可配置多个(最多不超过5个) mnode,它们自动构建成为一个虚拟管理节点组(图中M0, M1, M2)。mnode 间采用 master/slave 的机制进行管理,而且采取强一致方式进行数据同步, 任何数据更新操作只能在 Master 上进行。mnode 集群的创建由系统自动完成,无需人工干预。每个dnode上至多有一个mnode,由所属的数据节点的EP来唯一标识。每个dnode通过内部消息交互自动获取整个集群中所有 mnode 所在的 dnode 的EP。
**虚拟节点组(VGroup):** 不同数据节点上的 vnode 可以组成一个虚拟节点组(vnode group)来保证系统的高可靠。虚拟节点组内采取master/slave的方式进行管理。写操作只能在 master vnode 上进行,系统采用异步复制的方式将数据同步到 slave vnode,这样确保了一份数据在多个物理节点上有拷贝。一个 vgroup 里虚拟节点个数就是数据的副本数。如果一个DB的副本数为N,系统必须有至少N个数据节点。副本数在创建DB时通过参数 replica 可以指定,缺省为1。使用 TDengine 的多副本特性,可以不再需要昂贵的磁盘阵列等存储设备,就可以获得同样的数据高可靠性。虚拟节点组由管理节点创建、管理,并且由管理节点分配一个系统唯一的ID,VGroup ID。如果两个虚拟节点的vnode group ID相同,说明他们属于同一个组,数据互为备份。虚拟节点组里虚拟节点的个数是可以动态改变的,容许只有一个,也就是没有数据复制。VGroup ID是永远不变的,即使一个虚拟节点组被删除,它的ID也不会被收回重复利用。
-**TAOSC:** taosc是TDengine给应用提供的驱动程序(driver),负责处理应用与集群的接口交互,内嵌于JDBC、ODBC driver中,或者C、Python、Go语言连接库里。应用都是通过taosc而不是直接连接集群中的数据节点与整个集群进行交互的。这个模块负责获取并缓存元数据;将插入、查询等请求转发到正确的数据节点;在把结果返回给应用时,还需要负责最后一级的聚合、排序、过滤等操作。对于JDBC, ODBC, C/C++接口而言,这个模块是在应用所处的物理节点上运行,但消耗的资源很小。同时,为支持全分布式的RESTful接口,taosc在TDengine集群的每个dnode上都有一运行实例。
+**TAOSC:** taosc是TDengine给应用提供的驱动程序(driver),负责处理应用与集群的接口交互,提供C/C++语言原生接口,内嵌于JDBC、C#、Python、Go、Node.js语言连接库里。应用都是通过taosc而不是直接连接集群中的数据节点与整个集群进行交互的。这个模块负责获取并缓存元数据;将插入、查询等请求转发到正确的数据节点;在把结果返回给应用时,还需要负责最后一级的聚合、排序、过滤等操作。对于JDBC, C/C++/C#/Python/Go/Node.js接口而言,这个模块是在应用所处的物理节点上运行。同时,为支持全分布式的RESTful接口,taosc在TDengine集群的每个dnode上都有一运行实例。
### 节点之间的通讯
-**通讯方式:**TDengine系统的各个节点之间的通讯是通过TCP/UDP进行的。因为考虑到物联网场景,数据写入的包一般不大,因此TDengine 除采用TCP做传输之外,还采用UDP方式,因为UDP 更加高效,而且不受连接数的限制。TDengine实现了自己的超时、重传、确认等机制,以确保UDP的可靠传输。对于数据量不到15K的数据包,采取UDP的方式进行传输,超过15K的,或者是查询类的操作,自动采取TCP的方式进行传输。同时,TDengine根据配置和数据包,会自动对数据进行压缩/解压缩,数字签名/认证等处理。对于数据节点之间的数据复制,只采用TCP方式进行数据传输。
+**通讯方式:**TDengine系统的各个数据节点之间,以及应用驱动与各数据节点之间的通讯是通过TCP/UDP进行的。因为考虑到物联网场景,数据写入的包一般不大,因此TDengine 除采用TCP做传输之外,还采用UDP方式,因为UDP 更加高效,而且不受连接数的限制。TDengine实现了自己的超时、重传、确认等机制,以确保UDP的可靠传输。对于数据量不到15K的数据包,采取UDP的方式进行传输,超过15K的,或者是查询类的操作,自动采取TCP的方式进行传输。同时,TDengine根据配置和数据包,会自动对数据进行压缩/解压缩,数字签名/认证等处理。对于数据节点之间的数据复制,只采用TCP方式进行数据传输。
-**FQDN配置**:一个数据节点有一个或多个FQDN,可以在系统配置文件taos.cfg通过参数“fqdn"进行指定,如果没有指定,系统将自动获取FQDN。如果节点没有配置FQDN,可以直接将该节点的配置参数fqdn设置为它的IP地址。但不建议使用IP,因为IP地址可变,一旦变化,将让集群无法正常工作。一个数据节点的EP(End Point)由FQDN + Port组成。采用FQDN,需要保证DNS服务正常工作,或者在节点以及应用所在的节点配置好hosts文件。
+**FQDN配置**:一个数据节点有一个或多个FQDN,可以在系统配置文件taos.cfg通过参数“fqdn"进行指定,如果没有指定,系统将自动获取计算机的hostname作为其FQDN。如果节点没有配置FQDN,可以直接将该节点的配置参数fqdn设置为它的IP地址。但不建议使用IP,因为IP地址可变,一旦变化,将让集群无法正常工作。一个数据节点的EP(End Point)由FQDN + Port组成。采用FQDN,需要保证DNS服务正常工作,或者在节点以及应用所在的节点配置好hosts文件。
**端口配置:**一个数据节点对外的端口由TDengine的系统配置参数serverPort决定,对集群内部通讯的端口是serverPort+5。集群内数据节点之间的数据复制操作还占有一个TCP端口,是serverPort+10. 为支持多线程高效的处理UDP数据,每个对内和对外的UDP连接,都需要占用5个连续的端口。因此一个数据节点总的端口范围为serverPort到serverPort + 10,总共11个TCP/UDP端口。使用时,需要确保防火墙将这些端口打开。每个数据节点可以配置不同的serverPort。
@@ -153,6 +153,7 @@ TDengine除vnode分片之外,还对时序数据按照时间段进行分区。
当新的数据节点被添加进集群,因为新的计算和存储被添加进来,系统也将自动启动负载均衡流程。
负载均衡过程无需任何人工干预,应用也无需重启,将自动连接新的节点,完全透明。
+**提示:负载均衡由参数balance控制,决定开启/关闭自动负载均衡。**
## 数据写入与复制流程
如果一个数据库有N个副本,那一个虚拟节点组就有N个虚拟节点,但是只有一个是Master,其他都是slave。当应用将新的记录写入系统时,只有Master vnode能接受写的请求。如果slave vnode收到写的请求,系统将通知taosc需要重新定向。
@@ -192,7 +193,8 @@ Master Vnode遵循下面的写入流程:
理论上,只要是异步复制,就无法保证100%不丢失。但是这个窗口极小,mater与slave要同时发生故障,而且发生在刚给应用确认写入成功之后。
-注:异地容灾、IDC无中断迁移,仅仅企业版支持
+注:异地容灾、IDC无中断迁移,仅仅企业版支持。
+**提示:该功能暂未提供**
### 主从选择
Vnode会保持一个数据版本号(Version),对内存数据进行持久化存储时,对该版本号也进行持久化存储。每个数据更新操作,无论是采集的时序数据还是元数据,这个版本号将增一。
@@ -259,6 +261,7 @@ dataDir /mnt/disk6/taos 2
挂载的盘也可以是非本地的网络盘,只要系统能访问即可。
注:多级存储功能仅企业版支持
+**提示:该功能暂未提供**
## 数据查询
TDengine提供了多种多样针对表和超级表的查询处理功能,除了常规的聚合查询之外,还提供针对时序数据的窗口查询、统计聚合等功能。TDengine的查询处理需要客户端、vnode, mnode节点协同完成。
@@ -289,11 +292,18 @@ select count(*) from d1001 interval(1h) fill(prev);
针对d1001设备采集数据统计每小时记录数,如果某一个小时不存在数据,这返回之前一个小时的统计数据。TDengine提供前向插值(prev)、线性插值(linear)、NULL值填充(NULL)、特定值填充(value)。
### 多表聚合查询
-多表聚合查询与单表查询的整体流程相同,但是存在如下的差异:
-
-- 由于多表可能分布在不同的节点(dnode),因此多表的聚合查询需要首先获得表所在的全部数据节点的信息,并且同时向相关的dnode发出查询请求。
-- 每个vnode的计算获得的中间结果(partial results)需要进行第二阶段的聚合才能形成最终结果,第二阶段的聚合过程在客户端完成。
-- 由于表标签信息存储在vnode中,因此针对标签信息的查询也需要vnode完成。客户端将标签的过滤表达式封装在查询请求结构体中发送给vnode,由vnode的查询执行线程从中抽取出标签查询条件,然后执行查询。标签查询与过滤是在针对表的查询之前完成。标签查询完成以后,将符合条件的表纳入到接下来的查询处理流程中。
+TDengine对每个数据采集点单独建表,但在实际应用中经常需要对不同的采集点数据进行聚合。为高效的进行聚合操作,TDengine引入超级表(STable)的概念。超级表用来代表一特定类型的数据采集点,它是包含多张表的表集合,集合里每张表的模式(schema)完全一致,但每张表都带有自己的静态标签,标签可以多个,可以随时增加、删除和修改。 应用可通过指定标签的过滤条件,对一个STable下的全部或部分表进行聚合或统计操作,这样大大简化应用的开发。其具体流程如下图所示:
+
+
+ 图 5 多表聚合查询原理图
+1:应用将一个查询条件发往系统;
+2: taosc将超级表的名字发往 Meta Node(管理节点);
+3:管理节点将超级表所拥有的 vnode 列表发回 taosc;
+4:taosc将计算的请求连同标签过滤条件发往这些vnode对应的多个数据节点;
+5:每个vnode先在内存里查找出自己节点里符合标签过滤条件的表的集合,然后扫描存储的时序数据,完成相应的聚合计算,将结果返回给taosc;
+6:taosc将多个数据节点返回的结果做最后的聚合,将其返回给应用。
+
+由于TDengine在vnode内将标签数据与时序数据分离存储,通过在内存里过滤标签数据,先找到需要参与聚合操作的表的集合,将需要扫描的数据集大幅减少,大幅提升聚合计算速度。同时,由于数据分布在多个vnode/dnode,聚合计算操作在多个vnode里并发进行,又进一步提升了聚合的速度。 对普通表的聚合函数以及绝大部分操作都适用于超级表,语法完全一样,细节请看 TAOS SQL。
### 预计算
为有效提升查询处理的性能,针对物联网数据的不可更改的特点,在数据块头部记录该数据块中存储数据的统计信息:包括最大值、最小值、和。我们称之为预计算单元。如果查询处理涉及整个数据块的全部数据,直接使用预计算结果,完全不需要读取数据块的内容。由于预计算数据量远小于磁盘上存储的数据块数据的大小,对于磁盘IO为瓶颈的查询处理,使用预计算结果可以极大地减小读取IO压力,加速查询处理的流程。预计算机制与Postgre SQL的索引BRIN(block range index)有异曲同工之妙。
diff --git a/documentation20/webdocs/markdowndocs/cluster-ch.md b/documentation20/webdocs/markdowndocs/cluster-ch.md
index 13b773b3e302185009a07d4aa20db620ef702631..0e7a26eb3a8eff7d0c09cbd430bae3c4688293e1 100644
--- a/documentation20/webdocs/markdowndocs/cluster-ch.md
+++ b/documentation20/webdocs/markdowndocs/cluster-ch.md
@@ -8,7 +8,7 @@ TDengine的集群管理极其简单,除添加和删除节点需要人工干预
## 准备工作
-**第零步**:如果没有部署DNS服务,请规划集群所有物理节点的FQDN,然后按照《[一篇文章说清楚TDengine的FQDN](https://www.taosdata.com/blog/2020/09/11/1824.html)》里的步骤,将所有集群物理节点的IP与FQDN的对应关系添加好。
+**第零步**:规划集群所有物理节点的FQDN,将规划好的FQDN分别添加到每个物理节点的/etc/hostname;修改每个物理节点的/etc/hosts,将所有集群物理节点的IP与FQDN的对应添加好。【如部署了DNS,请联系网络管理员在DNS上做好相关配置】
**第一步**:如果搭建集群的物理节点中,存有之前的测试数据、装过1.X的版本,或者装过其他版本的TDengine,请先将其删除,并清空所有数据,具体步骤请参考博客[《TDengine多种安装包的安装和卸载》](https://www.taosdata.com/blog/2019/08/09/566.html )
**注意1:**因为FQDN的信息会写进文件,如果之前没有配置或者更改FQDN,且启动了TDengine。请一定在确保数据无用或者备份的前提下,清理一下之前的数据(rm -rf /var/lib/taos/);
@@ -16,9 +16,9 @@ TDengine的集群管理极其简单,除添加和删除节点需要人工干预
**第二步**:建议关闭所有物理节点的防火墙,至少保证端口:6030 - 6042的TCP和UDP端口都是开放的。**强烈建议**先关闭防火墙,集群搭建完毕之后,再来配置端口;
-**第三步**:在所有节点安装TDengine,且版本必须是一致的,**但不要启动taosd**。安装时,提示输入是否要加入一个已经存在的TDengine集群时,第一个物理节点直接回车创建新集群,后续物理节点则输入该集群任何一个在线的物理节点的FQDN:端口号(默认6030);
+**第三步**:在所有物理节点安装TDengine,且版本必须是一致的,**但不要启动taosd**。安装时,提示输入是否要加入一个已经存在的TDengine集群时,第一个物理节点直接回车创建新集群,后续物理节点则输入该集群任何一个在线的物理节点的FQDN:端口号(默认6030);
-**第四步**:检查所有数据节点,以及应用所在物理节点的网络设置:
+**第四步**:检查所有数据节点,以及应用程序所在物理节点的网络设置:
1. 每个物理节点上执行命令`hostname -f`,查看和确认所有节点的hostname是不相同的(应用驱动所在节点无需做此项检查);
2. 每个物理节点上执行`ping host`, 其中host是其他物理节点的hostname, 看能否ping通其它物理节点; 如果不能ping通,需要检查网络设置, 或/etc/hosts文件(Windows系统默认路径为C:\Windows\system32\drivers\etc\hosts),或DNS的配置。如果无法ping通,是无法组成集群的;
diff --git a/documentation20/webdocs/markdowndocs/insert-ch.md b/documentation20/webdocs/markdowndocs/insert-ch.md
index a84b577622b450089b22a961d6e5fe71627930c6..fa53cbd62b17169c0f54877a62da8c48ac21edcf 100644
--- a/documentation20/webdocs/markdowndocs/insert-ch.md
+++ b/documentation20/webdocs/markdowndocs/insert-ch.md
@@ -22,7 +22,7 @@ INSERT INTO d1001 VALUES (1538548685000, 10.3, 219, 0.31) (1538548695000, 12.6,
**Tips:**
-- 要提高写入效率,需要批量写入。一批写入的记录条数越多,插入效率就越高。但一条记录不能超过16K,一条SQL语句总长度不能超过64K(可通过参数maxSQLLength配置,最大可配置为8M)。
+- 要提高写入效率,需要批量写入。一批写入的记录条数越多,插入效率就越高。但一条记录不能超过16K,一条SQL语句总长度不能超过64K(可通过参数maxSQLLength配置,最大可配置为1M)。
- TDengine支持多线程同时写入,要进一步提高写入速度,一个客户端需要打开20个以上的线程同时写。但线程数达到一定数量后,无法再提高,甚至还会下降,因为线程切频繁切换,带来额外开销。
- 对同一张表,如果新插入记录的时间戳已经存在,新记录将被直接抛弃,也就是说,在一张表里,时间戳必须是唯一的。如果应用自动生成记录,很有可能生成的时间戳是一样的,这样,成功插入的记录条数会小于应用插入的记录条数。
- 写入的数据的时间戳必须大于当前时间减去配置参数keep的时间。如果keep配置为3650天,那么无法写入比3650天还老的数据。写入数据的时间戳也不能大于当前时间加配置参数days。如果days配置为2,那么无法写入比当前时间还晚2天的数据。
diff --git a/src/mnode/src/mnodeDb.c b/src/mnode/src/mnodeDb.c
index 8558350950de3892e30fac80514177ed3f76f886..a06152080ef23bbd561ef2e7b02531c6111e85df 100644
--- a/src/mnode/src/mnodeDb.c
+++ b/src/mnode/src/mnodeDb.c
@@ -760,6 +760,8 @@ static int32_t mnodeRetrieveDbs(SShowObj *pShow, char *data, int32_t rows, void
}
pShow->numOfReads += numOfRows;
+ mnodeVacuumResult(data, cols, numOfRows, rows, pShow);
+
mnodeDecUserRef(pUser);
return numOfRows;
}
diff --git a/tests/examples/JDBC/calciteDemo/pom.xml b/tests/examples/JDBC/calciteDemo/pom.xml
new file mode 100644
index 0000000000000000000000000000000000000000..90eea8e2c41a222f2b36967fb759fd250af536cf
--- /dev/null
+++ b/tests/examples/JDBC/calciteDemo/pom.xml
@@ -0,0 +1,53 @@
+
+
+ 4.0.0
+
+ com.taosdata.example.calcite
+ calciteDemo
+ 1.0-SNAPSHOT
+
+
+
+
+ org.slf4j
+ slf4j-simple
+ 1.7.25
+ compile
+
+
+
+ org.apache.calcite
+ calcite-core
+ 1.23.0
+
+
+ org.apache.commons
+ commons-dbcp2
+ 2.7.0
+
+
+ org.apache.calcite.avatica
+ avatica-core
+ 1.17.0
+
+
+
+
+ mysql
+ mysql-connector-java
+ 5.1.47
+
+
+
+
+ com.taosdata.jdbc
+ taos-jdbcdriver
+ 2.0.7
+
+
+
+
+
+
\ No newline at end of file
diff --git a/tests/examples/JDBC/calciteDemo/src/main/java/com/taosdata/example/calcite/CalciteDemo.java b/tests/examples/JDBC/calciteDemo/src/main/java/com/taosdata/example/calcite/CalciteDemo.java
new file mode 100644
index 0000000000000000000000000000000000000000..7e97956b7879c26056b9b0e27cce4786284ff96c
--- /dev/null
+++ b/tests/examples/JDBC/calciteDemo/src/main/java/com/taosdata/example/calcite/CalciteDemo.java
@@ -0,0 +1,67 @@
+package com.taosdata.example.calcite;
+
+import org.apache.calcite.adapter.jdbc.JdbcSchema;
+import org.apache.calcite.jdbc.CalciteConnection;
+import org.apache.calcite.schema.Schema;
+import org.apache.calcite.schema.SchemaPlus;
+import org.apache.calcite.sql.parser.SqlParseException;
+import org.apache.commons.dbcp2.BasicDataSource;
+
+import java.sql.*;
+import java.util.Properties;
+
+public class CalciteDemo {
+
+ private static String url_taos = "jdbc:TAOS://192.168.236.135:6030/test";
+ private static String url_mysql = "jdbc:mysql://master:3306/test?useSSL=false&useUnicode=true&characterEncoding=UTF-8";
+
+ public static void main(String[] args) throws SqlParseException, ClassNotFoundException, SQLException {
+ Class.forName("org.apache.calcite.jdbc.Driver");
+ Properties info = new Properties();
+ info.setProperty("caseSensitive", "false");
+
+ Connection connection = DriverManager.getConnection("jdbc:calcite:", info);
+ CalciteConnection calciteConnection = connection.unwrap(CalciteConnection.class);
+
+ SchemaPlus rootSchema = calciteConnection.getRootSchema();
+
+ //这里hdb是在tdengine中创建的数据库名
+ Schema schema = mysqlTest(rootSchema);
+// Schema schema = tdengineTest(rootSchema);
+
+ //创建新的schema自动映射到原来的hdb数据库
+ rootSchema.add("test", schema);
+
+ Statement stmt = calciteConnection.createStatement();
+ //查询schema test中的表,表名是tdengine中的表
+ ResultSet rs = stmt.executeQuery("select * from test.t");
+ ResultSetMetaData metaData = rs.getMetaData();
+ while (rs.next()) {
+ for (int i = 1; i <= metaData.getColumnCount(); i++) {
+ System.out.println(metaData.getColumnLabel(i) + " : " + rs.getString(i));
+ }
+ }
+ }
+
+
+ private static Schema tdengineTest(SchemaPlus rootSchema) throws ClassNotFoundException {
+ Class.forName("com.taosdata.jdbc.TSDBDriver");
+ BasicDataSource dataSource = new BasicDataSource();
+ dataSource.setUrl(url_taos);
+ dataSource.setUsername("root");
+ dataSource.setPassword("taosdata");
+
+ return JdbcSchema.create(rootSchema, "test", dataSource, "hdb", null);
+ }
+
+ private static Schema mysqlTest(SchemaPlus rootSchema) throws ClassNotFoundException {
+ Class.forName("com.mysql.jdbc.Driver");
+ BasicDataSource dataSource = new BasicDataSource();
+ dataSource.setUrl(url_mysql);
+ dataSource.setUsername("root");
+ dataSource.setPassword("123456");
+
+ //Schema schema = JdbcSchema.create(rootSchema, "test", dataSource, "hdb", null);
+ return JdbcSchema.create(rootSchema, "test", dataSource, "test", null);
+ }
+}
diff --git a/tests/examples/JDBC/calciteDemo/src/main/resources/log4j.properties b/tests/examples/JDBC/calciteDemo/src/main/resources/log4j.properties
new file mode 100644
index 0000000000000000000000000000000000000000..1a77ec520cd3e727ac51acb4b8f647b7cf188d97
--- /dev/null
+++ b/tests/examples/JDBC/calciteDemo/src/main/resources/log4j.properties
@@ -0,0 +1,6 @@
+log4j.rootLogger=info,stdout
+
+#console
+log4j.appender.stdout=org.apache.log4j.ConsoleAppender
+log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
+log4j.appender.stdout.layout.ConversionPattern= [%d{yyyy-MM-dd HH:mm:ss a}]:%p %l%m%n
\ No newline at end of file
diff --git a/tests/pytest/concurrent_inquiry.py b/tests/pytest/concurrent_inquiry.py
new file mode 100644
index 0000000000000000000000000000000000000000..faefc8a1c296c10e8b4fc18c2e72a6b0ff8fda44
--- /dev/null
+++ b/tests/pytest/concurrent_inquiry.py
@@ -0,0 +1,146 @@
+###################################################################
+# Copyright (c) 2016 by TAOS Technologies, Inc.
+# All rights reserved.
+#
+# This file is proprietary and confidential to TAOS Technologies.
+# No part of this file may be reproduced, stored, transmitted,
+# disclosed or used in any form or by any means other than as
+# expressly provided by the written permission from Jianhui Tao
+#
+###################################################################
+
+# -*- coding: utf-8 -*-
+import threading
+import taos
+
+import json
+import time
+import random
+# query sql
+query_sql = [
+# first supertable
+"select count(*) from test.meters where c1 > 50;",
+"select count(*) from test.meters where c2 >= 50 and c2 < 100;",
+"select count(*) from test.meters where c3 != 5;",
+"select count(*) from test.meters where t3 > 2;",
+"select count(*) from test.meters where ts <> '2020-05-13 10:00:00.002';",
+"select count(*) from test.meters where t7 like 'fi%';",
+"select count(*) from test.meters where t7 like '_econd';",
+"select count(*) from test.meters interval(1n) order by ts desc;",
+"select first(*) from test.meters;",
+"select last(*) from test.meters;",
+"select last_row(*) from test.meters;",
+"select twa(c1) from test.t1 where ts > 1500000001000 and ts < 1500000101000" ,
+"select avg(c1) from test.meters;",
+"select bottom(c1, 2) from test.t1;",
+"select diff(c1) from test.t1;",
+"select leastsquares(c1, 1, 1) from test.t1 ;",
+"select max(c1) from test.meters;",
+"select min(c1) from test.meters;",
+"select c1 + c2 * c3 + c1 / c5 + c4 + c2 from test.t1;",
+"select percentile(c1, 50) from test.t1;",
+"select spread(c1) from test.t1 ;",
+"select stddev(c1) from test.t1;",
+"select sum(c1) from test.meters;",
+"select top(c1, 2) from test.meters;"
+"select twa(c6) from test.t1 where ts > 1500000001000 and ts < 1500000101000" ,
+"select avg(c6) from test.meters;",
+"select bottom(c6, 2) from test.t1;",
+"select diff(c6) from test.t1;",
+"select leastsquares(c6, 1, 1) from test.t1 ;",
+"select max(c6) from test.meters;",
+"select min(c6) from test.meters;",
+"select c6 + c2 * c3 + c6 / c5 + c4 + c2 from test.t1;",
+"select percentile(c6, 50) from test.t1;",
+"select spread(c6) from test.t1 ;",
+"select stddev(c6) from test.t1;",
+"select sum(c6) from test.meters;",
+"select top(c6, 2) from test.meters;",
+# second supertable
+"select count(*) from test.meters1 where c1 > 50;",
+"select count(*) from test.meters1 where c2 >= 50 and c2 < 100;",
+"select count(*) from test.meters1 where c3 != 5;",
+"select count(*) from test.meters1 where t3 > 2;",
+"select count(*) from test.meters1 where ts <> '2020-05-13 10:00:00.002';",
+"select count(*) from test.meters1 where t7 like 'fi%';",
+"select count(*) from test.meters1 where t7 like '_econd';",
+"select count(*) from test.meters1 interval(1n) order by ts desc;",
+"select first(*) from test.meters1;",
+"select last(*) from test.meters1;",
+"select last_row(*) from test.meters1;",
+"select twa(c1) from test.m1 where ts > 1500000001000 and ts < 1500000101000" ,
+"select avg(c1) from test.meters1;",
+"select bottom(c1, 2) from test.m1;",
+"select diff(c1) from test.m1;",
+"select leastsquares(c1, 1, 1) from test.m1 ;",
+"select max(c1) from test.meters1;",
+"select min(c1) from test.meters1;",
+"select c1 + c2 * c3 + c1 / c5 + c3 + c2 from test.m1;",
+"select percentile(c1, 50) from test.m1;",
+"select spread(c1) from test.m1 ;",
+"select stddev(c1) from test.m1;",
+"select sum(c1) from test.meters1;",
+"select top(c1, 2) from test.meters1;",
+"select twa(c6) from test.m1 where ts > 1500000001000 and ts < 1500000101000" ,
+"select avg(c6) from test.meters1;",
+"select bottom(c6, 2) from test.m1;",
+"select diff(c6) from test.m1;",
+"select leastsquares(c6, 1, 1) from test.m1 ;",
+"select max(c6) from test.meters1;",
+"select min(c6) from test.meters1;",
+"select c6 + c2 * c3 + c6 / c5 + c3 + c2 from test.m1;",
+"select percentile(c6, 50) from test.m1;",
+"select spread(c6) from test.m1 ;",
+"select stddev(c6) from test.m1;",
+"select sum(c6) from test.meters1;",
+"select top(c6, 2) from test.meters1;"
+]
+
+class ConcurrentInquiry:
+ def initConnection(self):
+ self.numOfTherads = 50
+ self.ts=1500000001000
+
+
+ def query_thread(self,threadID):
+ host = "10.211.55.14"
+ user = "root"
+ password = "taosdata"
+ conn = taos.connect(
+ host,
+ user,
+ password,
+ )
+ cl = conn.cursor()
+
+ print("Thread %d: starting" % threadID)
+
+ while True:
+ ran_query_sql=query_sql
+ random.shuffle(ran_query_sql)
+ for i in ran_query_sql:
+ print("Thread %d : %s"% (threadID,i))
+ try:
+ cl.execute(i)
+ cl.fetchall
+ except Exception as e:
+ print(
+ "Failure thread%d, sql: %s,exception: %s" %
+ (threadID, str(i),str(e)))
+
+
+ print("Thread %d: finishing" % threadID)
+
+
+
+ def run(self):
+
+ threads = []
+ for i in range(50):
+ thread = threading.Thread(target=self.query_thread, args=(i,))
+ threads.append(thread)
+ thread.start()
+
+q = ConcurrentInquiry()
+q.initConnection()
+q.run()