一、主键冲突
1.测试主键冲突的影响
(1)在主键不冲突时,处理下图的4个文件
查看程序运行的日志,开始处理第一个文件的时间为:
处理完最后一个文件的时间为:
这个过程花费的时间为 9 秒。
(2)再次将上面处理的5个文件入库,因为它们已经入库,会导致主键冲突,这时来查看处理时间:
开始第一个文件处理的时间点为:
处理完最后一个文件的时间点为:
这个过程一共花费的时间为 36 秒。
(3)在往表里插入记录的时候,oracle数据库系统是不是先去表里查一下有没有这条记录,如果有的话就不插入,然后报错。 这个步骤需要我们自己完成
但是它不是这样做的,如果它是这样的话,主键冲突时,效率就不会差那么多
这样处理后,再次将这几个文件插入表中(此时是冲突的),查看处理时间
这个过程花了 5秒,比之前没有经过处理快了很多。
2.加上插入前查询处理源代码:
int iccount=0;
sqlstatement stmtsel;
stmtsel.connect(&conn);
stmtsel.prepare("select count(*) from T_SURFDATA where obtid=:1 and ddatetime=to_date(:2,'yyyy-mm-dd hh24:mi:ss')");
stmtsel.bindin( 1, stsurfdata.obtid,5);
stmtsel.bindin( 2, stsurfdata.ddatetime,19);
stmtsel.bindout(1,&iccount);
// 在执行插入之前,先查询
if ( stmtsel.execute() != 0 )
{
logfile.Write("stmtsel.execute() failed.\n%s\n%s\n",stmtsel.m_sql,\
stmtsel.m_cda.message);
continue;
}
iccount=0;
stmtsel.next();
if ( iccount > 0 ) continue;
二、错误处理
2.1 忽略错误出现的问题
在上一个步骤中,为了让程序在处理数据的时候(执行SQL语句),遇到主键冲突和错误的数据(比如说数据的格式不对,日期中出现了第13月份)能够继续运行下去,就忽略了很多错误。也就是在遇到错误时,没有退出程序(return ),如下图
这样会导致另外一问题,如果在执行SQL语句的时候( execute() ),数据库断开了连接,程序依然会继续运行,但是这样已经是没有意义的了。因为程序继续运行,但数据插入不了数据库,程序依然会运行到删除文件的位置,这样就会导致数据的丢失。
2.2 模拟忽略错误出现的问题
(1)我们打算将这个目录下的这几个文件的数据导入数据库
(2)下面,就来模拟这个情况,将一个文件导入了数据库后,就 sleep 10秒,我就在这个时间空隙断开数据库的连接。
(3)查看程序的运行日志,会看到程序没有连接到数据库,数据没有导入库中,但是依然继续运行下去。
(4)再到(1)步骤的目录中查看文件,那几个文件已经丢失了(在程序中,导入了数据库会删除原文件)
2.3 选择性忽略错误
(1)因此有些错误可以忽略跳过,让程序继续运行,但是有些错误不行,就像数据库断开连接。所以要修改程序,要判断错误时属于哪些类型。如果是数据错误可以继续运行,但如果是系统错误(数据库断开连接,网络断开出现故障等)要退出程序。
像下图这的错误要 return ,退出程序
(2)修改程序
2.3 检验修改效果
(1)查看下图目录中的文件为:
(2)运行程序,模拟数据库断开连接情况,查看程序运行日志:
(3)手动断开数据库连接,程序退出。在程序退出之前,有两个文件导入了数据库,如下图
那么下图的目录中,应该还剩下3个文件,
(4)查看上图目录中还剩余的文件为:
还剩余3个,数据没有丢失,修改程序成功。
三、总结
1、主键冲突会影响程序的性能,会使处理速度下降。所以要导入数据库的数据经常会出现主键冲突时,要采取插入前查询的措施,但是当数据库中的数据量很庞大时,这个措施也是会花费一定的时间的,所以当数据不经常或者极少出现主键冲突时,不要这个措施了。要根据数据的特点去决定要不要去加入处理主键冲突的措施。
2、错误的忽略,一般数据库断开连接的错误不能忽略,首先要考虑到这个,其他的一般可以忽略。