dash3000怎么看使用开源的TDengine与开源的Grafana部署短信运营监测可视化平台

新闻资讯2026-04-20 23:10:14

公司的主营业务是给企业客户提供短信服务,内部有一个强大的运营监控平台。每日短信业务量巨大,监控平台需要使用时序数据库(Time-Series Database)来对发送的海量短信分地理区域、运营商、接收状态等类别进行统计和监控。以前一直在用InfluxDB,对于时间跨度稍大些的查询(比如一个月的数据)就显得非常慢了。从TDengine Database开源后,便知道了这个很牛的家伙,于是尝试着使用TDengine。

在搞懂了基本的功能后,便上线了TDengine版的监控系统,但是发现,在grafana中居然不能“group by”,只能通过写where多条语句将多个短信状态数据放到一个仪表盘里,如图:

dash3000怎么看使用开源的TDengine与开源的Grafana部署短信运营监测可视化平台_https://www.jmylbn.com_新闻资讯_第1张

如果where条件有更多,这样的方法就太笨,并且灵活性太差。

于是,开始仔细研究官方文档,搞懂了“超级表”、“连续查询”等,在这个过程中遇到过不少问题,在这里做一下记录(测试环境,数据是模拟产生的)。

测试环境:

cat /etc/redhat-release
CentOS Linux release 7.7.1908 (Core)

安装很简单:

rpm -ivh tdengine-1.6.3.1-3.x86_64.rpm

配置都用默认的(未改配置文件)

启动TDengine:

systemctl start taosd

在命令行输入“taos”

taos>

以下建库、建表操作都在此提示符下进行

create database jk keep 365 precision 'us';

说明:

dash3000怎么看使用开源的TDengine与开源的Grafana部署短信运营监测可视化平台_https://www.jmylbn.com_新闻资讯_第2张

进入数据库“jk”

taos> use jk; 
Database changed.
create table jiankong (ts timestamp, gatewayid binary(6), companyid binary(20), provinceid binary(10), cityid binary(10), value int, timestr binary(30))
tags(type binary(10), subtype binary(10));

短信系统中有3种type,几百种subtype,所以将这些静态信息(或者简单地理解为需要将进行group by的字段设置为tag)

解释一下超级表:

标签数据(或者叫标签值)直接关联到每个子表,相同的标签值(一个或者多个,最多6个)定位到一个子表(用“写数据时自动建表”的方式,可以将“相同的标签值”对应到多个子表)。

tag值支持中文,需要将tag类型设置为NCHAR(在其他测试中已经验证过)。

create table jiankong_sub_send using jiankong tags ('send', 'send'); 
create table jiankong_sub_delivrd using jiankong tags ('delivrd', 'delivrd'); 
create table jiankong_sub_undeliv_db_0108 using jiankong tags ('undeliv', 'DB:0108'); 
create table jiankong_sub_undeliv_db_0107 using jiankong tags ('undeliv', 'DB:0107'); 
create table jiankong_sub_undeliv_balance using jiankong tags ('undeliv', 'BALANCE'); 
create table jiankong_sub_undeliv_id_0076 using jiankong tags ('undeliv', 'ID:0076'); 
create table jiankong_sub_undeliv_ib_0008 using jiankong tags ('undeliv', 'IB:0008');

相同类型的type和subtype的组合创建为一个子表(只是进行测试,所以并没有将所有的几百个subtype都进行建表)

INSERT INTO jiankong_sub_send VALUES (now, 3034, '1564', '109', '1272', '2', '201909231530') 
INSERT INTO jiankong_sub_delivrd VALUES (now, 3034, '1564', '109', '1272', '2', '201909231530')
INSERT INTO jiankong_sub_undeliv_balance VALUES (now, 1179, '152', '106', '1000', '1', '201910071113') 
INSERT INTO jiankong_sub_undeliv_id_0076 VALUES (now, 1165, '1785', '111', '1226', '1', '201910071415') 
INSERT INTO jiankong_sub_undeliv_ib_0008 VALUES (now, 1165, '1785', '127', '1000', '2', '201910061727') 
INSERT INTO jiankong_sub_undeliv_db_0108 VALUES (now, 90, '548', '123', '1237', '1', '201910061127') 
INSERT INTO jiankong_sub_undeliv_db_0107 VALUES (now, 2261, '808', '116', '1314', '2', '201910032106')

以上是对上述创建的7个子表分别插入模拟数据,由于模拟大量数据,所以需要写shell脚本(也可以用其他方式)进行数据灌入。

写入数据时不能直接对STable操作,而是要对每张子表进行操作。

查询数据库信息:

taos> show databases; 
name | created time | ntables | vgroups |replica| days | keep1,keep2,keep(D) | tables | rows | cache(b) | ablocks |tblocks| ctime(s) | clog | comp |time precision| status | 
==============================================================================================================================================================================================================================================
log | 19-11-18 16:37:14.025| 4| 1| 1| 10|30,30,30 | 32| 1024| 2048| 2.00000| 32| 3600| 1| 2|us |ready | 
jk | 19-11-18 16:48:19.867| 10| 1| 1| 10|365,365,365 | 1024| 4096| 16384| 4.00000| 100| 3600| 1| 2|us |ready | 
Query OK, 1 row(s) in set (0.002487s)

查询超级表:

taos> show stables; 
name | created_time |columns| tags | tables | 
==================================================================================================================== 
jiankong | 19-11-18 16:48:41.540| 7| 2| 7| Query OK, 1 row(s) in set (0.002140s)

查询超级表的表结构:

taos> describe jiankong; 
Field | Type | Length | Note | 
 ======================================================================================================= 
ts |TIMESTAMP | 8| | 
gatewayid |BINARY | 6| | 
companyid |BINARY | 20| | 
provinceid |BINARY | 10| | 
cityid |BINARY | 10| | value |INT | 4| | 
timestr |BINARY | 30| | 
type |BINARY | 10|tag | 
subtype |BINARY | 10|tag | 
Query OK, 9 row(s) in set (0.001301s)

可以在Note列看到“tag”,表示是此列是标签

查询子表:

taos> show tables;
                           table_name                           |     created_time     |columns|                             stable                             |
 =================================================================================================================================================================
jiankong_sub_delivrd                                            | 19-11-18 16:49:17.009|      7|jiankong                                                        |
jiankong_sub_undeliv_ib_0008                                    | 19-11-18 16:49:17.025|      7|jiankong                                                        |
jiankong_sub_undeliv_db_0108                                    | 19-11-18 16:49:17.016|      7|jiankong                                                        |
jiankong_sub_undeliv_db_0107                                    | 19-11-18 16:49:17.018|      7|jiankong                                                        |
jiankong_sub_undeliv_id_0076                                    | 19-11-18 16:49:17.023|      7|jiankong                                                        |
jiankong_sub_send                                               | 19-11-18 16:49:17.003|      7|jiankong                                                        |
jiankong_sub_undeliv_balance                                    | 19-11-18 16:49:17.021|      7|jiankong                                                        |

查询具体的子表的表结构:

taos> describe jiankong_sub_undeliv_db_0108;
                             Field                              |      Type      |  Length   |   Note   |
    =========================================================================================================
    ts                                                              |TIMESTAMP       |          8|          |
    gatewayid                                                       |BINARY          |          6|          |
    companyid                                                       |BINARY          |         20|          |
    provinceid                                                      |BINARY          |         10|          |
    cityid                                                          |BINARY          |         10|          |
    value                                                           |INT             |          4|          |
    timestr                                                         |BINARY          |         30|          |
    type                                                            |BINARY          |         10|undeliv   |
    subtype                                                         |BINARY          |         10|DB:0108   |

可以在Note列看到“undeliv”(超级表中的type字段)和“DB:0108″(超级表中的subtype字段),这2个静态标签值确定了这个子表

对type进行分组聚合查询:

taos> select sum(value) from jk.jiankong group by type;
     sum(value)      |   type   |
=================================
             11827688|delivrd   |
             55566578|send      |
             46687487|undeliv   |
Query OK, 3 row(s) in set (0.018251s)

对subtype进行分组聚合查询:

taos>
taos> select sum(value) from jk.jiankong group by subtype;
     sum(value)      | subtype  |
=================================
                 9317|BALANCE   |
                65219|DB:0107   |
              2077691|DB:0108   |
              2804417|IB:0008   |
             41730843|ID:0076   |
             11827688|delivrd   |
             55566578|send      |
Query OK, 7 row(s) in set (0.013978s)

对type和subtype进行分组聚合查询:

taos> select sum(value) from jk.jiankong group by type, subtype;
     sum(value)      |   type   | subtype  |
============================================
             11827688|delivrd   |delivrd   |
             55566578|send      |send      |
                  9317|undeliv   |BALANCE   |
                65219|undeliv   |DB:0107   |
              2077691|undeliv   |DB:0108   |
              2804417|undeliv   |IB:0008   |
             41730843|undeliv   |ID:0076   |
Query OK, 7 row(s) in set (0.732830s)

按天对type和subtype进行分组聚合查询:

taos> select sum(value) from jk.jiankong interval(1d) group by type, subtype;
           ts            |     sum(value)      |   type   | subtype  |
======================================================================
 19-11-18 00:00:00.000000|              1760800|delivrd   |delivrd   |
 19-11-19 00:00:00.000000|                14768|delivrd   |delivrd   |
 19-11-20 00:00:00.000000|              3290720|delivrd   |delivrd   |
 19-11-21 00:00:00.000000|              4973640|delivrd   |delivrd   |
 19-11-22 00:00:00.000000|              1787760|delivrd   |delivrd   |
 19-11-18 00:00:00.000000|             36976790|send      |send      |
 19-11-19 00:00:00.000000|               310128|send      |send      |
 19-11-20 00:00:00.000000|              9482760|send      |send      |
 19-11-21 00:00:00.000000|              6470940|send      |send      |
 19-11-22 00:00:00.000000|              2325960|send      |send      |
 19-11-18 00:00:00.000000|                 6200|undeliv   |BALANCE   |
 19-11-19 00:00:00.000000|                   52|undeliv   |BALANCE   |
 19-11-20 00:00:00.000000|                 1590|undeliv   |BALANCE   |
 19-11-21 00:00:00.000000|                 1085|undeliv   |BALANCE   |
 19-11-22 00:00:00.000000|                  390|undeliv   |BALANCE   |
 19-11-18 00:00:00.000000|                43400|undeliv   |DB:0107   |
 19-11-19 00:00:00.000000|                  364|undeliv   |DB:0107   |
 19-11-20 00:00:00.000000|                11130|undeliv   |DB:0107   |
 19-11-21 00:00:00.000000|                 7595|undeliv   |DB:0107   |
 19-11-22 00:00:00.000000|                 2730|undeliv   |DB:0107   |
 19-11-18 00:00:00.000000|              1382600|undeliv   |DB:0108   |
 19-11-19 00:00:00.000000|                11596|undeliv   |DB:0108   |
 19-11-20 00:00:00.000000|               354570|undeliv   |DB:0108   |
 19-11-21 00:00:00.000000|               241955|undeliv   |DB:0108   |
 19-11-22 00:00:00.000000|                86970|undeliv   |DB:0108   |
 19-11-18 00:00:00.000000|              1866200|undeliv   |IB:0008   |
 19-11-19 00:00:00.000000|                15652|undeliv   |IB:0008   |
 19-11-20 00:00:00.000000|               478590|undeliv   |IB:0008   |
 19-11-21 00:00:00.000000|               326585|undeliv   |IB:0008   |
 19-11-22 00:00:00.000000|               117390|undeliv   |IB:0008   |
 19-11-18 00:00:00.000000|             27769800|undeliv   |ID:0076   |
 19-11-19 00:00:00.000000|               232908|undeliv   |ID:0076   |
 19-11-20 00:00:00.000000|              7121610|undeliv   |ID:0076   |
 19-11-21 00:00:00.000000|              4859715|undeliv   |ID:0076   |
 19-11-22 00:00:00.000000|              1746810|undeliv   |ID:0076   |
Query OK, 35 row(s) in set (0.023865s)

此处interval是聚合时间段的长度, 最短时间间隔10毫秒(10a)

未建超级表时,对普通表进行分组聚合查询,会报错:

taos> select sum(value) from jk.jiankong group by type;
    TSDB error: invalid SQL: group by only available for STable query

我们有另外一个需求,由于要监控的静态数据多达几百个,而且具有不确定性,所以无法全部在建库、建表的时候创建所有子表,这个功能完全解决了我们的这个问题。

以下是官网的文档摘录:

对比,用create创建子表:

create table jiankong_sub_send using jiankong tags ('send', 'send');

在官网https://grafana.com/grafana/download下载grafana的rpm安装包后,进行安装:

rpm -ivh grafana-6.4.4-1.x86_64.rpm

TDengine的Grafana插件在安装包的/usr/local/taos/connector/grafana目录下

cp -r /usr/local/taos/connector/grafana/tdengine/ /var/lib/grafana/plugins
systemctl start grafana-server

默认用户名和密码都是admin

dash3000怎么看使用开源的TDengine与开源的Grafana部署短信运营监测可视化平台_https://www.jmylbn.com_新闻资讯_第3张
dash3000怎么看使用开源的TDengine与开源的Grafana部署短信运营监测可视化平台_https://www.jmylbn.com_新闻资讯_第4张
dash3000怎么看使用开源的TDengine与开源的Grafana部署短信运营监测可视化平台_https://www.jmylbn.com_新闻资讯_第5张

在最下方找到“TDengine”

dash3000怎么看使用开源的TDengine与开源的Grafana部署短信运营监测可视化平台_https://www.jmylbn.com_新闻资讯_第6张
Name:“TDengine”(可以是其他名字)
Host:测试服务器地址“http://192.168.8.66:6020”
User: 默认为“root”
Password:默认为“taosdata”
dash3000怎么看使用开源的TDengine与开源的Grafana部署短信运营监测可视化平台_https://www.jmylbn.com_新闻资讯_第7张

测试一下:

dash3000怎么看使用开源的TDengine与开源的Grafana部署短信运营监测可视化平台_https://www.jmylbn.com_新闻资讯_第8张

将相同类型需要监控的仪表盘(dashboard)放到一个Folder中

dash3000怎么看使用开源的TDengine与开源的Grafana部署短信运营监测可视化平台_https://www.jmylbn.com_新闻资讯_第9张

进入刚才创建的Folder后,创建Dashboard

dash3000怎么看使用开源的TDengine与开源的Grafana部署短信运营监测可视化平台_https://www.jmylbn.com_新闻资讯_第10张

INPUT处的sql语句,要注意fill的位置,需要在group by前面,否则报错

dash3000怎么看使用开源的TDengine与开源的Grafana部署短信运营监测可视化平台_https://www.jmylbn.com_新闻资讯_第11张

配置图形显示

可以根据需求进行曲线图,表格,仪表盘等的选择

dash3000怎么看使用开源的TDengine与开源的Grafana部署短信运营监测可视化平台_https://www.jmylbn.com_新闻资讯_第12张
dash3000怎么看使用开源的TDengine与开源的Grafana部署短信运营监测可视化平台_https://www.jmylbn.com_新闻资讯_第13张

在这里配置“曲线图”,图示下方是具体的图形显示细则,如:标线、是否填充,对显示的字段进行曲线颜色的自定义等

dash3000怎么看使用开源的TDengine与开源的Grafana部署短信运营监测可视化平台_https://www.jmylbn.com_新闻资讯_第14张

给此仪表盘起个一看就懂的名字:

dash3000怎么看使用开源的TDengine与开源的Grafana部署短信运营监测可视化平台_https://www.jmylbn.com_新闻资讯_第15张
dash3000怎么看使用开源的TDengine与开源的Grafana部署短信运营监测可视化平台_https://www.jmylbn.com_新闻资讯_第16张

无group by,需要写多条sql,通过where条件去区分,如果分类多就很麻烦且不灵活

dash3000怎么看使用开源的TDengine与开源的Grafana部署短信运营监测可视化平台_https://www.jmylbn.com_新闻资讯_第17张

有group by,一条sql就解决问题了:

dash3000怎么看使用开源的TDengine与开源的Grafana部署短信运营监测可视化平台_https://www.jmylbn.com_新闻资讯_第18张

下图是有无group by的曲线趋势对比,可以看到是一模一样的

dash3000怎么看使用开源的TDengine与开源的Grafana部署短信运营监测可视化平台_https://www.jmylbn.com_新闻资讯_第19张

TDengine的“预计算”的概念我觉得非常的棒,官网文档摘录如下:

连续查询的官网文档摘录如下:

其中,将结果再写回到TDengine中的方式其实就是一种用户级别的预计算,这样由TDengine按照用户定义的时间窗口和时间增量进行后台的计算,在用户查询数据的时候,直接从回写的表中读取数据,速度就会非常快。

创建连续查询:

taos> create table test_stream_sum as select sum(value) from jiankong interval(20s) sliding(10s) group by type, subtype;
Query OK, 1 row(s) affected (0.000983s)

上述连续查询,sql的select部分实际的输出结果为:

taos> select sum(value) from jiankong interval(20s) group by type, subtype;
           ts            |     sum(value)      |   type   | subtype  |
======================================================================
 19-11-18 16:50:40.000000|                 9088|delivrd   |delivrd   |
 19-11-18 16:51:00.000000|                31808|delivrd   |delivrd   |
 19-11-18 16:51:20.000000|                15904|delivrd   |delivrd   |
 19-11-18 16:52:20.000000|                12212|delivrd   |delivrd   |
 19-11-18 16:52:40.000000|                31524|delivrd   |delivrd   |
 19-11-18 16:53:00.000000|                31524|delivrd   |delivrd   |
 19-11-18 16:53:20.000000|                31808|delivrd   |delivrd   |
 19-11-18 16:53:40.000000|                31240|delivrd   |delivrd   |
 19-11-18 16:54:00.000000|                31524|delivrd   |delivrd   |
 19-11-18 16:54:20.000000|                31524|delivrd   |delivrd   |
 19-11-18 16:54:40.000000|                31240|delivrd   |delivrd   |
 19-11-18 16:55:00.000000|                31524|delivrd   |delivrd   |
 19-11-18 16:55:20.000000|                28400|delivrd   |delivrd   |
 19-11-18 16:55:40.000000|                31808|delivrd   |delivrd   |
 19-11-18 16:56:00.000000|                31524|delivrd   |delivrd   |
 19-11-18 16:56:20.000000|                31240|delivrd   |delivrd   |
 19-11-18 16:56:40.000000|                31524|delivrd   |delivrd   |
 19-11-18 16:57:00.000000|                32092|delivrd   |delivrd   |
 19-11-18 16:57:20.000000|                31240|delivrd   |delivrd   |
 19-11-18 16:57:40.000000|                32092|delivrd   |delivrd   |
 19-11-18 16:58:00.000000|                31240|delivrd   |delivrd   |
 19-11-18 16:58:20.000000|                22720|delivrd   |delivrd   |
 19-11-18 16:50:40.000000|               190848|send      |send      |

自动创建的连续查询的表中实际的数据为:

taos> select * from test_stream_sum;
           ts            |     sum_value_      |
================================================
 19-11-18 17:17:30.000000|                 2556|
 19-11-18 17:17:40.000000|                18460|
 19-11-18 17:17:50.000000|                15904|
 19-11-18 17:18:00.000000|                15620|
Query OK, 4 row(s) in set (0.000431s)

上述结果并不是期待的结果,没有按照我定义的group by字段进行聚合查询显示。

于是github Issues, taos的攻城狮回复“连续查询目前还不能很好的支持 group by,这个问题已经在我们的计划列表里,后续会完善这方面的功能”,原因是“因为这样回写后,新表的时间戳主键可能出现相同(不同的group by字段会有相同的时间),就会冲突了,所以暂时不支持”。

虽然目前这个功能未达到我的预期,攻城狮的回复还是聊以安慰,期待这个功能的完善。

 TDengine的设计初衷是服务于物联网,有结构化和时序的特性,建议是和时序密切的数据可以用,其他的数据不建议使用。

从TDengine的架构设计、存储等等,觉得不局限于百分之百的时序特性,有些明细查询也是可以尝试在TDengine中进行存储的,后续会尝试进行一下测试。