数据类型 #

一、数据模型回顾 #

1.1 数据点结构 #

text
数据点(Point)结构:

┌─────────────────────────────────────────────────────┐
│                    Measurement                      │
│                    (度量名称)                        │
├─────────────────────────────────────────────────────┤
│  Tags (标签)          │  Fields (字段)              │
│  ┌─────────────────┐  │  ┌─────────────────────┐   │
│  │ host=server01   │  │  │ value=78.5 (float)  │   │
│  │ region=us-west  │  │  │ count=100 (int)     │   │
│  │ env=production  │  │  │ enabled=true (bool) │   │
│  └─────────────────┘  │  │ message="ok" (str)  │   │
│                       │  └─────────────────────┘   │
├─────────────────────────────────────────────────────┤
│                   Timestamp                         │
│                  (时间戳)                           │
│              1704067200000000000                    │
└─────────────────────────────────────────────────────┘

1.2 Tags vs Fields #

text
Tags和Fields对比:

特性          Tags                    Fields
───────────────────────────────────────────────────
存储内容      元数据                  实际数据值
索引          是                      否
数据类型      仅字符串                多种类型
查询效率      高(索引)              较低
分组查询      适合                    不适合
修改          不建议频繁修改          可随时修改

二、字段数据类型 #

2.1 浮点数(Float) #

text
浮点数类型:

特点
├── 默认数值类型
├── IEEE 754 64位浮点数
└── 支持科学计数法

行协议示例
├── temperature value=23.5
├── temperature value=1.5e3
└── temperature value=-0.5

精度
├── 有效数字:约15-17位
├── 范围:±1.7976931348623157e308
└── 最小正数:约5e-324
flux
// Flux中使用浮点数
value = 23.5
scientific = 1.5e3
negative = -0.5

// 类型检查
float(v: "23.5")  // 字符串转浮点

2.2 整数(Integer) #

text
整数类型:

特点
├── 64位有符号整数
├── 行协议中需加 i 后缀
└── 不支持小数点

行协议示例
├── counter count=100i
├── counter count=-50i
└── counter count=0i

范围
├── 最小值:-9223372036854775808
└── 最大值:9223372036854775807
flux
// Flux中使用整数
count = 100i
negative = -50i

// 类型转换
int(v: "100")   // 字符串转整数
int(v: 23.5)    // 浮点转整数

2.3 字符串(String) #

text
字符串类型:

特点
├── UTF-8编码
├── 双引号包裹
└── 支持转义字符

行协议示例
├── log message="Hello World"
├── log message="Hello \"World\""
└── log message="Line1\nLine2"

转义字符
├── \" - 双引号
├── \\ - 反斜杠
├── \n - 换行
└── \t - 制表符
flux
// Flux中使用字符串
name = "InfluxDB"
message = "Hello, World!"

// 多行字符串
text = "
这是一个
多行字符串
"

// 字符串操作
strings.toUpper(v: "influxdb")
strings.toLower(v: "INFLUXDB")

2.4 布尔值(Boolean) #

text
布尔类型:

特点
├── true 或 false
├── 行协议中无引号
└── 大小写敏感

行协议示例
├── status enabled=true
├── status enabled=false
├── status enabled=t
├── status enabled=f
├── status enabled=T
└── status enabled=F

支持的表示
├── true: true, t, True, T, TRUE
└── false: false, f, False, F, FALSE
flux
// Flux中使用布尔值
enabled = true
disabled = false

// 比较结果
isGreater = 10 > 5  // true
isEqual = 1 == 2    // false

// 逻辑运算
result = true and false  // false
result = true or false   // true
result = not true        // false

2.5 无符号整数(Unsigned Integer) #

text
无符号整数类型:

特点
├── 64位无符号整数
├── 行协议中需加 u 后缀
└── 仅支持非负数

行协议示例
├── counter total=18446744073709551615u
└── counter bytes=1024u

范围
├── 最小值:0
└── 最大值:18446744073709551615
flux
// Flux中使用
uint(v: "100")   // 字符串转无符号整数
uint(v: 100i)    // 整数转无符号整数

三、时间戳类型 #

3.1 时间戳格式 #

text
时间戳格式:

Unix时间戳
├── 纳秒精度(默认)
├── 19位数字
└── 例:1704067200000000000

精度选项
├── ns - 纳秒
├── us - 微秒
├── ms - 毫秒
├── s - 秒
└── RFC3339格式

3.2 写入时间戳 #

bash
# 纳秒精度(默认)
temperature value=23.5 1704067200000000000

# 毫秒精度
curl -X POST "http://localhost:8086/api/v2/write?precision=ms" \
    --data "temperature value=23.5 1704067200000"

# 秒精度
curl -X POST "http://localhost:8086/api/v2/write?precision=s" \
    --data "temperature value=23.5 1704067200"

# RFC3339格式
temperature value=23.5 2024-01-01T00:00:00Z

3.3 Flux时间操作 #

flux
import "date"

// 当前时间
now()

// 解析时间
time(v: "2024-01-01T00:00:00Z")

// Unix时间戳转换
uint(v: now())  // 转为纳秒时间戳

// 时间计算
future = date.add(t: now(), d: 1h)
past = date.sub(t: now(), d: 1h)

// 时间截断
hourStart = date.truncate(t: now(), unit: 1h)
dayStart = date.truncate(t: now(), unit: 1d)

四、标签数据类型 #

4.1 标签特点 #

text
标签特点:

数据类型
├── 仅支持字符串
├── 自动转换为字符串
└── 存储为UTF-8编码

索引特性
├── 自动创建索引
├── 快速查询
└── 适合分组

限制
├── 值长度:无限制(建议<100字节)
├── 标签数量:建议<10个
└── 基数:建议<10,000个不同值

4.2 标签使用示例 #

bash
# 标签值自动为字符串
cpu,host=server01,region=us-west,env=production value=78.5

# 数字也会转为字符串
cpu,core=0 value=45.2

# 布尔值转为字符串
cpu,enabled=true value=45.2

4.3 Flux中的标签 #

flux
from(bucket: "metrics")
    |> range(start: -1h)
    |> filter(fn: (r) => r.host == "server01")  // 标签过滤

// 标签值始终是字符串
from(bucket: "metrics")
    |> range(start: -1h)
    |> filter(fn: (r) => r.core == "0")  // 即使是数字也要用字符串比较

五、Flux数据类型 #

5.1 基本类型 #

flux
// 基本类型

// 字符串
str = "hello"

// 整数
int = 100i

// 无符号整数
uint = 100u

// 浮点数
float = 23.5

// 布尔值
bool = true

// 时间
time = 2024-01-01T00:00:00Z

// 持续时间
duration = 1h30m

// 正则表达式
regex = /^server\d+$/

// 字节
bytes = bytes("hello")

5.2 复合类型 #

flux
// 数组
arr = [1, 2, 3, 4, 5]

// 字典
dict = {
    key1: "value1",
    key2: "value2"
}

// 记录
record = {
    name: "cpu",
    value: 78.5,
    time: now()
}

// 函数
add = (a, b) => a + b

5.3 空值 #

flux
// 空值处理
value = null

// 检查空值
if exists value then value else 0

// 过滤空值
from(bucket: "my-bucket")
    |> range(start: -1h)
    |> filter(fn: (r) => exists r._value)

六、类型转换 #

6.1 基本转换函数 #

flux
// 字符串转换
string(v: 100)           // "100"
string(v: 23.5)          // "23.5"
string(v: true)          // "true"

// 整数转换
int(v: "100")            // 100i
int(v: 23.5)             // 23i(截断)
int(v: true)             // 1i

// 浮点数转换
float(v: "23.5")         // 23.5
float(v: 100i)           // 100.0

// 布尔转换
bool(v: "true")          // true
bool(v: 1i)              // true
bool(v: 0i)              // false

// 时间转换
time(v: "2024-01-01T00:00:00Z")
time(v: 1704067200000000000)

6.2 查询中转换 #

flux
// 字段值类型转换
from(bucket: "my-bucket")
    |> range(start: -1h)
    |> filter(fn: (r) => r._measurement == "cpu")
    |> map(fn: (r) => ({ 
        r with 
        _value: float(v: r._value) 
    }))

// 标签值转换
from(bucket: "my-bucket")
    |> range(start: -1h)
    |> map(fn: (r) => ({ 
        r with 
        coreNum: int(v: r.core) 
    }))

七、行协议中的类型 #

7.1 语法规则 #

text
行协议语法:

measurement[,tag_key=tag_value...] field_key=field_value[,field_key=field_value...] [timestamp]

示例:
cpu,host=server01,region=us-west usage=78.5,idle=21.5i,enabled=true 1704067200000000000

组成部分:
├── measurement: cpu
├── tags: host=server01,region=us-west
├── fields: usage=78.5,idle=21.5i,enabled=true
└── timestamp: 1704067200000000000

7.2 类型后缀 #

text
字段类型后缀:

类型          后缀        示例
────────────────────────────────
浮点数        无          value=23.5
整数          i           count=100i
字符串        " "         msg="hello"
布尔值        无          enabled=true
无符号整数    u           total=100u

7.3 转义规则 #

text
需要转义的字符:

元素          需要转义的字符
────────────────────────────────
measurement   , (逗号), 空格
tag key       , (逗号), = (等号), 空格
tag value     , (逗号), = (等号), 空格
field key     , (逗号), = (等号), 空格
field value   " (双引号), \ (反斜杠)

转义方法:使用反斜杠 \
weather,location=us\ midwest temperature=82 1465839830100400200

八、类型最佳实践 #

8.1 选择正确的类型 #

text
类型选择建议:

数值数据
├── 需要小数 → float
├── 整数计数 → integer
├── 大数值ID → unsigned integer
└── 百分比 → float

文本数据
├── 用于分组/过滤 → tag
├── 用于存储值 → field (string)
└── 长文本 → field (string)

布尔数据
├── 状态标记 → field (boolean)
└── 分类标识 → tag

时间数据
├── 事件时间 → timestamp
└── 时间间隔 → duration

8.2 标签vs字段选择 #

text
选择决策树:

数据是否用于分组/过滤?
├── 是 → 使用Tag
└── 否 → 数据是否需要计算?
          ├── 是 → 使用Field (数值类型)
          └── 否 → 使用Field (字符串类型)

示例:
├── host, region, env → Tag
├── CPU使用率, 温度 → Field (float)
├── 请求计数 → Field (integer)
├── 状态消息 → Field (string)
└── 启用状态 → Field (boolean)

8.3 基数考虑 #

text
基数管理:

低基数(适合Tag)
├── 主机名:< 1000
├── 区域:< 50
├── 环境:< 10
└── 状态:< 10

高基数(使用Field)
├── 用户ID:> 10000
├── 时间戳:无限
├── 随机值:无限
└── 日志消息:无限

警告信号
├── 标签值快速增长
├── 内存使用增加
└── 查询变慢

九、类型检查 #

9.1 Flux类型检查 #

flux
// 类型检查函数
strings.isString(v: "hello")    // true
ints.isInt(v: 100i)             // true
floats.isFloat(v: 23.5)         // true
bools.isBool(v: true)           // true

// 类型断言
from(bucket: "my-bucket")
    |> range(start: -1h)
    |> filter(fn: (r) => floats.isFloat(v: r._value))

9.2 类型错误处理 #

flux
// 安全类型转换
safeInt = (v) => {
    if exists v and ints.isInt(v: v) then v
    else 0i
}

// 处理混合类型
from(bucket: "my-bucket")
    |> range(start: -1h)
    |> map(fn: (r) => ({ 
        r with 
        _value: if floats.isFloat(v: r._value) then r._value 
                else float(v: r._value)
    }))

十、完整示例 #

10.1 多类型数据写入 #

bash
# 写入包含多种类型的数据
curl -X POST "http://localhost:8086/api/v2/write?org=my-org&bucket=my-bucket" \
    --header "Authorization: Token YOUR_TOKEN" \
    --data '
system,host=server01,region=us-west cpu=78.5,memory=8192i,uptime=86400i,enabled=true,message="running"
system,host=server02,region=us-east cpu=45.2,memory=4096i,uptime=43200i,enabled=false,message="stopped"
'

10.2 类型转换查询 #

flux
// 查询并转换类型
from(bucket: "metrics")
    |> range(start: -1h)
    |> filter(fn: (r) => r._measurement == "system")
    |> map(fn: (r) => ({
        r with
        _value: float(v: r._value),
        uptime_hours: int(v: r.uptime) / 3600i
    }))

10.3 类型聚合 #

flux
// 按类型分组聚合
from(bucket: "metrics")
    |> range(start: -1h)
    |> filter(fn: (r) => r._measurement == "system")
    |> group(columns: ["_field"])
    |> mean()

十一、总结 #

数据类型要点:

  1. 字段类型多样:float、integer、string、boolean、uint
  2. 标签仅字符串:用于索引和分组
  3. 时间戳精确:支持纳秒精度
  4. 类型转换灵活:Flux提供丰富的转换函数
  5. 基数管理重要:合理选择标签和字段

下一步,让我们学习Bucket操作!

最后更新:2026-03-27