static void Main(string[] args)
{
var bag = GetData("D:user.csv");
List<StringBuilder> listbuilder = new List<StringBuilder>();
StringBuilder sb = new StringBuilder();
for (int i = 0; i < bag.Count; i++)
{
if (i % 1000 == 0)
{
sb = new StringBuilder();
listbuilder.Add(sb);
//sb.Append("insert into mesh(x,y,z) values");
sb.Append($"{bag[i].x}, {bag[i].y}, {bag[i].z}");
}
else
sb.Append($",{bag[i].x}, {bag[i].y}, {bag[i].z}");
}
StringBuilder sbp = new StringBuilder();
sbp.Append("PREPARE insertplan (");
for (int i = 0; i < 1000; i++)
{
sbp.Append("int,int,int,");
}
sbp.Remove(sbp.Length - 1, 1);
sbp.Append(") AS INSERT INTO mesh(x, y, z) values");
for (int i = 0; i < 1000; i++)
{
sbp.Append($"(${i*3 + 1},${i* 3 + 2},${i*3+ 3}),");
}
sbp.Remove(sbp.Length - 1, 1);
TimeCalc.LogStartTime();
using (var sm = new SqlManipulation(@"string", SqlType.PostgresQL))
{
sm.Init();
sm.ExcuteNonQuery(sbp.ToString());
foreach (var n in listbuilder)
{
sm.ExcuteNonQuery($"EXECUTE insertplan({n.ToString()})");
}
}
TimeCalc.ShowTotalDuration();
Console.ReadKey();
}
使用Transaction
在前面的基础上,使用事务改造。每条语句插入1000条数据,每1000条作为一个事务,CPU 30%,磁盘34MB/S,耗时170.16s。
改成100条一个事务,耗时167.78s。
使用多线程
还在前面的基础上,使用多线程,每个线程建立一个连接,一个连接处理100条sql语句,每条sql语句插入1000条数据,以此种方式进行导入。注意,连接字符串可以将maxpoolsize设置大一些,我机器上实测,不设置会报连接超时错误。
CPU占用率上到80%, 磁盘这里需要注意,由于生成了非常多个Postgresql server进程,不好统计,累积算上应该有小100MB/S,最终时间,98.18s。
使用TPL,由于Parallel.ForEach返回的结果没有检查,可能导致时间不是很准确(偏小)。
var lists = new List<List<string>>();
var listt = new List<string>();
for (int i = 0; i < listbuilder.Count; i++)
{
if (i % 1000 == 0)
{
listt = new List<string>();
lists.Add(listt);
}
listt.Add(listbuilder[i].ToString());
}
TimeCalc.LogStartTime();
Parallel.ForEach(lists, (x) =>
{
using (var sm = new SqlManipulation(@";string;MaxPoolSize=1000;", SqlType.PostgresQL))
{
sm.Init();
foreach (var n in x)
{
sm.ExcuteNonQuery(n);
}
}
});
TimeCalc.ShowTotalDuration();








