求助帖:C#数千万数据处理问题——————大侠请指教

Apple 2011-10-29 07:01:28
大侠们好,
现在项目中遇到这么一个问题:项目需要把原Maximo系统(PS:IBM的设备管理系统)中的部分数据抓过来,比如:工单、资
产、备件等表中的相关字段信息,Maximo原系统中的源表很多、源表中的字段很复杂,现项目并不需要所有的源表信息,所以
需要从Maximo系统库的表中抽取相关表的相关字段出来,把这些字段组合成一条数据

涉及到的数据处理情况比如:a、单张工单的维修人员是多个维修人员,此时多个人员姓名需要合并为一个字符串
b、工单描述、备注等字段中的特殊字符需要处理,比如“)'”同时出现,可能影响插 入SQL语句的执行
c、多表关联查询
d、以及其他各种处理情况,这里就不一一列举了

提示:需要处理的Maximo源表的数据量都非常巨大,1千万+++++,Oracle10g数据库


目前的处理方法:
现在是写了一个winform程序来进行处理,就是每次读取主表的200条数据,然后遍历主表数据行,根据主表行的关键字段分布到各个表中再去查询相关需要的字段信息,这样拼出一条数据InsertSql寄存在一个ArryList中,200行主表数据遍历完成之后再执行带数据库事务的批量插入操作,当段数据插入之后,标识字段+200再进行下一路的主表数据读取及插入,以此循环
现在遇到的问题是:1、每200条主表数据的轮询过程,几分钟不等,速度太慢了,处理完几千万数据不知要多久
2、程序执行好几个小时后会发生未知错误,不是数据查询、插入等的错误



希望能够给予帮助的大侠们看到帖子能及时给予回复,不胜感激。

一段简单的数据处理日志记录:
1 2011-10-29 18:59:09 **********WorkOrderID当前已执行位置:startID=106201; endID=106401**********
2 2011-10-29 18:59:09 **********工单资产信息行数:63**********
3 2011-10-29 18:59:09 **********成功执行Insert Sql语句条数:121行**********
4 2011-10-29 18:57:13 **********工单资产信息行数:64**********
5 2011-10-29 18:57:13 **********成功执行Insert Sql语句条数:0行**********
6 2011-10-29 18:57:13 **********工单资产信息行数:0**********
7 2011-10-29 18:57:13 **********WorkOrderID当前已执行位置:startID=106001; endID=106201**********
8 2011-10-29 18:57:12 **********成功执行Insert Sql语句条数:6行**********
9 2011-10-29 18:57:12 **********WorkOrderID当前已执行位置:startID=105801; endID=106001**********
10 2011-10-29 18:57:04 **********WorkOrderID当前已执行位置:startID=105601; endID=105801**********
11 2011-10-29 18:57:04 **********工单资产信息行数:5**********
12 2011-10-29 18:57:04 **********成功执行Insert Sql语句条数:64行**********
13 2011-10-29 18:55:56 **********WorkOrderID当前已执行位置:startID=105401; endID=105601**********
14 2011-10-29 18:55:56 **********成功执行Insert Sql语句条数:3行**********
15 2011-10-29 18:55:56 **********工单资产信息行数:38**********
16 2011-10-29 18:55:53 **********成功执行Insert Sql语句条数:143行**********
17 2011-10-29 18:55:53 **********工单资产信息行数:2**********
18 2011-10-29 18:55:53 **********WorkOrderID当前已执行位置:startID=105201; endID=105401**********
19 2011-10-29 18:53:48 **********成功执行Insert Sql语句条数:115行**********
20 2011-10-29 18:53:48 **********工单资产信息行数:70**********
21 2011-10-29 18:53:48 **********WorkOrderID当前已执行位置:startID=105001; endID=105201**********



C#数据处理的主要方法贴上,请大侠指教,谢谢了:


public void RunDataPanel()
{
da.SaveLogs("WorkOrderID当前已执行位置:startID=" + startID + "; endID=" + endID);

string strSql = string.Empty;

strSql = "select distinct a.assetnum 资产编号,a.description 设备名称,w.wonum 工单号,w.description 工单描述,w.worktype 工单类型,w.FAILDATE 日期,w.SiteID,w.WO20 ";
strSql += "from workorder w,asset a ";
strSql += "where w.worktype not in ('MR','MQ') and a.siteid = w.siteid and a.assetnum = w.assetnum ";
strSql += "and workorderid>=" + startID + " and workorderid<" + endID + "";

//资产工单信息
DataTable dt = da.RunSelectSQL(strSql);
da.SaveLogs("工单资产信息行数:" + dt.Rows.Count);

//插入SQL语句集合
ArrayList sqlArr = new ArrayList();
//维修记录ID
int CMID = da.GetMaxID("ID", "ENQ_DEVICESERVICE");
//维修更换配件ID
int WXPJID = da.GetMaxID("ID", "ENQ_SERVICEPARTS");
//维修步骤ID
int BZID = da.GetMaxID("ID", "ENQ_SERVICEBZ");

//维保记录ID
int PMID = da.GetMaxID("ID", "ENQ_DEVICEPROTECTED");
//维保更换配件ID
int WBPJID = da.GetMaxID("ID", "ENQ_PROTECTEDPARTS");
//维保内容ID
int NRID = da.GetMaxID("ID", "ENQ_PROTECTEDNR");

foreach (DataRow dr in dt.Rows)
{
#region 基本信息收集
//资产编号
string assetNum = dr["资产编号"].ToString();
//工单号
string woNum = dr["工单号"].ToString();

//故障原因附加
strSql = "select distinct f.CUSTDESCCN 故障现象, f1.CUSTDESCCN 原因分析 ";
strSql += "from workorder w, failurecode f0, extwo01 e, CUSTFAILUREREPORT c, failurecode f, CUSTFAILUREREPORT c2, failurecode f1 ";
strSql += "where w.status in (select value from synonymdomain where domainid = 'WOSTATUS' and maxvalue in ('APPR','COMP','CLOSE')) ";
strSql += "and w.orgid = f0.orgid(+) and w.failurecode = f0.failurecode(+) and w.siteid = e.siteid(+) ";
strSql += "and w.wonum = e.wonum(+) and w.siteid = c.siteid(+) and w.wonum = c.wonum(+) and c.parent(+) is null ";
strSql += "and c.orgid = f.orgid(+) and c.failurecode = f.failurecode(+) and c.siteid = c2.siteid(+) and c.wonum = c2.wonum(+) ";
strSql += "and c.custfailurereporid = c2.parent(+) and c2.orgid = f1.orgid(+) and c2.failurecode = f1.failurecode(+) ";
strSql += "and w.wonum='" + woNum + "' ";
DataTable temp1 = da.RunSelectSQL(strSql);
//故障现象
string strGZXX = string.Empty;
//原因分析
string strYYFX = string.Empty;
if (temp1 != null)
{
foreach (DataRow dr1 in temp1.Rows)
{
strGZXX += dr1["故障现象"] + ",";
strYYFX += dr1["原因分析"] + ",";
}
}
if (strGZXX.Length > 1)
{
strGZXX = strGZXX.Substring(0, strGZXX.Length - 1);
}
if (strYYFX.Length > 1)
{
strYYFX = strYYFX.Substring(0, strYYFX.Length - 1);
}


//使用工具附加
strSql = "select distinct c.description 使用工具 from tooltrans t,tool c where t.orgid = c.orgid and t.itemnum = c.toolnum ";
strSql += "and t.refwo = '" + woNum + "' ";
DataTable temp2 = da.RunSelectSQL(strSql);
//使用工具
string strSYGJ = string.Empty;
if (temp2 != null)
{
foreach (DataRow dr2 in temp2.Rows)
{
strSYGJ += dr2["使用工具"] + ",";
}
}
if (strSYGJ.Length > 1)
{
strSYGJ = strSYGJ.Substring(0, strSYGJ.Length - 1);
}

//维修人员附加
strSql = "select p.displayname 维修人员 from labtrans t,craft c,labor l,person p ";
strSql += "where t.orgid = c.orgid(+) and t.craft = c.craft(+) ";
strSql += "and t.laborcode = l.laborcode(+) and t.orgid = l.orgid(+) and l.personid = p.personid(+) ";
strSql += "and t.refwo = '" + woNum + "' ";
DataTable temp3 = da.RunSelectSQL(strSql);
//维修人员
string strWXRY = string.Empty;
if (temp3 != null)
{
foreach (DataRow dr3 in temp3.Rows)
{
strWXRY += dr3["维修人员"] + ",";
}
}
if (strWXRY.Length > 1)
{
strWXRY = strWXRY.Substring(0, strWXRY.Length - 1);
}


//维修耗时
strSql = "select trunc(((t.actfinish - t.actstart)*24),2) 维修耗时 from workorder t ";
strSql += "where t.wonum = '" + woNum + "' ";
DataTable temp4 = da.RunSelectSQL(strSql);
//维修耗时
string strWXHS = string.Empty;
if (temp4 != null)
{
foreach (DataRow dr4 in temp4.Rows)
{
strWXHS = dr4["维修耗时"].ToString();
}
}


//保养周期
strSql = "select p.pmnum 预防性维护编码,p.FREQUENCY 维护频率,p.FREQUNIT 频率单位,p.description 预防性维护描述 ";
strSql += "from asset t,pm p ";
strSql += "where t.siteid = p.siteid and t.assetnum = p.assetnum and p.status = 'ACTIVE' ";
strSql += "and t.assetnum = '"+assetNum+"' ";
DataTable temp11 = da.RunSelectSQL(strSql);
//保养周期
string strBYZQ = string.Empty;
//维保名称
string strWBMC = string.Empty;
//维保名称
if (temp11 != null)
{
foreach (DataRow dr11 in temp11.Rows)
{
strBYZQ = dr11["维护频率"].ToString() + dr11["频率单位"].ToString();
strWBMC = dr11["预防性维护描述"].ToString();
}
}

//da.SaveLogs("资产编号:" + assetNum + " 工单号:" + woNum + " 故障现象:" + strGZXX + " 原因分析:" + strYYFX + " 使用工具:" + strSYGJ + " 维修人员:" + strWXRY + " 维修耗时:" + strWXHS + " 保养周期:" + strBYZQ);

#endregion

//工单所属区域
string SiteID = dr["SiteID"].ToString();
//WO20
string WO20=dr["WO20"].ToString();
//设备名称
string SBName = dr["设备名称"].ToString();
//日期
string RiQi = dr["日期"].ToString();
//工单描述
string Remark = dr["工单描述"].ToString();








...全文
429 28 打赏 收藏 转发到动态 举报
写回复
用AI写文章
28 条回复
切换为时间正序
请发表友善的回复…
发表回复
gxmark 2011-11-08
  • 打赏
  • 举报
回复
不知道楼主是如何处理的?
ijwsoft 2011-11-01
  • 打赏
  • 举报
回复
利用SqlBulkCopy类 批量导入数据到sql server .

http://blog.csdn.net/keenweiwei/article/details/6869465
jdc71264 2011-11-01
  • 打赏
  • 举报
回复
不要用这个办法 速度太慢
要用VS自带的一个类库
我贴点示例代码上来 具体的操作你在上网上看看 比你这快很多

//省略连接字符串
SqlConnection conn = new SqlConnection(".....");
conn.Open();
//初始化类
using (System.Data.SqlClient.SqlBulkCopy sqlBC = new System.Data.SqlClient.SqlBulkCopy(conn))
{
//获取需要导入的数据表
DataTable dt = GetDataTable();

//每10W条数据一个事物
sqlBC.BatchSize = 100000;

//超时时间
sqlBC.BulkCopyTimeout = 60;

//表名Users
sqlBC.DestinationTableName = "dbo.Users";

//字段对应,分表为原数据表字段名,和导入数据库的字段名
sqlBC.ColumnMappings.Add("Access_ID", "MSSQL_ID");
sqlBC.ColumnMappings.Add("Access_Name", "MSSQL_Name");
//sqlBC.ColumnMappings.Add("Access_...", "MSSQL_...");
//sqlBC.ColumnMappings.Add("Access_...", "MSSQL_...");

//导入到数据库
sqlBC.WriteToServer(dt);
qiri07 2011-11-01
  • 打赏
  • 举报
回复
个人建议:
1 大数据量的,可否分表处理,大数据量不建议放在1个表中
2 必要的优化,表索引,部分操作放在存储过程中
3 如果上述的办法效果都不快,可以考虑把表记录中核心字段提取出,放到内存中进行处理(用到算法)
晏子 2011-10-31
  • 打赏
  • 举报
回复
以上差不多都说中了,首先是,数据库层面:肯定不是现有数据库影响操作,是愿数据库的问题,可以索引上面优化下,使得查询快一点,还有就是使用视图,使用存储过程,
代码上:数据量那么大,不要拼装任何的sql语句
现数据库,可以暂时取消表关系,取消主键的自动递增,插入也可以写存储过程
最后说逻辑:你都是从总-分-分的关系遍历查询的,很多查询都是多余的,查出总1个,接下来分100个,再分10000个,也就是说,本来可以只需要查询3次,你却查询了10000次,再说添加可以使用批处理C#那个什么可以一个datatable的数据全部一次性添加的,只需要几次,你却sql一条一条的添加了10000次之多,数据随便举的哈
你想想是不是那样的
你整理下源数据库表以及关系,和新数据库表和关系,然后通过视图,什么的,一次性当张表或者简单的关联表查询几十万条直接插入对应新表,你的几十个表,整理下之后依次存入新表,这个应该会很快的,因为查询中根本就不存在多少where语句
新数据库,完成了之后存在很多问题,比如说不关联的数据什么的,冗余数据,这些都很好说了撒,写个程序,慢慢的去验证,验证不正确就删掉,这个时候肯定也不急时间了吧,验证也要注意顺序总-分-分,比如遍历外键表,看这个外键是否成立,不成立就删掉,这个应该也不会要多少时间吧,就算,一时没有验证出来,也不影响新数据库的业务操作,是吧,把所有的验证做好了之后,就可以给新数据库添加键关系什么的咯

楼主你看看这个合理不
  • 打赏
  • 举报
回复
把索引disable掉,再写数据,然后重新生成索引
虐码锅锅 2011-10-31
  • 打赏
  • 举报
回复
先把索引建好,视图弄好,就不会写那么多的查询了
Apple 2011-10-31
  • 打赏
  • 举报
回复
没有具体点儿的建议?
pitsou7 2011-10-31
  • 打赏
  • 举报
回复
很晕, 难道是想不出优秀的算法?
wylp_19 2011-10-31
  • 打赏
  • 举报
回复
查询的话 存储过程加索引
happytonice 2011-10-31
  • 打赏
  • 举报
回复
这样写光连接数据库也累死
Apple 2011-10-31
  • 打赏
  • 举报
回复
[Quote=引用 6 楼 nevermore_0923 的回复:]

3点建议:
1.string改成stringBuilder.
2.ArrayList改成泛型。
3.不要foreach datarow 。
[/Quote]
不要foreach datarow ,那么可以介绍下其他方法参考否?
Apple 2011-10-31
  • 打赏
  • 举报
回复
[Quote=引用 14 楼 dj1232090 的回复:]

一次处理200条数据太少了,我一次处理5000~10000条,使用多线程,速度很快的
[/Quote]

能否给段代码参考一下?
Apple 2011-10-30
  • 打赏
  • 举报
回复
多谢大侠们的建议,我改改试试
Lxpd 2011-10-30
  • 打赏
  • 举报
回复
优化,缓存,条件查询
linus2008117 2011-10-30
  • 打赏
  • 举报
回复
在循环中频繁出现类似
select distinct f.CUSTDESCCN 故障现象, f1.CUSTDESCCN 原因分析 ";
strSql += "from workorder w, failurecode f0, extwo01 e, CUSTFAILUREREPORT c, failurecode f, CUSTFAILUREREPORT c2, failurecode f1 ";

的多表查询。

你不如先一次把结果放到一张临时表,程序对临时表操作。我相信速度会有很大提升
虐码锅锅 2011-10-30
  • 打赏
  • 举报
回复
一次处理200条数据太少了,我一次处理5000~10000条,使用多线程,速度很快的
虐码锅锅 2011-10-30
  • 打赏
  • 举报
回复
代码太多,我没仔细看
说下我的想法,先在Oracle10 里做好视图,处理程序需要用的,并且要优化好,让查询速度快起来
这样处理起来程序里边就不会那么多查询了

记录处理的标记,方便中间出错,又得删处理后的数据,重头来处理程序

我之前处理5000万数据就是这样弄的
haa17 2011-10-29
  • 打赏
  • 举报
回复
需求表复杂,简单的代码优化估计作用不大。

等待高手指点,帮顶。
gxmark 2011-10-29
  • 打赏
  • 举报
回复
建议考虑一下SQL语句的优化,找出最合适\高效的语句
加载更多回复(7)

62,046

社区成员

发帖
与我相关
我的任务
社区描述
.NET技术交流专区
javascript云原生 企业社区
社区管理员
  • ASP.NET
  • .Net开发者社区
  • R小R
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告

.NET 社区是一个围绕开源 .NET 的开放、热情、创新、包容的技术社区。社区致力于为广大 .NET 爱好者提供一个良好的知识共享、协同互助的 .NET 技术交流环境。我们尊重不同意见,支持健康理性的辩论和互动,反对歧视和攻击。

希望和大家一起共同营造一个活跃、友好的社区氛围。

试试用AI创作助手写篇文章吧