GO操作Taos数据库

前言

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数据库的性能还是不错的,特别是物联网情景下,包括数据库的设计也是非常合理的。值得体验一下。

你可能感兴趣的:(GO操作Taos数据库)