前言
go 语言操作 TDengine 可以说是非常简单了,今天我们就记录一下操作流程
其实操作基本都是使用 原生SQL 在操作。
代码
package TDengine
import (
"database/sql"
"fmt"
_ "mydt/taosSql"
"strconv"
"time"
)
func InitTaos() {
url := fmt.Sprintf("%s:%s@/tcp(%s:%d)/%s?interpolateParams=true", "root", "taosdata", "127.0.0.1", 6030, "log")
db, err := sql.Open("taosSql", url)
if err != nil {
fmt.Printf("error on: sql.open %s", err.Error())
return
}
defer db.Close()
dropDatabase(db, "mydt")
createDatabase(db, "mydt")
createSTable(db, "mydt", "scamera")
// dropSTable(db,"mydt", "scamera")
createTableUseS(db, "mydt", "scamera", "camera")
//insertData(db, "mydt", "camera")
for i := 0; i < 12; i++ {
go insertDataTest(i, "mydt", "camera")
}
time.Sleep(10 * time.Minute)
return
}
// dropDatabase 删除数据库
/*
DROP DATABASE [IF EXISTS] db_name;
*/
func dropDatabase(db *sql.DB, dbName string) {
sqlStr := "drop database if exists " + dbName+";"
_, err := db.Exec(sqlStr)
checkErr(err, sqlStr)
}
// createDatabase 创建数据库
/*
CREATE DATABASE [IF NOT EXISTS] db_name [KEEP keep] [DAYS days] [UPDATE 1];
KEEP是该数据库的数据保留多长天数,缺省是3650天(10年),数据库会自动删除超过时限的数据;
DAYS: (个人理解)未来最大时间,例如存储未来10天以内的时间,超过的删除掉
UPDATE 标志数据库支持更新相同时间戳数据;
*/
func createDatabase(db *sql.DB, dbName string) {
// 创建数据库
sqlStr := "create database " + dbName + " keep " + strconv.Itoa(365 * 20) + " days " + strconv.Itoa(30)+";"
_, err := db.Exec(sqlStr)
checkErr(err, sqlStr)
}
// createSTable 创建超级表
/*
CREATE STABLE [IF NOT EXISTS] stb_name (timestamp_field_name TIMESTAMP, field1_name data_type1 [, field2_name data_type2 ...]) TAGS (tag1_name tag_type1, tag2_name tag_type2 [, tag3_name tag_type3]);
1) TAGS 列的数据类型不能是 timestamp 类型;
2) TAGS 列名不能与其他列名相同;
3) TAGS 列名不能为预留关键字;
4) TAGS 最多允许 128 个,至少 1 个,总长度不超过 16 KB。
*/
func createSTable(db *sql.DB, dbName, supTblName string){
// 这一指令中的 STABLE 关键字,在 2.0.15 之前的版本中需写作 TABLE 。
sqlStr := "create stable if not exists " + dbName + "." + supTblName + " (ts timestamp, name BINARY(32), age INT, isAlarm BOOL) tags(location nchar(64), groupId int);"
_, err := db.Exec(sqlStr)
checkErr(err, sqlStr)
}
// dropSTable 删除超级表
/*
DROP STABLE [IF EXISTS] stb_name;
删除 STable 会自动删除通过 STable 创建的子表
*/
func dropSTable(db *sql.DB, dbName, supTblName string) {
// TODO is exists 依然会报错
sqlStr := "drop stable if exists " + dbName + "." + supTblName + ";"
fmt.Printf("sqlStr: %s \n", sqlStr)
_, err := db.Exec(sqlStr)
checkErr(err, sqlStr)
}
// createTable 以超级表为模板创建数据表
/*
// 使用超级表的所有tag
CREATE TABLE [IF NOT EXISTS] tb_name USING stb_name TAGS (tag_value1, ...);
// 使用超级表的部分tag
CREATE TABLE [IF NOT EXISTS] tb_name USING stb_name (tag_name1, ...) TAGS (tag_value1, ...);
*/
func createTableUseS(db *sql.DB, dbName, sTableName, tableName string){
sqlStr := "create table if not exists " + dbName + "." + tableName + " using " + dbName + "." + sTableName +" tags('location', 2);"
//fmt.Printf("sqlStr: %v\n", sqlStr)
_, err := db.Exec(sqlStr)
checkErr(err, sqlStr)
}
// createTable 创建普通表
/*
CREATE TABLE [IF NOT EXISTS] tb_name (timestamp_field_name TIMESTAMP, field1_name data_type1 [, field2_name data_type2 ...]);
1) 表的第一个字段必须是 TIMESTAMP,并且系统自动将其设为主键;
2) 表名最大长度为 192;
3) 表的每行长度不能超过 16k 个字符;(注意:每个 BINARY/NCHAR 类型的列还会额外占用 2 个字节的存储位置)
4) 子表名只能由字母、数字和下划线组成,且不能以数字开头
5) 使用数据类型 binary 或 nchar,需指定其最长的字节数,如 binary(20),表示 20 字节;
*/
func createTable(db *sql.DB, dbName, tableName string) {
sqlStr := "create table if not exists " + dbName + "." + tableName + " (id TIMESTAMP, name BINARY(32), age INT, isAlarm BOOL);"
//fmt.Printf("sqlStr: %v\n", sqlStr)
_, err := db.Exec(sqlStr)
checkErr(err, sqlStr)
}
// dropTable 删除数据表
/*
DROP TABLE [IF EXISTS] tb_name;
*/
func dropTable(db *sql.DB, dbName, tableName string) {
sqlStr := "drop table if exists " + dbName + "." + tableName +";"
//fmt.Printf("sqlStr: %v\n", sqlStr)
_, err := db.Exec(sqlStr)
checkErr(err, sqlStr)
}
// insertData 插入数据
/*
INSERT INTO tb_name VALUES (field_value, ...);
INSERT INTO tb_name (field1_name, ...) VALUES (field1_value1, ...);
INSERT INTO tb_name VALUES (field1_value1, ...) (field1_value2, ...) ...;
INSERT INTO tb_name (field1_name, ...) VALUES (field1_value1, ...) (field1_value2, ...) ...;
INSERT INTO tb1_name VALUES (field1_value1, ...) (field1_value2, ...) ...
tb2_name VALUES (field1_value1, ...) (field1_value2, ...) ...;
INSERT INTO tb1_name (tb1_field1_name, ...) VALUES (field1_value1, ...) (field1_value2, ...) ...
tb2_name (tb2_field1_name, ...) VALUES (field1_value1, ...) (field1_value2, ...) ...;
*/
func insertData(db *sql.DB, dbName, tableName string) {
timestamp := time.Now().Unix() *1000
sqlStr := "insert into " + dbName + "." + tableName + " values (" + strconv.FormatInt(timestamp, 10) + ", 'zzx', 28, true);"
//fmt.Printf("sqlStr: %v\n", sqlStr)
_, err := db.Exec(sqlStr)
checkErr(err, sqlStr)
}
// 插入速度测试
func insertDataTest(goi int, dbName, tableName string) {
url := fmt.Sprintf("%s:%s@/tcp(%s:%d)/%s?interpolateParams=true", "root", "taosdata", "127.0.0.1", 6030, "log")
db, err := sql.Open("taosSql", url)
if err != nil {
fmt.Printf("error on: sql.open %s", err.Error())
return
}
defer db.Close()
num := 10000
timestamp := time.Now().Unix() *1000 - int64((goi+1) * num * 2)
//var err error
start := time.Now() // 获取当前时间
for i := 0; i < num; i++ {
if i%(num/10) == 0 {
fmt.Printf("insert: %v 条;time= %v\n", i, time.Now().Format("15:04:05"))
}
timestamp++
sqlStr := "insert into " + dbName + "." + tableName + " values (" + strconv.FormatInt(timestamp, 10) + ", 'zzx', 28, true);"
//fmt.Printf("sqlStr: %v\n", sqlStr)
_, _ = db.Exec(sqlStr)
//checkErr(err, sqlStr)
}
elapsed := time.Since(start)
fmt.Printf("携程%v完成耗时:%v \n",goi, elapsed)
}
// 查询数据数量
/*
SELECT COUNT(*) FROM DBNAME;
*/
func count(db *sql.DB, dbName, tableName string) {
sqlStr := "select count(*) from " + dbName + "." + tableName +";"
//fmt.Printf("sqlStr: %v\n", sqlStr)
_, err := db.Exec(sqlStr)
checkErr(err, sqlStr)
}
func checkErr(err error, prompt string) {
fmt.Printf("sqlStr: %s\n", prompt)
if err != nil {
panic(err)
}
}
后记
上面记录了 taos 数据库的基本操作,也有一些更复杂的操作,我们可以查看官网学习。
体会
taos数据库的性能还是不错的,特别是物联网情景下,包括数据库的设计也是非常合理的。值得体验一下。
网友评论