13-schemaless.md 11.8 KB
Newer Older
1 2
---
title: Schemaless Writing
D
danielclow 已提交
3
description: This document describes how to use the schemaless write component of TDengine.
4 5
---

6
In IoT applications, data is collected for many purposes such as intelligent control, business analysis, device monitoring and so on. Due to changes in business or functional requirements or changes in device hardware, the application logic and even the data collected may change. Schemaless writing automatically creates storage structures for your data as it is being written to TDengine, so that you do not need to create supertables in advance. When necessary, schemaless writing will automatically add the required columns to ensure that the data written by the user is stored correctly.
7

8
The schemaless writing method creates super tables and their corresponding subtables. These are completely indistinguishable from the super tables and subtables created directly via SQL. You can write data directly to them via SQL statements. Note that the names of tables created by schemaless writing are based on fixed mapping rules for tag values, so they are not explicitly ideographic and they lack readability.
9

10
Note: Schemaless writing creates tables automatically. Creating tables manually is not supported with schemaless writing.
wmmhello's avatar
wmmhello 已提交
11

12 13
## Schemaless Writing Line Protocol

S
Sean Ely 已提交
14
TDengine's schemaless writing line protocol supports InfluxDB's Line Protocol, OpenTSDB's telnet line protocol, and OpenTSDB's JSON format protocol. However, when using these three protocols, you need to specify in the API the standard of the parsing protocol to be used for the input content.
15 16 17

For the standard writing protocols of InfluxDB and OpenTSDB, please refer to the documentation of each protocol. The following is a description of TDengine's extended protocol, based on InfluxDB's line protocol first. They allow users to control the (super table) schema more granularly.

S
Sean Ely 已提交
18
With the following formatting conventions, schemaless writing uses a single string to express a data row (multiple rows can be passed into the writing API at once to enable bulk writing).
19 20 21 22 23

```json
measurement,tag_set field_set timestamp
```

24
where:
25 26

- measurement will be used as the data table name. It will be separated from tag_set by a comma.
27 28
- `tag_set` will be used as tags, with format like `<tag_key>=<tag_value>,<tag_key>=<tag_value>` Enter a space between `tag_set` and `field_set`.
- `field_set`will be used as data columns, with format like `<field_key>=<field_value>,<field_key>=<field_value>` Enter a space between `field_set` and `timestamp`.
29
- `timestamp` is the primary key timestamp corresponding to this row of data
30 31 32 33 34 35 36

All data in tag_set is automatically converted to the NCHAR data type and does not require double quotes (").

In the schemaless writing data line protocol, each data item in the field_set needs to be described with its data type. Let's explain in detail:

- If there are English double quotes on both sides, it indicates the BINARY(32) type. For example, `"abc"`.
- If there are double quotes on both sides and an L prefix, it means NCHAR(32) type. For example, `L"error message"`.
S
Sean Ely 已提交
37
- Spaces, equal signs (=), commas (,), and double quotes (") need to be escaped with a backslash (\\) in front. (All refer to the ASCII character)
38 39
- Numeric types will be distinguished from data types by the suffix.

40 41 42 43 44 45 46 47
| **Serial number** | **Postfix** | **Mapping type**              | **Size (bytes)** |
| ----------------- | ----------- | ----------------------------- | ---------------- |
| 1                 | None or 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                |
48 49 50

- `t`, `T`, `true`, `True`, `TRUE`, `f`, `F`, `false`, and `False` will be handled directly as BOOL types.

51
For example, the following string indicates that the one row of data is written to the st supertable with the t1 tag as "3" (NCHAR), the t2 tag as "4" (NCHAR), and the t3 tag as "t3" (NCHAR); the c1 column is 3 (BIGINT), the c2 column is false (BOOL), the c3 column is "passit" (BINARY), the c4 column is 4 (DOUBLE), and the primary key timestamp is 1626006833639000000.
52 53 54 55 56 57 58 59 60 61 62

```json
st,t1=3,t2=4,t3=t3 c1=3i64,c3="passit",c2=false,c4=4f64 1626006833639000000
```

Note that if the wrong case is used when describing the data type suffix, or if the wrong data type is specified for the data, it may cause an error message and cause the data to fail to be written.

## Main processing logic for schemaless writing

Schemaless writes process row data according to the following principles.

63
1. You can use the following rules to generate the subtable names: first, combine the measurement name and the key and value of the label into the next string:
64 65 66 67 68

```json
"measurement,tag_key1=tag_value1,tag_key2=tag_value2"
```

69
:::tip
70
Note that tag_key1, tag_key2 are not the original order of the tags entered by the user but the result of using the tag names in ascending order of the strings. Therefore, tag_key1 is not the first tag entered in the line protocol.
71 72
The string's MD5 hash value "md5_val" is calculated after the ranking is completed. The calculation result is then combined with the string to generate the table name: "t_md5_val". "t\_" is a fixed prefix that every table generated by this mapping relationship has.
:::
73

wmmhello's avatar
wmmhello 已提交
74
You can configure smlChildTableName in taos.cfg to specify table names, for example, `smlChildTableName=tname`. You can insert `st,tname=cpul,t1=4 c1=3 1626006833639000000` and the cpu1 table will be automatically created. Note that if multiple rows have the same tname but different tag_set values, the tag_set of the first row is used to create the table and the others are ignored.
75 76

2. If the super table obtained by parsing the line protocol does not exist, this super table is created.
77 78
   **Important:** Manually creating supertables for schemaless writing is not supported. Schemaless writing creates appropriate supertables automatically.

79
3. If the subtable obtained by the parse line protocol does not exist, Schemaless creates the sub-table according to the subtable name determined in steps 1 or 2.
80

81
4. If the specified tag or regular column in the data row does not exist, the corresponding tag or regular column is added to the super table (only incremental).
82 83 84

5. If there are some tag columns or regular columns in the super table that are not specified to take values in a data row, then the values of these columns are set to NULL.

85
6. For BINARY or NCHAR columns, if the length of the value provided in a data row exceeds the column type limit, the maximum length of characters allowed to be stored in the column is automatically increased (only incremented and not decremented) to ensure complete preservation of the data.
86

wmmhello's avatar
wmmhello 已提交
87
7. Errors encountered throughout the processing will interrupt the writing process and return an error code.
88

89
8. It is assumed that the order of field_set in a supertable is consistent, meaning that the first record contains all fields and subsequent records store fields in the same order. If the order is not consistent, set smlDataFormat in taos.cfg to false. Otherwise, data will be written out of order and a database error will occur.
90
   Note: TDengine 3.0.3.0 and later automatically detect whether order is consistent. This parameter is no longer used.
91 92

:::tip
93
All processing logic of schemaless will still follow TDengine's underlying restrictions on data structures, such as the total length of each row of data cannot exceed 48 KB and the total length of a tag value cannot exceed 16 KB. See [TDengine SQL Boundary Limits](/taos-sql/limit) for specific constraints in this area.
94 95 96 97 98 99
:::

## Time resolution recognition

Three specified modes are supported in the schemaless writing process, as follows:

100 101 102 103 104
| **Serial** | **Value**           | **Description**        |
| ---------- | ------------------- | ---------------------- |
| 1          | SML_LINE_PROTOCOL   | InfluxDB Line Protocol |
| 2          | SML_TELNET_PROTOCOL | OpenTSDB file protocol |
| 3          | SML_JSON_PROTOCOL   | OpenTSDB JSON protocol |
105

106
In InfluxDB line protocol mode, you must specify the precision of the input timestamp. Valid precisions are described in the following table.
107

108 109 110 111 112 113 114 115 116
| **No.** | **Precision**                     | **Description**       |
| ------- | --------------------------------- | --------------------- |
| 1       | TSDB_SML_TIMESTAMP_NOT_CONFIGURED | Not defined (invalid) |
| 2       | TSDB_SML_TIMESTAMP_HOURS          | Hours                 |
| 3       | TSDB_SML_TIMESTAMP_MINUTES        | Minutes               |
| 4       | TSDB_SML_TIMESTAMP_SECONDS        | Seconds               |
| 5       | TSDB_SML_TIMESTAMP_MILLI_SECONDS  | Milliseconds          |
| 6       | TSDB_SML_TIMESTAMP_MICRO_SECONDS  | Microseconds          |
| 7       | TSDB_SML_TIMESTAMP_NANO_SECONDS   | Nanoseconds           |
117

118
In OpenTSDB file and JSON protocol modes, the precision of the timestamp is determined from its length in the standard OpenTSDB manner. User input is ignored.
119

120
## Data Model Mapping
121

122
This section describes how data in InfluxDB line protocol is mapped to a schema. The data measurement in each line is mapped to a supertable name. The tag name in tag_set is the tag name in the schema, and the name in field_set is the column name in the schema. The following example shows how data is mapped:
123 124 125 126 127

```json
st,t1=3,t2=4,t3=t3 c1=3i64,c3="passit",c2=false,c4=4f64 1626006833639000000
```

128
This row is mapped to a supertable: `st` contains three NCHAR tags: t1, t2, and t3. Five columns are created: ts (timestamp), c1 (bigint), c3 (binary), c2 (bool), and c4 (bigint). The following SQL statement is generated:
129 130 131 132 133

```json
create stable st (_ts timestamp, c1 bigint, c2 bool, c3 binary(6), c4 bigint) tags(t1 nchar(1), t2 nchar(1), t3 nchar(2))
```

134
## Processing Schema Changes
135

136
This section describes the impact on the schema caused by different data being written.
137

sangshuduo's avatar
sangshuduo 已提交
138
If you use line protocol to write to a specific tag field and then later change the field type, a schema error will occur. This triggers an error on the write API. This is shown as follows:
139 140

```json
141 142
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
143 144
```

145
The first row defines c4 as a double. However, in the second row, the suffix indicates that the value of c4 is a bigint. This causes schemaless writing to throw an error.
146

147
An error also occurs if data input into a binary column exceeds the defined length of the column.
148 149

```json
150 151
st,t1=3,t2=4,t3=t3 c1=3i64,c5="pass"     1626006833639000000
st,t1=3,t2=4,t3=t3 c1=3i64,c5="passit"   1626006833640000000
152 153
```

154
The first row defines c5 as a binary(4). but the second row writes 6 bytes to it. This means that the length of the binary column must be expanded to contain the data.
155 156

```json
157 158
st,t1=3,t2=4,t3=t3 c1=3i64               1626006833639000000
st,t1=3,t2=4,t3=t3 c1=3i64,c6="passit"   1626006833640000000
159 160
```

161
The preceding data includes a new entry, c6, with type binary(6). When this occurs, a new column c6 with type binary(6) is added automatically.
162

163
## Write Integrity
164

165
TDengine guarantees the idempotency of data writes. This means that you can repeatedly call the API to perform write operations with bad data. However, TDengine does not guarantee the atomicity of multi-row writes. In a multi-row write, some data may be written successfully and other data unsuccessfully.
166

167
## Error Codes
168

169 170 171
The TSDB_CODE_TSC_LINE_SYNTAX_ERROR indicates an error in the schemaless writing component.
This error occurs when writing text. For other errors, schemaless writing uses the standard TDengine error codes
found in taos_errstr.