java 给Access一个表插入100万条记录,时间好慢呀

时间:2021-09-14 04:33:37
有一个access表,含有100万左右的个人记录, 我现在想要添加一个新的列(sortingkey),这个列的数据要靠其他列的数据获得。(比如姓名的前三个字符+邮编的前3个字符)。


于是我首先将这个表的数据select * from table之后 转为了一个arraylist,


然后将数据进行处理,根据已有的数据内容,经过处理获得了新列的的各个数据。


然后我把这含有了100万条的arraylist插入一个新access表里面, 我发现如果我只选择1万条进行处理 (select TOP 10000 from table), 时间还可以接受, 几秒钟就完成了。 如果我一次性都选择(select * from table)就发现内存溢出了,于是我曾加了内存参数。 可是速度非常非常的慢。很多分钟也出不来结果。
我搜索了一些帖子,有一些人说可以利用批量 分页什么的思想解决。不知各位是否有过类似的经验呢?

描述的代码我简单的写一下:

ResultSet rs=stmt.executeQuery("select TOP 10000 * from table");

convert(rs); // 先把rs专程arraylist, 在convert方法里面就直接把arraylist的数据往新表里面插了。于是就出现问题了



public ArrayList convert(ResultSet rs)throws Exception   // turn resultset records into an arraylist
{
ArrayList list=new ArrayList();
ResultSetMetaData rsm=rs.getMetaData();
int count=rsm.getColumnCount();
while(rs.next())
{
HashMap map=new HashMap();

for(int i=1;i<=count; i++)
{
map.put(rsm.getColumnName(i), rs.getObject(i));  
}
   
list.add(map);

}

rs.close();

try
{
       
for (int i=0;i<list.size();i++)
{
  HashMap sortingmap=(HashMap)list.get(i);

  String URN=(String)sortingmap.get("编号");
  String name=(String)sortingmap.get("姓名");
  String Address=(String)sortingmap.get("地址");
  String Postcode=(String)sortingmap.get("邮编");
  
stmt.execute("insert into newtable (URN, name,Address, Postcode, SortingKey ) values ('"+URN+"','"+name+"','"+Address+"',,'"+Postcode+"','"+Sortingkey.toString"');  
}


}
catch (Exception e)
{
e.printStackTrace();
}

return list;
}









11 个解决方案

#1


1、打开事务插入试试;
2、直接插入试试
nsert into newtable (URN, name,Address, Postcode, SortingKey ) select top ...

#2


有一个access表,含有100万左右的个人记录, 我现在想要添加一个新的列(sortingkey),这个列的数据要靠其他列的数据获得。(比如姓名的前三个字符+邮编的前3个字符)。
如果这样,不建议你去用程序一条记录一条记录去处理。 你可以加完这个字段后,直接运行下面SQL语句进行更新
update 有一个access表
set sortingkey=left(姓名,3) & left(邮编,3)

#3



我又测了一下,发现问题出现在刚刚开始的位置,即:

select * from table


因为table中100万条记录就因为这句一次性全都要读出来然后处理。我觉得这个影响了速度和内存。

有没有什么方法可以边读记录 边处理然后释放内存呢?比如读1000条处理1000条然后接着读下面1000条。。。

这样子会不会也会提速


#4


如果有唯一标识的字段,比如ID
SELECT * FROM TT WHERE ID BETWEEN 1000 AND 2000

#5


有ID, 但是ID不是数字 是字母数字混合的8位String。

我测试了一下时间,发现大量的时间分别用在了

1: while(rs.next) 处理 rs转 arraylist上

2:将arraylist一条一条的插入新表中。


刚刚想了一下,在处理 while  rs.next的时候 会占用相当多的内存而且速度会超级慢。所以能否分页一部分一部分的处理呢? 比如1外万条记录的resultset, 分成几十个块,一个快处理之后 清空占用的内存,然后处理下一块。  不知道如何实现。

#6


建议不要循环,直接用SQL语句解决,增加自增字段

#7


我放弃转List 再输入表了。

直接自己建一个表,含有多出来的那一列。

可是1百万条数据一个一个的插进去,总共用了几十分钟。

#8


你现在的代码是什么

#9


引用 7 楼 phdapp 的回复:
我放弃转List 再输入表了。

直接自己建一个表,含有多出来的那一列。

可是1百万条数据一个一个的插进去,总共用了几十分钟。
为什么不直接在你的原表上加上这个字段,然后直接 #2楼 的UPDATE语句?

#10


引用 9 楼 acmain_chm 的回复:
引用 7 楼 phdapp 的回复:
我放弃转List 再输入表了。

直接自己建一个表,含有多出来的那一列。

可是1百万条数据一个一个的插进去,总共用了几十分钟。
为什么不直接在你的原表上加上这个字段,然后直接 #2楼 的UPDATE语句?


这个是我最开始的做法,实验了一下,因为实在速度很慢很慢所以放弃了。

#11


这两天,看了不少资料和帖子,现在的做法是已经改了使用SQL server, 然后在循环里

while rs.next
{

调用一个insert的存储过程给表里插入内容

}


这样算下来 对比下面这两种方式

1:在access原表上面建立一个column然后更新
2:建立一个新access表插入记录

时间上都省了超多。

虽然省了时间,可是我还是对现在的速度不是很满意。我期待能有一个方法可以几秒之内就将A表的每一条数据全部处理完插入B表中。

各位觉得可能么?

#1


1、打开事务插入试试;
2、直接插入试试
nsert into newtable (URN, name,Address, Postcode, SortingKey ) select top ...

#2


有一个access表,含有100万左右的个人记录, 我现在想要添加一个新的列(sortingkey),这个列的数据要靠其他列的数据获得。(比如姓名的前三个字符+邮编的前3个字符)。
如果这样,不建议你去用程序一条记录一条记录去处理。 你可以加完这个字段后,直接运行下面SQL语句进行更新
update 有一个access表
set sortingkey=left(姓名,3) & left(邮编,3)

#3



我又测了一下,发现问题出现在刚刚开始的位置,即:

select * from table


因为table中100万条记录就因为这句一次性全都要读出来然后处理。我觉得这个影响了速度和内存。

有没有什么方法可以边读记录 边处理然后释放内存呢?比如读1000条处理1000条然后接着读下面1000条。。。

这样子会不会也会提速


#4


如果有唯一标识的字段,比如ID
SELECT * FROM TT WHERE ID BETWEEN 1000 AND 2000

#5


有ID, 但是ID不是数字 是字母数字混合的8位String。

我测试了一下时间,发现大量的时间分别用在了

1: while(rs.next) 处理 rs转 arraylist上

2:将arraylist一条一条的插入新表中。


刚刚想了一下,在处理 while  rs.next的时候 会占用相当多的内存而且速度会超级慢。所以能否分页一部分一部分的处理呢? 比如1外万条记录的resultset, 分成几十个块,一个快处理之后 清空占用的内存,然后处理下一块。  不知道如何实现。

#6


建议不要循环,直接用SQL语句解决,增加自增字段

#7


我放弃转List 再输入表了。

直接自己建一个表,含有多出来的那一列。

可是1百万条数据一个一个的插进去,总共用了几十分钟。

#8


你现在的代码是什么

#9


引用 7 楼 phdapp 的回复:
我放弃转List 再输入表了。

直接自己建一个表,含有多出来的那一列。

可是1百万条数据一个一个的插进去,总共用了几十分钟。
为什么不直接在你的原表上加上这个字段,然后直接 #2楼 的UPDATE语句?

#10


引用 9 楼 acmain_chm 的回复:
引用 7 楼 phdapp 的回复:
我放弃转List 再输入表了。

直接自己建一个表,含有多出来的那一列。

可是1百万条数据一个一个的插进去,总共用了几十分钟。
为什么不直接在你的原表上加上这个字段,然后直接 #2楼 的UPDATE语句?


这个是我最开始的做法,实验了一下,因为实在速度很慢很慢所以放弃了。

#11


这两天,看了不少资料和帖子,现在的做法是已经改了使用SQL server, 然后在循环里

while rs.next
{

调用一个insert的存储过程给表里插入内容

}


这样算下来 对比下面这两种方式

1:在access原表上面建立一个column然后更新
2:建立一个新access表插入记录

时间上都省了超多。

虽然省了时间,可是我还是对现在的速度不是很满意。我期待能有一个方法可以几秒之内就将A表的每一条数据全部处理完插入B表中。

各位觉得可能么?