最近在寻找时序数据库,想应用在公司的项目上。
上一篇文章实验了InfluxDB:windows上使用influx2.7学习,还学习了flux语言,最后发现宽表查询比较困难,就放弃了,于是决定试试国产时序数据库TDengine
参考
官方文档:https://docs.taosdata.com/
windows安装TDengine
从3.0.71版本之后,TDengine就不提供Server版本的安装包了:
那就安装3.0.71
版本吧,下载地址:https://www.taosdata.com/assets-download/3.0/TDengine-server-3.0.7.1-Windows-x64.exe
下载之后,点击安装,会默认安装到C:\TDengine
目录下:
点击taosd.exe
即可运行TDengine数据库服务
2000万示例数据
我准备了一个csv数据,可百度网盘下载:链接:https://pan.baidu.com/s/1FlcFkh8cF1WEAOMrmrb9JQ?pwd=o579
提取码:o579,有4G多(解压后的csv文件),大概有19610118
条数据,最后全部写入到tdengine,只占500M不到,非常节省空间
创建数据库
打开taos.exe
,输入如下命令,创建一个名称叫tony
的数据库
create database tony precision 'ns'
注意1:precision 'ns'
这一句是让数据库支持纳秒,不加这句的话默认是毫秒。需要支持纳秒的原因:因为在读取data.csv的行的时候,生成sql语句的ts
字段用的是DateTime.Now
,需要数据库支持纳秒来区分时间,否则插入的ts有可能一样,会被当做更新行。
注意2:最新版本的TDengine(截止到写文章的时候,是3.2.3.0
)的linux安装包版本使用precision 'ns'
无效,亲测,可能是自己的使用方式不对,所以想跟着本文章学习,最好使用3.0.71
版本
编写C#程序写入数据
使用C#,将data.csv
中的19610118
条数据写入到数据库
创建一个控制台程序,引用Nuget:
<PackageReference Include="TDengine.Connector" Version="3.1.2" />
编写代码如下(包含自动创建表):
// See https://aka.ms/new-console-template for more information
using System.Diagnostics;
using TDengine.Driver;
using TDengine.Driver.Client;
Console.WriteLine("Hello, World!");
var builder = new ConnectionStringBuilder("host=localhost;port=6030;username=root;password=taosdata");
using (var client = DbDriver.Open(builder))
{
Console.WriteLine("connected");
var affectRow = client.Exec(@"create TABLE IF NOT exists tony.batinfo(
ts timestamp,
batcode varchar(50),
logintime varchar(50),
devicecode varchar(20),
processid int,
flowid int,
batterypos int,
capacity1 float ,
capacity2 float ,
voltage1 float ,
voltage2 float ,
current1 float ,
current2 float ,
ocv1 float ,
ocv2 float ,
ir1 float ,
ir2 float,
batid float
);");
if (affectRow > 0)
{
Console.WriteLine("create table success!");
}
string csvPath = "G:\\BatInfo_2021\\data.csv";
//写入
Stopwatch stopwatch = Stopwatch.StartNew();
using (var stream = new StreamReader(csvPath))
{
int count = 0;
int totalCount = 0;
while (true)
{
var line = await stream.ReadLineAsync();
if (line == null) break;
count++;
totalCount++;
if (totalCount == 1) continue;//第1行舍弃
var strs = line.Split(',');
if (count >= 10000)
{
count = 0;
Console.WriteLine($"has read {totalCount} lines,ellapse time {stopwatch.ElapsedMilliseconds / (double)1000} seconds");
}
var batCodeStr = strs[0];
var loginTimeStr = strs[1];
var deviceCodeStr = strs[2];
var processIdStr = strs[3];
var flowIdStr = strs[4];
var batteryPos = strs[7];
var capacity1Str = strs[12];
var capacity2Str = strs[13];
var voltage1Str = strs[18];
var voltage2Str = strs[19];
var current1Str = strs[24];
var current2Str = strs[25];
var ocv1Str = strs[28];
var ocv2Str = strs[29];
var ir1Str = strs[33];
var ir2Str = strs[34];
var batIdStr = strs[71];
var sql = @$"insert into tony.batinfo values(
'{DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss.ffffff")}',
'{batCodeStr}',
'{loginTimeStr}',
'{deviceCodeStr}',
{ConvertToDouble(processIdStr, 0)},
{ConvertToDouble(flowIdStr, 0)},
{ConvertToDouble(batteryPos, 0)},
{ConvertToDouble(capacity1Str, 0)},
{ConvertToDouble(capacity2Str, 0)},
{ConvertToDouble(voltage1Str, 0)},
{ConvertToDouble(voltage2Str, 0)},
{ConvertToDouble(current1Str, 0)},
{ConvertToDouble(current2Str, 0)},
{ConvertToDouble(ocv1Str, 0)},
{ConvertToDouble(ocv2Str, 0)},
{ConvertToDouble(ir1Str, 0)},
{ConvertToDouble(ir2Str, 0)},
{ConvertToDouble(batIdStr, 0)})";
try
{
affectRow = client.Exec(sql);
if (affectRow <= 0) { Console.WriteLine($"affect row:{affectRow}"); }
}
catch (Exception e)
{
Console.WriteLine($"Error:{e.Message}");
}
}
}
Console.WriteLine($"finish,ellapse total seconds:{stopwatch.ElapsedMilliseconds / (double)1000}");
}
double ConvertToDouble(string str, double defalutValue)
{
if (double.TryParse(str, out var v)) return v;
return defalutValue;
}
运行完成后,数据插入成功。
数据查询体验
点击taos.exe
即可开启查询。
注意:TDengine以上都没有给任何列添加索引!!!
查询数据总量
使用tdengine查询数据总量耗时0.03s
相同数据量的SQL SERVER查询,耗时0.63s
查询电压平均值
计算将近2千万数字的平均值大概时间为0.04s
查询电压大于3500小于3600的记录最多10条
耗时0.2s
查询BatCode='111’的数据有多少条
耗时1.88s