TDengine 开发指南——无模式写入
简介
在物联网应用中,为了实现自动化管理、业务分析和设备监控等多种功能,通常需要采集大量的数据项。然而,由于应用逻辑的版本升级和设备自身的硬件调整等原因,数据采集项可能会频繁发生变化。为了应对这种挑战,TDengine 提供了无模式(schemaless)写入方式,旨在简化数据记录过程。
采用无模式写入方式,用户无须预先创建超级表或子表,因为 TDengine 会根据实际写入的数据自动创建相应的存储结构。此外,在必要时,无模式写入方式还能自动添加必要的数据列或标签列,确保用户写入的数据能够被正确存储。
值得注意的是,通过无模式写入方式创建的超级表及其对应的子表与通过 SQL 直接创建的超级表和子表在功能上没有区别,用户仍然可以使用 SQL 直接向其中写入数据。然而,由于无模式写入方式生成的表名是基于标签值按照固定的映射规则生成的,因此这些表名可能缺乏可读性,不易于理解。
采用无模式写入方式时会自动创建表,无须手动创建表。手动建表的话可能会出现未知的错误。
无模式写入行协议
TDengine 的无模式写入行协议兼容 InfluxDB 的行协议、OpenTSDB 的 TELNET 行协议和 OpenTSDB 的 JSON 格式协议。InfluxDB、OpenTSDB 的标准写入协议请参考各自的官方文档。
下面首先以 InfluxDB 的行协议为基础,介绍 TDengine 扩展的协议内容。该协议允许用户采用更加精细的方式控制(超级表)模式。采用一个字符串来表达一个数据行,可以向写入 API 中一次传入多行字符串来实现多个数据行的批量写入,其格式约定如下。
measurement,tag_set field_set timestamp
各参数说明如下。
- measurement 为数据表名,与 tag_set 之间使用一个英文逗号来分隔。
- tag_set 格式形如
<tag_key>=<tag_value>, <tag_key>=<tag_value>
,表示标签列数据,使用英文逗号分隔,与 field_set 之间使用一个半角空格分隔。 - field_set 格式形如
<field_key>=<field_value>, <field_key>=<field_value>
,表示普通列,同样使用英文逗号来分隔,与 timestamp 之间使用一个半角空格分隔。 - timestamp 为本行数据对应的主键时间戳。
- 无模式写入不支持含第二主键列的表的数据写入。
tag_set 中的所有的数据自动转化为 nchar 数据类型,并不需要使用双引号。
在无模式写入数据行协议中,field_set 中的每个数据项都需要对自身的数据类型进行描述,具体要求如下。
- 如果两边有英文双引号,表示 varchar 类型,例如 “abc”。
- 如果两边有英文双引号而且带有 L 或 l 前缀,表示 nchar 类型,例如 L" 报错信息 "。
- 如果两边有英文双引号而且带有 G 或 g 前缀,表示 geometry 类型,例如 G"Point(4.343 89.342)"。
- 如果两边有英文双引号而且带有 B 或 b 前缀,表示 varbinary 类型,双引号内可以为 \x 开头的十六进制或者字符串,例如 B"\x98f46e" 和 B"hello"。
- 对于空格、等号(=)、逗号(,)、双引号(")、反斜杠(\),前面需要使用反斜杠(\)进行转义(均为英文半角符号)。无模式写入协议的域转义规则如下表所示。
序号 | 域 | 需转义字符 |
---|---|---|
1 | 超级表名 | 逗号,空格 |
2 | 标签名 | 逗号,等号,空格 |
3 | 标签值 | 逗号,等号,空格 |
4 | 列名 | 逗号,等号,空格 |
5 | 列值 | 双引号,反斜杠 |
如果使用两个连续的反斜杠,则第 1 个反斜杠作为转义符,当只有一个反斜杠时则无须转义。无模式写入协议的反斜杠转义规则如下表所示。
序号 | 反斜杠 | 转义为 |
---|---|---|
1 | \ | \ |
2 | \\ | \ |
3 | \\\ | \\ |
4 | \\\\ | \\ |
5 | \\\\\ | \\\ |
6 | \\\\\\ | \\\ |
数值类型将通过后缀来区分数据类型。无模式写入协议的数值类型转义规则如下表所示。
序号 | 后缀 | 映射类型 | 大小 (字节) |
---|---|---|---|
1 | 无或 f64 | double | 8 |
2 | f32 | float | 4 |
3 | i8/u8 | TinyInt/UTinyInt | 1 |
4 | i16/u16 | SmallInt/USmallInt | 2 |
5 | i32/u32 | Int/UInt | 4 |
6 | i64/i/u64/u | BigInt/BigInt/UBigInt/UBigInt | 8 |
- t、T、true、True、TRUE、f、F、false、False 将直接作为 BOOL 型来处理。
例如如下数据行表示:向名为 st 的超级表下的 t1 标签为 “3”(NCHAR)、t2 标签为 “4”(NCHAR)、t3 标签为 “t3”(NCHAR)的数据子表,写入 c1 列为 3(BIGINT)、c2 列为 false(BOOL)、c3
列为 “passit”(BINARY)、c4 列为 4(DOUBLE)、主键时间戳为 1626006833639000000 的一行数据。
st,t1=3,t2=4,t3=t3 c1=3i64,c3="passit",c2=false,c4=4f64 1626006833639000000
需要注意的是,如果描述数据类型后缀时出现大小写错误,或者为数据指定的数据类型有误,均可能引发报错提示而导致数据写入失败。
TDengine 提供数据写入的幂等性保证,即您可以反复调用 API 进行出错数据的写入操作。但是不提供多行数据写入的原子性保证。即在多行数据一批次写入过程中,会出现部分数据写入成功,部分数据写入失败的情况。
无模式写入处理规则
无模式写入按照如下原则来处理行数据:
-
将使用如下规则来生成子表名:首先将 measurement 的名称和标签的 key 和 value 组合成为如下的字符串
"measurement,tag_key1=tag_value1,tag_key2=tag_value2"
-
需要注意的是,这里的 tag_key1、tag_key2 并不是用户输入的标签的原始顺序,而是使用了标签名称按照字符串升序排列后的结果。所以,tag_key1 并不是在行协议中输入的第一个标签。
排列完成以后计算该字符串的 MD5 散列值 “md5_val”。然后将计算的结果与字符串组合生成表名:“t_md5_val”。其中的 “t_” 是固定的前缀,每个通过该映射关系自动生成的表都具有该前缀。 -
如果不想用自动生成的表名,有两种指定子表名的方式(第一种优先级更高)。
- 通过在 taos.cfg 里配置 smlAutoChildTableNameDelimiter 参数来指定(
@ # 空格 回车 换行 制表符
除外),例如配置 smlAutoChildTableNameDelimiter=- 插入数据为 st,t0=cpu1,t1=4 c1=3 1626006833639000000 则创建的表名为 cpu1-4。 - 通过在 taos.cfg 里配置 smlChildTableName 参数来指定,例如配置 smlChildTableName=tname 插入数据为 st,tname=cpu1,t1=4 c1=3 1626006833639000000 则创建的表名为 cpu1,注意如果多行数据 tname 相同,但是后面的 tag_set 不同,则使用第一行自动建表时指定的 tag_set,其他的行会忽略。
- 通过在 taos.cfg 里配置 smlAutoChildTableNameDelimiter 参数来指定(
-
-
如果解析行协议获得的超级表不存在,则会创建这个超级表(不建议手动创建超级表,不然插入数据可能异常)。
-
如果解析行协议获得子表不存在,则 schemaless 会按照步骤 1 或 2 确定的子表名来创建子表。
-
如果数据行中指定的标签列或普通列不存在,则在超级表中增加对应的标签列或普通列(只增不减)。
-
如果超级表中存在一些标签列或普通列未在一个数据行中被指定取值,那么这些列的值在这一行中会被置为 NULL。
-
对 BINARY 或 NCHAR 列,如果数据行中所提供值的长度超出了列类型的限制,自动增加该列允许存储的字符长度上限(只增不减),以保证数据的完整保存。
-
整个处理过程中遇到的错误会中断写入过程,并返回错误代码。
-
为了提高写入的效率,默认假设同一个超级表中 field_set 的顺序是一样的(第一条数据包含所有的 field,后面的数据按照这个顺序),如果顺序不一样,需要配置参数 smlDataFormat 为 false,否则,数据写入按照相同顺序写入,库中数据会异常,从 3.0.3.0 开始,自动检测顺序是否一致,该配置废弃。
-
由于 sql 建表表名不支持点号(.),所以 schemaless 也对点号(.)做了处理,如果 schemaless 自动建表的表名如果有点号(.),会自动替换为下划线(_)。如果手动指定子表名的话,子表名里有点号(.),同样转化为下划线(_)。
-
taos.cfg 增加 smlTsDefaultName 配置(字符串类型),只在 client 端起作用,配置后,schemaless 自动建表的时间列名字可以通过该配置设置。不配置的话,默认为 _ts。
-
无模式写入的数据超级表或子表名区分大小写。
-
无模式写入仍然遵循 TDengine 对数据结构的底层限制,例如每行数据的总长度不能超过 48KB(从 3.0.5.0 版本开始为 64KB),标签值的总长度不超过 16KB。
时间分辨率识别
无模式写入支持 3 个指定的模式,如下表所示:
序号 | 值 | 说明 |
---|---|---|
1 | SML_LINE_PROTOCOL | InfluxDB 行协议(Line Protocol) |
2 | SML_TELNET_PROTOCOL | OpenTSDB 文本行协议 |
3 | SML_JSON_PROTOCOL | JSON 协议格式 |
在 SML_LINE_PROTOCOL 解析模式下,需要用户指定输入的时间戳的时间分辨率。可用的时间分辨率如下表所示:
序号 | 时间分辨率定义 | 含义 |
---|---|---|
1 | TSDB_SML_TIMESTAMP_NOT_CONFIGURED | 未定义(无效) |
2 | TSDB_SML_TIMESTAMP_HOURS | 小时 |
3 | TSDB_SML_TIMESTAMP_MINUTES | 分钟 |
4 | TSDB_SML_TIMESTAMP_SECONDS | 秒 |
5 | TSDB_SML_TIMESTAMP_MILLI_SECONDS | 毫秒 |
6 | TSDB_SML_TIMESTAMP_MICRO_SECONDS | 微秒 |
7 | TSDB_SML_TIMESTAMP_NANO_SECONDS | 纳秒 |
在 SML_TELNET_PROTOCOL 和 SML_JSON_PROTOCOL 模式下,根据时间戳的长度来确定时间精度(与 OpenTSDB 标准操作方式相同),此时会忽略用户指定的时间分辨率。
数据模式映射规则
InfluxDB 行协议的数据将被映射成具有模式的数据,其中,measurement 映射为超级表名称,tag_set 中的标签名称映射为数据模式中的标签名,field_set 中的名称映射为列名称。例如下面的数据。
st,t1=3,t2=4,t3=t3 c1=3i64,c3="passit",c2=false,c4=4f64 1626006833639000000
该行数据映射生成一个超级表:st,其包含了 3 个类型为 nchar 的标签,分别是:t1、t2、t3。五个数据列,分别是 ts(timestamp)、c1 (bigint)、c3(binary)、c2 (bool)、c4 (bigint)。映射成为如下 SQL 语句:
create stable st (_ts timestamp, c1 bigint, c2 bool, c3 binary(6), c4 bigint) tags(t1 nchar(1), t2 nchar(1), t3 nchar(2))
数据模式变更处理
本节将说明不同行数据写入情况下,对于数据模式的影响。
在使用行协议写入一个明确的标识的字段类型的时候,后续更改该字段的类型定义,会出现明确的数据模式错误,即会触发写入 API 报告错误。如下所示,
st,t1=3,t2=4,t3=t3 c1=3i64,c3="passit",c2=false,c4=4 1626006833639000000
st,t1=3,t2=4,t3=t3 c1=3i64,c3="passit",c2=false,c4=4i 1626006833640000000
第一行的数据类型映射将 c4 列定义为 Double,但是第二行的数据又通过数值后缀方式声明该列为 bigInt,由此会触发无模式写入的解析错误。
如果列前面的行协议将数据列声明为了 binary,后续的要求长度更长的 binary 长度,此时会触发超级表模式的变更。
st,t1=3,t2=4,t3=t3 c1=3i64,c5="pass" 1626006833639000000
st,t1=3,t2=4,t3=t3 c1=3i64,c5="passit" 1626006833640000000
第一行中行协议解析会声明 c5 列是一个 binary(4) 的字段,第二次行数据写入会提取列 c5 仍然是 binary 列,但是其宽度为 6,此时需要将 binary 的宽度增加到能够容纳 新字符串的宽度。
st,t1=3,t2=4,t3=t3 c1=3i64 1626006833639000000
st,t1=3,t2=4,t3=t3 c1=3i64,c6="passit" 1626006833640000000
第二行数据相对于第一行来说增加了一个列 c6,类型为 binary(6)。那么此时会自动增加一个列 c6,类型为 binary(6)。
无模式写入示例
下面以智能电表为例,介绍各语言连接器使用无模式写入接口写入数据的代码样例,包含了三种协议:InfluxDB 的行协议、OpenTSDB 的 TELNET 行协议和 OpenTSDB 的 JSON 格式协议。
:::note
- 因为无模式写入自动建表规则与之前执行 SQL 样例中不同,因此运行代码样例前请确保
meters
、metric_telnet
和metric_json
表不存在。 - OpenTSDB 的 TELNET 行协议和 OpenTSDB 的 JSON 格式协议只支持一个数据列,因此我们采用了其他示例。
:::
WebSocket 连接
执行带有 reqId 的无模式写入,最后一个参数 reqId 可用于请求链路追踪。
JAVA 示例
public class SchemalessWsTest {private static final String host = "127.0.0.1";private static final String lineDemo = "meters,groupid=2,location=California.SanFrancisco current=10.3000002f64,voltage=219i32,phase=0.31f64 1626006833639";private static final String telnetDemo = "metric_telnet 1707095283260 4 host=host0 interface=eth0";private static final String jsonDemo = "{\"metric\": \"metric_json\",\"timestamp\": 1626846400,\"value\": 10.3, \"tags\": {\"groupid\": 2, \"location\": \"California.SanFrancisco\", \"id\": \"d1001\"}}";public static void main(String[] args) throws SQLException {final String url = "jdbc:TAOS-WS://" + host + ":6041?user=root&password=taosdata";try (Connection connection = DriverManager.getConnection(url)) {init(connection);AbstractConnection conn = connection.unwrap(AbstractConnection.class);conn.write(lineDemo, SchemalessProtocolType.LINE, SchemalessTimestampType.MILLI_SECONDS);conn.write(telnetDemo, SchemalessProtocolType.TELNET, SchemalessTimestampType.MILLI_SECONDS);conn.write(jsonDemo, SchemalessProtocolType.JSON, SchemalessTimestampType.SECONDS);System.out.println("Inserted data with schemaless successfully.");} catch (Exception ex) {// please refer to the JDBC specifications for detailed exceptions infoSystem.out.printf("Failed to insert data with schemaless, %sErrMessage: %s%n",ex instanceof SQLException ? "ErrCode: " + ((SQLException) ex).getErrorCode() + ", " : "",ex.getMessage());// Print stack trace for context in examples. Use logging in production.ex.printStackTrace();throw ex;}}private static void init(Connection connection) throws SQLException {try (Statement stmt = connection.createStatement()) {stmt.execute("CREATE DATABASE IF NOT EXISTS power");stmt.execute("USE power");}}
}
Python 示例
import taoswshost = "localhost"
port = 6041
def prepare():conn = Nonetry:conn = taosws.connect(user="root",password="taosdata",host=host,port=port)# create databaserowsAffected = conn.execute(f"CREATE DATABASE IF NOT EXISTS power")assert rowsAffected == 0except Exception as err:print(f"Failed to create db and table, db addrr:{host}:{port} ; ErrMessage:{err}")raise errfinally:if conn:conn.close()def schemaless_insert():conn = NonelineDemo = ["meters,groupid=2,location=California.SanFrancisco current=10.3000002f64,voltage=219i32,phase=0.31f64 1626006833639"]telnetDemo = ["metric_telnet 1707095283260 4 host=host0 interface=eth0"]jsonDemo = ['{"metric": "metric_json","timestamp": 1626846400,"value": 10.3, "tags": {"groupid": 2, "location": "California.SanFrancisco", "id": "d1001"}}']try:conn = taosws.connect(user="root",password="taosdata",host=host,port=port,database='power')conn.schemaless_insert(lines = lineDemo,protocol = taosws.PySchemalessProtocol.Line,precision = taosws.PySchemalessPrecision.Millisecond,ttl=1,req_id=1,)conn.schemaless_insert(lines=telnetDemo,protocol=taosws.PySchemalessProtocol.Telnet,precision=taosws.PySchemalessPrecision.Microsecond,ttl=1,req_id=2,)conn.schemaless_insert(lines=jsonDemo,protocol=taosws.PySchemalessProtocol.Json,precision=taosws.PySchemalessPrecision.Millisecond,ttl=1,req_id=3,)print("Inserted data with schemaless successfully.");except Exception as err:print(f"Failed to insert data with schemaless, ErrMessage:{err}")raise errfinally:if conn:conn.close()if __name__ == "__main__":prepare()schemaless_insert()
C 语言示例
int code = 0;
char *dsn = "ws://localhost:6041";// connect
WS_TAOS *taos = ws_connect(dsn);
if (taos == NULL) {fprintf(stderr, "Failed to connect to %s, ErrCode: 0x%x, ErrMessage: %s.\n", dsn, ws_errno(NULL), ws_errstr(NULL));return -1;
}// create database
WS_RES *result = ws_query(taos, "CREATE DATABASE IF NOT EXISTS power");
code = ws_errno(result);
if (code != 0) {fprintf(stderr, "Failed to create database power, ErrCode: 0x%x, ErrMessage: %s.\n", code, ws_errstr(result));ws_close(taos);return -1;
}
ws_free_result(result);// use database
result = ws_query(taos, "USE power");
code = ws_errno(result);
if (code != 0) {fprintf(stderr, "Failed to execute use power, ErrCode: 0x%x, ErrMessage: %s\n.", code, ws_errstr(result));ws_close(taos);return -1;
}
ws_free_result(result);// schemaless demo data
char *line_demo ="meters,groupid=2,location=California.SanFrancisco current=10.3000002f64,voltage=219i32,phase=0.31f64 ""1626006833639";
char *telnet_demo = "metric_telnet 1707095283260 4 host=host0 interface=eth0";
char *json_demo ="{\"metric\": \"metric_json\",\"timestamp\": 1626846400,\"value\": 10.3, \"tags\": {\"groupid\": 2, ""\"location\": \"California.SanFrancisco\", \"id\": \"d1001\"}}";// influxdb line protocol
char *lines[] = {line_demo};
int totalLines = 0;
result = ws_schemaless_insert_raw(taos, line_demo, strlen(line_demo), &totalLines, WS_TSDB_SML_LINE_PROTOCOL,WS_TSDB_SML_TIMESTAMP_MILLI_SECONDS);
code = ws_errno(result);
if (code != 0) {fprintf(stderr, "Failed to insert schemaless line data, data: %s, ErrCode: 0x%x, ErrMessage: %s\n.", line_demo,code, ws_errstr(result));ws_close(taos);return -1;
}fprintf(stdout, "Insert %d rows of schemaless line data successfully.\n", totalLines);
ws_free_result(result);// opentsdb telnet protocol
totalLines = 0;
result = ws_schemaless_insert_raw(taos, telnet_demo, strlen(telnet_demo), &totalLines, WS_TSDB_SML_TELNET_PROTOCOL,WS_TSDB_SML_TIMESTAMP_MILLI_SECONDS);
code = ws_errno(result);
if (code != 0) {fprintf(stderr, "Failed to insert schemaless telnet data, data: %s, ErrCode: 0x%x, ErrMessage: %s\n.", telnet_demo,code, ws_errstr(result));ws_close(taos);return -1;
}fprintf(stdout, "Insert %d rows of schemaless telnet data successfully.\n", totalLines);
ws_free_result(result);// opentsdb json protocol
char *jsons[1] = {0};
// allocate memory for json data. can not use static memory.
totalLines = 0;
result = ws_schemaless_insert_raw(taos, json_demo, strlen(json_demo), &totalLines, WS_TSDB_SML_JSON_PROTOCOL,WS_TSDB_SML_TIMESTAMP_MILLI_SECONDS);
code = ws_errno(result);
if (code != 0) {free(jsons[0]);fprintf(stderr, "Failed to insert schemaless json data, Server: %s, ErrCode: 0x%x, ErrMessage: %s\n.", json_demo,code, ws_errstr(result));ws_close(taos);return -1;
}
free(jsons[0]);fprintf(stdout, "Insert %d rows of schemaless json data successfully.\n", totalLines);
ws_free_result(result);// close & clean
ws_close(taos);
return 0;
Go 示例
package mainimport ("database/sql""fmt""log""time""github.com/taosdata/driver-go/v3/common"_ "github.com/taosdata/driver-go/v3/taosWS""github.com/taosdata/driver-go/v3/ws/schemaless"
)func main() {host := "127.0.0.1"lineDemo := "meters,groupid=2,location=California.SanFrancisco current=10.3000002f64,voltage=219i32,phase=0.31f64 1626006833639"telnetDemo := "metric_telnet 1707095283260 4 host=host0 interface=eth0"jsonDemo := "{\"metric\": \"metric_json\",\"timestamp\": 1626846400,\"value\": 10.3, \"tags\": {\"groupid\": 2, \"location\": \"California.SanFrancisco\", \"id\": \"d1001\"}}"taosDSN := fmt.Sprintf("root:taosdata@ws(%s:6041)/", host)db, err := sql.Open("taosWS", taosDSN)if err != nil {log.Fatalln("Failed to connect to host: " + host + "; ErrMessage: " + err.Error())}defer db.Close()_, err = db.Exec("CREATE DATABASE IF NOT EXISTS power")if err != nil {log.Fatalln("Failed to create database power, ErrMessage: " + err.Error())}s, err := schemaless.NewSchemaless(schemaless.NewConfig("ws://localhost:6041", 1,schemaless.SetDb("power"),schemaless.SetReadTimeout(10*time.Second),schemaless.SetWriteTimeout(10*time.Second),schemaless.SetUser("root"),schemaless.SetPassword("taosdata"),))if err != nil {log.Fatalln("Failed to connect to host: " + host + "; ErrMessage: " + err.Error())}// insert influxdb line protocolerr = s.Insert(lineDemo, schemaless.InfluxDBLineProtocol, "ms", 0, common.GetReqID())if err != nil {log.Fatalln("Failed to insert data with schemaless, data:" + lineDemo + ", ErrMessage: " + err.Error())}// insert opentsdb telnet line protocolerr = s.Insert(telnetDemo, schemaless.OpenTSDBTelnetLineProtocol, "ms", 0, common.GetReqID())if err != nil {log.Fatalln("Failed to insert data with schemaless, data: " + telnetDemo + ", ErrMessage: " + err.Error())}// insert opentsdb json format protocolerr = s.Insert(jsonDemo, schemaless.OpenTSDBJsonFormatProtocol, "s", 0, common.GetReqID())if err != nil {log.Fatalln("Failed to insert data with schemaless, data: " + jsonDemo + ", ErrMessage: " + err.Error())}fmt.Println("Inserted data with schemaless successfully.")
}
Rust 示例
use taos_query::common::SchemalessPrecision;
use taos_query::common::SchemalessProtocol;
use taos_query::common::SmlDataBuilder;use taos::AsyncQueryable;
use taos::AsyncTBuilder;
use taos::TaosBuilder;
use taos::taos_query;#[tokio::main]
async fn main() -> anyhow::Result<()> {std::env::set_var("RUST_LOG", "taos=debug");pretty_env_logger::init();let host = "localhost";let dsn = format!("ws://{}:6041/power", host);log::debug!("dsn: {:?}", &dsn);let client = TaosBuilder::from_dsn(dsn)?.build().await?;let db = "power";client.exec(format!("create database if not exists {db}")).await?;// should specify database before insertclient.exec(format!("use {db}")).await?;// SchemalessProtocol::Linelet data = ["meters,groupid=2,location=California.SanFrancisco current=10.3000002f64,voltage=219i32,phase=0.31f64 1626006833639",].map(String::from).to_vec();let sml_data = SmlDataBuilder::default().protocol(SchemalessProtocol::Line).precision(SchemalessPrecision::Millisecond).data(data.clone()).ttl(1000).req_id(100u64).build()?;match client.put(&sml_data).await{Ok(_) => {},Err(err) => {eprintln!("Failed to insert data with schemaless, data:{:?}, ErrMessage: {}", data, err);return Err(err.into());}}// SchemalessProtocol::Telnetlet data = ["metric_telnet 1707095283260 4 host=host0 interface=eth0",].map(String::from).to_vec();let sml_data = SmlDataBuilder::default().protocol(SchemalessProtocol::Telnet).precision(SchemalessPrecision::Millisecond).data(data.clone()).ttl(1000).req_id(200u64).build()?;match client.put(&sml_data).await{Ok(_) => {},Err(err) => {eprintln!("Failed to insert data with schemaless, data:{:?}, ErrMessage: {}", data, err);return Err(err.into());}}// SchemalessProtocol::Jsonlet data = [r#"[{"metric": "metric_json","timestamp": 1626846400,"value": 10.3,"tags": {"groupid": 2,"location": "California.SanFrancisco","id": "d1001"}}]"#].map(String::from).to_vec();let sml_data = SmlDataBuilder::default().protocol(SchemalessProtocol::Json).precision(SchemalessPrecision::Millisecond).data(data.clone()).ttl(1000).req_id(300u64).build()?;match client.put(&sml_data).await{Ok(_) => {},Err(err) => {eprintln!("Failed to insert data with schemaless, data:{:?}, ErrMessage: {}", data, err);return Err(err.into());}}println!("Inserted data with schemaless successfully.");Ok(())
}
nodejs 示例
const taos = require("@tdengine/websocket");let influxdbData = ["meters,groupid=2,location=California.SanFrancisco current=10.3000002f64,voltage=219i32,phase=0.31f64 1626006833639"];
let jsonData = ["{\"metric\": \"metric_json\",\"timestamp\": 1626846400,\"value\": 10.3, \"tags\": {\"groupid\": 2, \"location\": \"California.SanFrancisco\", \"id\": \"d1001\"}}"]
let telnetData = ["metric_telnet 1707095283260 4 host=host0 interface=eth0"];async function createConnect() {let dsn = 'ws://localhost:6041'let conf = new taos.WSConfig(dsn);conf.setUser('root');conf.setPwd('taosdata');let wsSql = await taos.sqlConnect(conf);await wsSql.exec('CREATE DATABASE IF NOT EXISTS power KEEP 3650 DURATION 10 BUFFER 16 WAL_LEVEL 1;');await wsSql.exec('USE power');return wsSql;
}async function test() {let wsSql = null;let wsRows = null;let ttl = 0;try {wsSql = await createConnect()await wsSql.schemalessInsert(influxdbData, taos.SchemalessProto.InfluxDBLineProtocol, taos.Precision.MILLI_SECONDS, ttl);await wsSql.schemalessInsert(telnetData, taos.SchemalessProto.OpenTSDBTelnetLineProtocol, taos.Precision.MILLI_SECONDS, ttl);await wsSql.schemalessInsert(jsonData, taos.SchemalessProto.OpenTSDBJsonFormatProtocol, taos.Precision.SECONDS, ttl);console.log("Inserted data with schemaless successfully.")}catch (err) {console.error(`Failed to insert data with schemaless, ErrCode: ${err.code}, ErrMessage: ${err.message}`);throw err;}finally {if (wsRows) {await wsRows.close();}if (wsSql) {await wsSql.close();}taos.destroy();}
}test()
C# 示例
public static void Main(string[] args)
{var host = "127.0.0.1";var lineDemo ="meters,groupid=2,location=California.SanFrancisco current=10.3000002f64,voltage=219i32,phase=0.31f64 1626006833639";var telnetDemo = "metric_telnet 1707095283260 4 host=host0 interface=eth0";var jsonDemo ="{\"metric\": \"metric_json\",\"timestamp\": 1626846400,\"value\": 10.3, \"tags\": {\"groupid\": 2, \"location\": \"California.SanFrancisco\", \"id\": \"d1001\"}}";try{var builder =new ConnectionStringBuilder($"protocol=WebSocket;host={host};port=6041;username=root;password=taosdata");using (var client = DbDriver.Open(builder)){// create databaseclient.Exec("CREATE DATABASE IF NOT EXISTS power");// use databaseclient.Exec("USE power");// insert influx line protocol dataclient.SchemalessInsert(new[] { lineDemo }, TDengineSchemalessProtocol.TSDB_SML_LINE_PROTOCOL,TDengineSchemalessPrecision.TSDB_SML_TIMESTAMP_MILLI_SECONDS, 0, ReqId.GetReqId());// insert opentsdb telnet protocol dataclient.SchemalessInsert(new[] { telnetDemo }, TDengineSchemalessProtocol.TSDB_SML_TELNET_PROTOCOL,TDengineSchemalessPrecision.TSDB_SML_TIMESTAMP_MILLI_SECONDS, 0, ReqId.GetReqId());// insert json dataclient.SchemalessInsert(new[] { jsonDemo }, TDengineSchemalessProtocol.TSDB_SML_JSON_PROTOCOL,TDengineSchemalessPrecision.TSDB_SML_TIMESTAMP_NOT_CONFIGURED, 0, ReqId.GetReqId());}Console.WriteLine("Inserted data with schemaless successfully.");}catch (TDengineError e){// handle TDengine errorConsole.WriteLine("Failed to insert data with schemaless, ErrCode: " + e.Code +", ErrMessage: " + e.Error);throw;}catch (Exception e){// handle other exceptionsConsole.WriteLine("Failed to insert data with schemaless, ErrMessage: " + e.Message);throw;}
}
REST API 示例
不支持
原生连接
执行带有 reqId 的无模式写入,最后一个参数 reqId 可用于请求链路追踪。
JAVA 示例
public class SchemalessJniTest {private static final String host = "127.0.0.1";private static final String lineDemo = "meters,groupid=2,location=California.SanFrancisco current=10.3000002f64,voltage=219i32,phase=0.31f64 1626006833639";private static final String telnetDemo = "metric_telnet 1707095283260 4 host=host0 interface=eth0";private static final String jsonDemo = "{\"metric\": \"metric_json\",\"timestamp\": 1626846400,\"value\": 10.3, \"tags\": {\"groupid\": 2, \"location\": \"California.SanFrancisco\", \"id\": \"d1001\"}}";public static void main(String[] args) throws SQLException {final String jdbcUrl = "jdbc:TAOS://" + host + ":6030/?user=root&password=taosdata";try (Connection connection = DriverManager.getConnection(jdbcUrl)) {init(connection);AbstractConnection conn = connection.unwrap(AbstractConnection.class);conn.write(lineDemo, SchemalessProtocolType.LINE, SchemalessTimestampType.MILLI_SECONDS);conn.write(telnetDemo, SchemalessProtocolType.TELNET, SchemalessTimestampType.MILLI_SECONDS);conn.write(jsonDemo, SchemalessProtocolType.JSON, SchemalessTimestampType.NOT_CONFIGURED);System.out.println("Inserted data with schemaless successfully.");} catch (Exception ex) {// please refer to the JDBC specifications for detailed exceptions infoSystem.out.printf("Failed to insert data with schemaless, %sErrMessage: %s%n",ex instanceof SQLException ? "ErrCode: " + ((SQLException) ex).getErrorCode() + ", " : "",ex.getMessage());// Print stack trace for context in examples. Use logging in production.ex.printStackTrace();throw ex;}}private static void init(Connection connection) throws SQLException {try (Statement stmt = connection.createStatement()) {stmt.execute("CREATE DATABASE IF NOT EXISTS power");stmt.execute("USE power");}}
}
Python 示例
import taoslineDemo = ["meters,groupid=2,location=California.SanFrancisco current=10.3000002f64,voltage=219i32,phase=0.31f64 1626006833639"
]telnetDemo = ["metric_telnet 1707095283260 4 host=host0 interface=eth0"]jsonDemo = ['{"metric": "metric_json","timestamp": 1626846400,"value": 10.3, "tags": {"groupid": 2, "location": "California.SanFrancisco", "id": "d1001"}}'
]
host = "localhost"
port = 6030
try:conn = taos.connect(user="root",password="taosdata",host=host,port=port)conn.execute("CREATE DATABASE IF NOT EXISTS power")# change database. same as execute "USE db"conn.select_db("power")conn.schemaless_insert(lineDemo, taos.SmlProtocol.LINE_PROTOCOL, taos.SmlPrecision.MILLI_SECONDS)conn.schemaless_insert(telnetDemo, taos.SmlProtocol.TELNET_PROTOCOL, taos.SmlPrecision.MICRO_SECONDS)conn.schemaless_insert(jsonDemo, taos.SmlProtocol.JSON_PROTOCOL, taos.SmlPrecision.MILLI_SECONDS)print("Inserted data with schemaless successfully.");
except Exception as err:print(f"Failed to insert data with schemaless, ErrMessage:{err}")raise err
finally:if conn:conn.close()
C 语言示例
const char *host = "localhost";
const char *user = "root";
const char *password = "taosdata";
uint16_t port = 6030;
int code = 0;// connect
TAOS *taos = taos_connect(host, user, password, NULL, port);
if (taos == NULL) {fprintf(stderr, "Failed to connect to %s:%hu, ErrCode: 0x%x, ErrMessage: %s.\n", host, port, taos_errno(NULL),taos_errstr(NULL));taos_cleanup();return -1;
}// create database
TAOS_RES *result = taos_query(taos, "CREATE DATABASE IF NOT EXISTS power");
code = taos_errno(result);
if (code != 0) {fprintf(stderr, "Failed to create database power, ErrCode: 0x%x, ErrMessage: %s.\n", code, taos_errstr(result));taos_close(taos);taos_cleanup();return -1;
}
taos_free_result(result);// use database
result = taos_query(taos, "USE power");
code = taos_errno(result);
if (code != 0) {fprintf(stderr, "Failed to execute use power, ErrCode: 0x%x, ErrMessage: %s\n.", code, taos_errstr(result));taos_close(taos);taos_cleanup();return -1;
}
taos_free_result(result);// schemaless demo data
char *line_demo ="meters,groupid=2,location=California.SanFrancisco current=10.3000002f64,voltage=219i32,phase=0.31f64 ""1626006833639";
char *telnet_demo = "metric_telnet 1707095283260 4 host=host0 interface=eth0";
char *json_demo ="{\"metric\": \"metric_json\",\"timestamp\": 1626846400,\"value\": 10.3, \"tags\": {\"groupid\": 2, ""\"location\": \"California.SanFrancisco\", \"id\": \"d1001\"}}";// influxdb line protocol
char *lines[] = {line_demo};
result = taos_schemaless_insert(taos, lines, 1, TSDB_SML_LINE_PROTOCOL, TSDB_SML_TIMESTAMP_MILLI_SECONDS);
code = taos_errno(result);
if (code != 0) {fprintf(stderr, "Failed to insert schemaless line data, data: %s, ErrCode: 0x%x, ErrMessage: %s\n.", line_demo, code,taos_errstr(result));taos_close(taos);taos_cleanup();return -1;
}int rows = taos_affected_rows(result);
fprintf(stdout, "Insert %d rows of schemaless line data successfully.\n", rows);
taos_free_result(result);// opentsdb telnet protocol
char *telnets[] = {telnet_demo};
result = taos_schemaless_insert(taos, telnets, 1, TSDB_SML_TELNET_PROTOCOL, TSDB_SML_TIMESTAMP_MILLI_SECONDS);
code = taos_errno(result);
if (code != 0) {fprintf(stderr, "Failed to insert schemaless telnet data, data: %s, ErrCode: 0x%x, ErrMessage: %s\n.", telnet_demo, code,taos_errstr(result));taos_close(taos);taos_cleanup();return -1;
}rows = taos_affected_rows(result);
fprintf(stdout, "Insert %d rows of schemaless telnet data successfully.\n", rows);
taos_free_result(result);// opentsdb json protocol
char *jsons[1] = {0};
// allocate memory for json data. can not use static memory.
size_t size = 1024;
jsons[0] = malloc(size);
if (jsons[0] == NULL) {fprintf(stderr, "Failed to allocate memory: %zu bytes.\n", size);taos_close(taos);taos_cleanup();return -1;
}
(void)strncpy(jsons[0], json_demo, 1023);
result = taos_schemaless_insert(taos, jsons, 1, TSDB_SML_JSON_PROTOCOL, TSDB_SML_TIMESTAMP_NOT_CONFIGURED);
code = taos_errno(result);
if (code != 0) {free(jsons[0]);fprintf(stderr, "Failed to insert schemaless json data, Server: %s, ErrCode: 0x%x, ErrMessage: %s\n.", json_demo, code,taos_errstr(result));taos_close(taos);taos_cleanup();return -1;
}
free(jsons[0]);rows = taos_affected_rows(result);
fprintf(stdout, "Insert %d rows of schemaless json data successfully.\n", rows);
taos_free_result(result);// close & clean
taos_close(taos);
taos_cleanup();
return 0;
Go 示例
package mainimport ("fmt""log""github.com/taosdata/driver-go/v3/af"
)func main() {host := "127.0.0.1"lineDemo := "meters,groupid=2,location=California.SanFrancisco current=10.3000002f64,voltage=219i32,phase=0.31f64 1626006833639"telnetDemo := "metric_telnet 1707095283260 4 host=host0 interface=eth0"jsonDemo := "{\"metric\": \"metric_json\",\"timestamp\": 1626846400,\"value\": 10.3, \"tags\": {\"groupid\": 2, \"location\": \"California.SanFrancisco\", \"id\": \"d1001\"}}"conn, err := af.Open(host, "root", "taosdata", "", 0)if err != nil {log.Fatalln("Failed to connect to host: " + host + "; ErrMessage: " + err.Error())}defer conn.Close()_, err = conn.Exec("CREATE DATABASE IF NOT EXISTS power")if err != nil {log.Fatalln("Failed to create database power, ErrMessage: " + err.Error())}_, err = conn.Exec("USE power")if err != nil {log.Fatalln("Failed to use database power, ErrMessage: " + err.Error())}// insert influxdb line protocolerr = conn.InfluxDBInsertLines([]string{lineDemo}, "ms")if err != nil {log.Fatalln("Failed to insert data with schemaless, data:" + lineDemo + ", ErrMessage: " + err.Error())}// insert opentsdb telnet protocolerr = conn.OpenTSDBInsertTelnetLines([]string{telnetDemo})if err != nil {log.Fatalln("Failed to insert data with schemaless, data:" + telnetDemo + ", ErrMessage: " + err.Error())}// insert opentsdb json protocolerr = conn.OpenTSDBInsertJsonPayload(jsonDemo)if err != nil {log.Fatalln("Failed to insert data with schemaless, data:" + jsonDemo + ", ErrMessage: " + err.Error())}fmt.Println("Inserted data with schemaless successfully.")
}
Rust 示例
use taos_query::common::SchemalessPrecision;
use taos_query::common::SchemalessProtocol;
use taos_query::common::SmlDataBuilder;use taos::AsyncQueryable;
use taos::AsyncTBuilder;
use taos::TaosBuilder;
use taos::taos_query;#[tokio::main]
async fn main() -> anyhow::Result<()> {std::env::set_var("RUST_LOG", "taos=debug");pretty_env_logger::init();let host = "localhost";let dsn = format!("taos://{}:6030", host);log::debug!("dsn: {:?}", &dsn);let client = TaosBuilder::from_dsn(dsn)?.build().await?;let db = "power";client.exec(format!("create database if not exists {db}")).await?;// should specify database before insertclient.exec(format!("use {db}")).await?;// SchemalessProtocol::Linelet data = ["meters,groupid=2,location=California.SanFrancisco current=10.3000002f64,voltage=219i32,phase=0.31f64 1626006833639",].map(String::from).to_vec();let sml_data = SmlDataBuilder::default().protocol(SchemalessProtocol::Line).precision(SchemalessPrecision::Millisecond).data(data.clone()).ttl(1000).req_id(100u64).build()?;match client.put(&sml_data).await{Ok(_) => {},Err(err) => {eprintln!("Failed to insert data with schemaless, data:{:?}, ErrMessage: {}", data, err);return Err(err.into());}}// SchemalessProtocol::Telnetlet data = ["metric_telnet 1707095283260 4 host=host0 interface=eth0",].map(String::from).to_vec();let sml_data = SmlDataBuilder::default().protocol(SchemalessProtocol::Telnet).precision(SchemalessPrecision::Millisecond).data(data.clone()).ttl(1000).req_id(200u64).build()?;match client.put(&sml_data).await{Ok(_) => {},Err(err) => {eprintln!("Failed to insert data with schemaless, data:{:?}, ErrMessage: {}", data, err);return Err(err.into());}}// SchemalessProtocol::Jsonlet data = [r#"[{"metric": "metric_json","timestamp": 1626846400,"value": 10.3,"tags": {"groupid": 2,"location": "California.SanFrancisco","id": "d1001"}}]"#].map(String::from).to_vec();let sml_data = SmlDataBuilder::default().protocol(SchemalessProtocol::Json).precision(SchemalessPrecision::Millisecond).data(data.clone()).ttl(1000).req_id(300u64).build()?;match client.put(&sml_data).await{Ok(_) => {},Err(err) => {eprintln!("Failed to insert data with schemaless, data:{:?}, ErrMessage: {}", data, err);return Err(err.into());}}println!("Inserted data with schemaless successfully.");Ok(())
}
nodejs 示例
不支持
C# 示例
public static void Main(string[] args)
{var host = "127.0.0.1";var lineDemo ="meters,groupid=2,location=California.SanFrancisco current=10.3000002f64,voltage=219i32,phase=0.31f64 1626006833639";var telnetDemo = "metric_telnet 1707095283260 4 host=host0 interface=eth0";var jsonDemo ="{\"metric\": \"metric_json\",\"timestamp\": 1626846400,\"value\": 10.3, \"tags\": {\"groupid\": 2, \"location\": \"California.SanFrancisco\", \"id\": \"d1001\"}}";try{var builder =new ConnectionStringBuilder($"host={host};port=6030;username=root;password=taosdata");using (var client = DbDriver.Open(builder)){// create databaseclient.Exec("CREATE DATABASE IF NOT EXISTS power");// use databaseclient.Exec("USE power");// insert influx line protocol dataclient.SchemalessInsert(new[]{lineDemo}, TDengineSchemalessProtocol.TSDB_SML_LINE_PROTOCOL,TDengineSchemalessPrecision.TSDB_SML_TIMESTAMP_MILLI_SECONDS, 0, ReqId.GetReqId());// insert opentsdb telnet protocol dataclient.SchemalessInsert(new[]{telnetDemo}, TDengineSchemalessProtocol.TSDB_SML_TELNET_PROTOCOL,TDengineSchemalessPrecision.TSDB_SML_TIMESTAMP_MILLI_SECONDS, 0, ReqId.GetReqId());// insert json dataclient.SchemalessInsert(new []{jsonDemo}, TDengineSchemalessProtocol.TSDB_SML_JSON_PROTOCOL,TDengineSchemalessPrecision.TSDB_SML_TIMESTAMP_NOT_CONFIGURED, 0, ReqId.GetReqId());}}catch (TDengineError e){// handle TDengine errorConsole.WriteLine("Failed to insert data with schemaless, ErrCode: " + e.Code + ", ErrMessage: " + e.Error);throw;}catch (Exception e){// handle other exceptionsConsole.WriteLine("Failed to insert data with schemaless, ErrMessage:" + e.Message);throw;}
}
REST API 示例
不支持
查询写入的数据
运行上节的样例代码,会在 power 数据库中自动建表,我们可以通过 TDengine CLI 或者应用程序来查询数据。下面给出用 TDengine CLI 查询超级表和 meters 表数据的样例。
taos> show power.stables;stable_name |
=================================meter_current |stb0_0 |meters |
Query OK, 3 row(s) in set (0.002527s)taos> select * from power.meters limit 1 \G;
*************************** 1.row ***************************_ts: 2021-07-11 20:33:53.639current: 10.300000199999999voltage: 219phase: 0.310000000000000groupid: 2
location: California.SanFrancisco
Query OK, 1 row(s) in set (0.004501s)
访问官网
更多内容欢迎访问 TDengine 官网
相关文章:

TDengine 开发指南——无模式写入
简介 在物联网应用中,为了实现自动化管理、业务分析和设备监控等多种功能,通常需要采集大量的数据项。然而,由于应用逻辑的版本升级和设备自身的硬件调整等原因,数据采集项可能会频繁发生变化。为了应对这种挑战,TDen…...
分布式互斥算法
1. 概述:什么是分布式互斥 假设有两个小孩想玩同一个玩具(临界资源),但玩具只有一个,必须保证一次只有一个人能够玩。当一个小孩在玩时,另一个小孩只能原地等待,直到玩完才能轮到自己。这就是 …...

第34次CCF-CSP认证真题解析(目标300分做法)
第34次CCF-CSP认证 矩阵重塑(其一)AC代码及解析矩阵重塑(其二)AC代码及解析货物调度AC代码及解析 矩阵重塑(其一) 输入输出及样例: AC代码及解析 1.线性化原矩阵 :由于cin的特性我们…...

video-audio-extractor:视频转换为音频
软件介绍 前几天在网上看见有人分享了一个源码,大概就是py调用的ffmpeg来制作的。 这一次我带来源码版(需要py环境才可以运行),开箱即用版本(直接即可运行) 软件特点 软件功能 视频提取音频:…...
rk3588 区分两个相同的usb相机
有时候会插入两个一模一样的usb相机,担心每次启动他们所对应的设备节点 /dev/video* 会变化,所以需要绑定usb口,区分两个相机。把两个相机都插入后,查看usb信息 rootrk3588:/# udevadm info --attribute-walk --name/dev/video0U…...

[概率论基本概念4]什么是无偏估计
关键词:Unbiased Estimation 一、说明 对于无偏和有偏估计,需要了解其叙事背景,是指整体和抽样的关系,也就是说整体的叙事是从理论角度的,而估计器原理是从实践角度说事;为了表明概率理论(不可…...
乐观锁与悲观锁的实现和应用
乐观锁与悲观锁:原理、实现与应用详解 在并发编程和数据库操作中,乐观锁和悲观锁是两种重要的并发控制策略,它们在原理、实现方式和应用场景上存在显著差异。下面我们将通过图文结合的方式,深入探讨这两种锁机制。 一、基本概念 1…...

PL/SQLDeveloper中数值类型字段查询后显示为科学计数法的处理方式
PL/SQLDeveloper中数值类型字段查询后显示为科学计数法的处理方式 文章目录 PL/SQLDeveloper中数值类型字段查询后显示为科学计数法的处理方式1. 查询效果2. 处理方式3. 再次查询 1. 查询效果 2. 处理方式 3. 再次查询...

【vue】Uniapp 打包Android 文件选择上传问题详解~
需求 uniapp兼容android app,pc,h5的文件选择并上传功能。 需要支持拍照和相册选择,以及选择其他类型文件上传~ 实践过程和问题 开始使用uni-file-picker组件 以为很顺利,android模拟器测试…… 忽略了平台兼容性提示~&#…...
ASR技术(自动语音识别)深度解析
ASR技术(自动语音识别)深度解析 自动语音识别(Automatic Speech Recognition,ASR)是将人类语音转换为文本的核心技术,以下是其全面解析: 一、技术原理架构 #mermaid-svg-QlJOWpMtlGi9LNeF {font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:1…...
图论水题2
div2 361 D. Tree Requests 题意 对于一颗 n n n节点的树,每个节点有一个字母,有 m m m次询问,每次询问求对于顶点 v v v的子树中深度为 h h h的结点能否组成一个回文串$ (1 \leq n \leq m \leq 5 \cdot 10^5) $ 思路 关于 v v v的子树结…...

Ctrl-Crash 助力交通安全:可控生成逼真车祸视频,防患于未然
视频扩散技术虽发展显著,但多数驾驶数据集事故事件少,难以生成逼真车祸图像,而提升交通安全又急需逼真可控的事故模拟。为此,论文提出可控车祸视频生成模型 Ctrl-Crash,它以边界框、碰撞类型、初始图像帧等为条件&…...

网络编程之服务器模型与UDP编程
一、服务器模型 在网络通信中,通常要求一个服务器连接多个客户端 为了处理多个客户端的请求,通常有多种表现形式 1、循环服务器模型 一个服务器可以连接多个客户端,但同一时间只能连接并处理一个客户的请求 socket() 结构体 bind() listen() …...

Transformer-BiLSTM、Transformer、CNN-BiLSTM、BiLSTM、CNN五模型时序预测
Transformer-BiLSTM、Transformer、CNN-BiLSTM、BiLSTM、CNN五模型时序预测 目录 Transformer-BiLSTM、Transformer、CNN-BiLSTM、BiLSTM、CNN五模型时序预测预测效果基本介绍程序设计参考资料 预测效果 基本介绍 Transformer-BiLSTM、Transformer、CNN-BiLSTM、BiLSTM、CNN五…...

阿里云服务器安装nginx并配置前端资源路径(前后端部署到一台服务器并成功访问)
运行以下命令,安装Nginx相关依赖。 yum install -y gcc-c yum install -y pcre pcre-devel yum install -y zlib zlib-devel yum install -y openssl openssl-devel 运行wget命令下载Nginx 1.21.6。 您可以通过Nginx开源社区直接获取对应版本的安装包URL&…...
Ubuntu 下开机自动执行命令的方法
Ubuntu 下开机自动执行命令的方法(使用 crontab) 在日常使用 Ubuntu 或其他 Linux 系统时,我们常常需要让某些程序或脚本在系统启动后自动运行。例如:启动 Clash 代理、初始化服务、定时同步数据等。 本文将介绍一种简单且常用的…...

C++11新增重要标准(下)
前言 一,forward(完美转发) 二,可变参数模板 三,emplace系列接口 四,新增类功能 五,default与delete 六,lambda表达式 七,包装器 八,bind 在C11中新增…...

【第六篇】 SpringBoot的日志基础操作
简介 日志系统在软件开发中至关重要,用于调试代码、记录运行信息及错误堆栈。本篇文章不仅详细介绍了日志对象的创建及快速使用,还说明了日志持久化的两种配置方式和滚动日志的设置。实际开发需根据场景选择合适的日志级别和存储策略。文章内容若存在错误…...

Pluto论文阅读笔记
主要还是参考了这一篇论文笔记:https://zhuanlan.zhihu.com/p/18319150220 Pluto主要有三个创新点: 横向纵向用lane的query来做将轨迹投回栅格化地图,计算碰撞loss对数据进行正增强和负增强,让正增强的结果也无增强的结果相近&a…...
ubuntu显示器未知
在Ubuntu系统中,当外接显示器被识别为“未知设备”时,可通过以下日志文件进行问题诊断,结合Xorg日志和内核日志综合分析: 🔍 一、查看Xorg显示服务日志(核心) Xorg日志记录了图形界面的详细事…...
Faiss向量数据库全面解析:从原理到实战
Faiss向量数据库全面解析:从原理到实战 引言:向量搜索的时代需求 在AI技术爆发的今天,向量数据已成为表示文本、图像、音视频等内容的核心形式。Facebook AI研究院开源的Faiss(Facebook AI Similarity Search)作为高…...

matlab 2024a 工具箱Aerospsce Toolbox报错
Matlab R2024a中Aerospsce Toolbox报错 警告:Aerospace Toolbox and Aerospace Blockset licenses are required in ‘built-in/Spacecraft Dynamics’ 找到安装路径\MATLAB\R2024a\licenses文件夹license_****_R2024a.lic 里面工具箱名称出错,手动修改…...

使用有限计算实现视频生成模型的高效训练
大家读完觉得有帮助记得关注和点赞!!! 抽象 视频生成的最新进展需要越来越高效的训练配方,以减轻不断上升的计算成本。在本报告中,我们介绍了 ContentV,这是一种 8B 参数文本到视频模型,在 256 …...

Server2003 B-1 Windows操作系统渗透
任务环境说明: 服务器场景:Server2003(开放链接) 服务器场景操作系统:Windows7 1.通过本地PC中渗透测试平台Kali对服务器场景Windows进行系统服务及版本扫描渗透测试,并将该操作显示结果中Telnet服务对应的…...

一次Oracle的非正常关闭
数据库自己会关闭吗? 从现象来说Oracle MySQL Redis等都会出现进程意外停止的情况。而这些停止都是非人为正常关闭或者暴力关闭(abort或者kill 进程) 一次测试环境的非关闭 一般遇到这种情况先看一下错误日志吧。 2025-06-01T06:26:06.35…...
AI不会杀死创作,但会杀死平庸
作为一个敲了8年Java代码的普通本科程序员,日常主要泡在会议后台管理系统的开发里。从2023年底被朋友拽着试了第一把AI工具到现在,电脑手机上的AI软件比外卖App还多——写代码的Copilot、画时序图的工具、聊天的ChatGPT、Deepseek,基本市面上…...
JeecgBoot低代码管理平台
一、一句话理解 JeecgBoot JeecgBoot 是一个基于 Java 技术栈(主要是 Spring Boot 和 Vue)的快速开发脚手架。它的核心理念是:通过代码生成器和一系列预置模块,极大地减少程序员在开发企业级后台管理系统时重复的、模板化的工作&…...
Fetch与Axios:区别、联系、优缺点及使用差异
Fetch与Axios:区别、联系、优缺点及使用差异 文章目录 Fetch与Axios:区别、联系、优缺点及使用差异一、联系二、区别1. 浏览器支持与兼容性2. 响应处理3. 请求拦截和响应拦截4. 错误处理 三、优缺点1. Fetch API优点缺点 2. Axios优点缺点 四、使用上的差…...

YOLO11解决方案之分析
概述 Ultralytics提供了一系列的解决方案,利用YOLO11解决现实世界的问题,包括物体计数、模糊处理、热力图、安防系统、速度估计、物体追踪等多个方面的应用。 Ultralytics提供了三种基本的数据可视化类型:折线图(面积图…...

yolov11与双目测距结合,实现目标的识别和定位测距(onnx版本)
一、yolov11双目测距基本流程 yolov11 双目测距的大致流程就是: 双目标定 --> 立体校正(含消除畸变) --> 立体匹配 --> 视差计算 --> 深度计算(3D坐标)计算 --> 目标检测 --> 目标距离计算及可视化 下面将分别阐述每…...