我要从数据库中取数据,大概有一千多万条记录,要把全部的结果保存到一个文件中,其中有个字段custName是存放姓名的,数据库的字符集是ISO-8859-1,要想得到中文还得做转换new String(rs.getString("custName").trim().getBytes("iso-8859-1"),"GBK");看了一些文章,说用new方法就又产生了一个对象,原来的对象所占的内存就只能等JAVA的垃圾回收机制处理了,所以我的程序一运行,内存就狂涨,取数的速度就不断慢下来了。请教各位高手,有什么好办法?
我的程序主要的部分如下:
sql="select * from kh";
String colvalue="";
rs=stmt.executeQuery(sql);
while(rs.next()){
for(int i=1;i<60;i++){
if(i!=3){
colvalue=rs.getString(i);
}else{
colvalue=new String(rs.getString("custName").trim().getBytes("iso-8859-1"),"GBK");
}
pw.print(colvalue+"|");
}
pw.println("");
}
rs.close();
另外,有没有办法可以判断String的值是不是中文?
我的程序主要的部分如下:
sql="select * from kh";
String colvalue="";
rs=stmt.executeQuery(sql);
while(rs.next()){
for(int i=1;i<60;i++){
if(i!=3){
colvalue=rs.getString(i);
}else{
colvalue=new String(rs.getString("custName").trim().getBytes("iso-8859-1"),"GBK");
}
pw.print(colvalue+"|");
}
pw.println("");
}
rs.close();
另外,有没有办法可以判断String的值是不是中文?
在JSP頁面調用數據庫裡面的存儲過程程序
存儲過程代碼如下:
CREATE Proc p_show
@QueryStr varchar(8000), --表名、視圖名、查詢語句
@PageSize int=10, --每頁的大小(行數)
@PageCurrent int=1, --要顯示的頁
@FdShow varchar (8000)='', --要顯示的欄位列表,如果查詢結果有標識欄位,需要指定此值,且不包含標識欄位
@FdOrder nvarchar (3000)='' --排序欄位列表
as
declare @FdName nvarchar(550) --表中的主鍵或表、臨時表中的標識列名
,@Id1 varchar(80),@Id2 varchar(80) --開始和結束的記錄號
,@Obj_ID int --對象ID
--表中有複合主鍵的處理
declare @strfd nvarchar(4000) --複合主鍵列表
,@strjoin varchar(8000) --連接欄位
,@strwhere nvarchar(4000) --查詢條件select @Obj_ID=object_id(@QueryStr)
,@FdShow=case isnull(@FdShow,'') when '' then ' *' else ' '+@FdShow end
,@FdOrder=case isnull(@FdOrder,'') when '' then '' else ' order by '+@FdOrder end
,@QueryStr=case when @Obj_ID is not null then ' '+@QueryStr else ' ('+@QueryStr+') a' end
--如果顯示第一頁,可以直接用top來完成
if @PageCurrent=1
begin
select @Id1=cast(@PageSize as varchar(50))
exec('select top '+@Id1+@FdShow+' from '+@QueryStr+@FdOrder)
return
end
--如果是表,則檢查表中是否有標識更或主鍵
if @Obj_ID is not null and objectproperty(@Obj_ID,'IsTable')=1
begin
select @Id1=cast(@PageSize as varchar(50))
,@Id2=cast((@PageCurrent-1)*@PageSize as varchar(50))
select @FdName=name from syscolumns where id=@Obj_ID and status=0x80
if @@rowcount=0 --如果表中無標識列,則檢查表中是否有主鍵
begin
if not exists(select 1 from sysobjects where parent_obj=@Obj_ID and xtype='PK')
goto lbusetemp --如果表中無主鍵,則用臨時表處理
select @FdName=name from syscolumns where id=@Obj_ID and colid in(
select colid from sysindexkeys where @Obj_ID=id and indid in(
select indid from sysindexes where @Obj_ID=id and name in(
select name from sysobjects where xtype='PK' and parent_obj=@Obj_ID
)))
if @@rowcount>1 --檢查表中的主鍵是否為複合主鍵
begin
select @strfd='',@strjoin='',@strwhere=''
select @strfd=@strfd+',['+name+']'
,@strjoin=@strjoin+' and a.['+name+']=b.['+name+']'
,@strwhere=@strwhere+' and b.['+name+'] is null'
from syscolumns where id=@Obj_ID and colid in(
select colid from sysindexkeys where @Obj_ID=id and indid in(
select indid from sysindexes where @Obj_ID=id and name in(
select name from sysobjects where xtype='PK' and parent_obj=@Obj_ID
)))
select @strfd=substring(@strfd,2,2000)
,@strjoin=substring(@strjoin,5,4000)
,@strwhere=substring(@strwhere,5,4000)
goto lbusepk
end
end
end
else
goto lbusetemp
/*--使用標識列或主鍵為單一欄位的處理方法--*/
lbuseidentity:
print('select top '+@Id1+@FdShow+' from '+@QueryStr
+' where '+@FdName+' not in(select top '
+@Id2+' '+@FdName+' from '+@QueryStr+@FdOrder
+')'+@FdOrder
)
exec('select top '+@Id1+@FdShow+' from '+@QueryStr
+' where '+@FdName+' not in(select top '
+@Id2+' '+@FdName+' from '+@QueryStr+@FdOrder
+')'+@FdOrder
)
return
/*--表中有複合主鍵的處理方法--*/
lbusepk:
exec('select '+@FdShow+' from(select top '+@Id1+' a.* from
(select top 100 percent * from '+@QueryStr+@FdOrder+') a
left join (select top '+@Id2+' '+@strfd+'
from '+@QueryStr+@FdOrder+') b on '+@strjoin+'
where '+@strwhere+') a'
)
print ('select '+@FdShow+' from(select top '+@Id1+' a.* from
(select top 100 percent * from '+@QueryStr+@FdOrder+') a
left join (select top '+@Id2+' '+@strfd+'
from '+@QueryStr+@FdOrder+') b on '+@strjoin+'
where '+@strwhere+') a'
)
return
/*--用臨時表處理的方法--*/
lbusetemp:
select @FdName='[ID_'+cast(newid() as varchar(80))+']'
,@Id1=cast(@PageSize*(@PageCurrent-1) as varchar(50))
,@Id2=cast(@PageSize*@PageCurrent-1 as varchar(50))
exec('select '+@FdName+'=identity(int,0,1),'+@FdShow+'
into #tb from'+@QueryStr+@FdOrder+'
select '+@FdShow+' from #tb where '+@FdName+' between '
+@Id1+' and '+@Id2
)
print ('select '+@FdName+'=identity(int,0,1),'+@FdShow+'
into #tb from'+@QueryStr+@FdOrder+'
select '+@FdShow+' from #tb where '+@FdName+' between '
+@Id1+' and '+@Id2
)
GO
在頁面中調用代碼如下:
public String selectRS_ERP() {
String str = "{call p_show('" + this.sql + "'," + intPageSize + ","
+ this.intPage + ",'','" + this.orderby + "')}";
return selectRSERP(str);
}
stmt = conn.prepareCall(str);
rs2 = stmt.executeQuery();
ResultSetMetaData rsmd = rs2.getMetaData();
int numberOfColumns = rsmd.getColumnCount();
在JSP頁面調用數據庫裡面的存儲過程程序
存儲過程代碼如下:
CREATE Proc p_show
@QueryStr varchar(8000), --表名、視圖名、查詢語句
@PageSize int=10, --每頁的大小(行數)
@PageCurrent int=1, --要顯示的頁
@FdShow varchar (8000)='', --要顯示的欄位列表,如果查詢結果有標識欄位,需要指定此值,且不包含標識欄位
@FdOrder nvarchar (3000)='' --排序欄位列表
as
declare @FdName nvarchar(550) --表中的主鍵或表、臨時表中的標識列名
,@Id1 varchar(80),@Id2 varchar(80) --開始和結束的記錄號
,@Obj_ID int --對象ID
--表中有複合主鍵的處理
declare @strfd nvarchar(4000) --複合主鍵列表
,@strjoin varchar(8000) --連接欄位
,@strwhere nvarchar(4000) --查詢條件select @Obj_ID=object_id(@QueryStr)
,@FdShow=case isnull(@FdShow,'') when '' then ' *' else ' '+@FdShow end
,@FdOrder=case isnull(@FdOrder,'') when '' then '' else ' order by '+@FdOrder end
,@QueryStr=case when @Obj_ID is not null then ' '+@QueryStr else ' ('+@QueryStr+') a' end
--如果顯示第一頁,可以直接用top來完成
if @PageCurrent=1
begin
select @Id1=cast(@PageSize as varchar(50))
exec('select top '+@Id1+@FdShow+' from '+@QueryStr+@FdOrder)
return
end
--如果是表,則檢查表中是否有標識更或主鍵
if @Obj_ID is not null and objectproperty(@Obj_ID,'IsTable')=1
begin
select @Id1=cast(@PageSize as varchar(50))
,@Id2=cast((@PageCurrent-1)*@PageSize as varchar(50))
select @FdName=name from syscolumns where id=@Obj_ID and status=0x80
if @@rowcount=0 --如果表中無標識列,則檢查表中是否有主鍵
begin
if not exists(select 1 from sysobjects where parent_obj=@Obj_ID and xtype='PK')
goto lbusetemp --如果表中無主鍵,則用臨時表處理
select @FdName=name from syscolumns where id=@Obj_ID and colid in(
select colid from sysindexkeys where @Obj_ID=id and indid in(
select indid from sysindexes where @Obj_ID=id and name in(
select name from sysobjects where xtype='PK' and parent_obj=@Obj_ID
)))
if @@rowcount>1 --檢查表中的主鍵是否為複合主鍵
begin
select @strfd='',@strjoin='',@strwhere=''
select @strfd=@strfd+',['+name+']'
,@strjoin=@strjoin+' and a.['+name+']=b.['+name+']'
,@strwhere=@strwhere+' and b.['+name+'] is null'
from syscolumns where id=@Obj_ID and colid in(
select colid from sysindexkeys where @Obj_ID=id and indid in(
select indid from sysindexes where @Obj_ID=id and name in(
select name from sysobjects where xtype='PK' and parent_obj=@Obj_ID
)))
select @strfd=substring(@strfd,2,2000)
,@strjoin=substring(@strjoin,5,4000)
,@strwhere=substring(@strwhere,5,4000)
goto lbusepk
end
end
end
else
goto lbusetemp
/*--使用標識列或主鍵為單一欄位的處理方法--*/
lbuseidentity:
print('select top '+@Id1+@FdShow+' from '+@QueryStr
+' where '+@FdName+' not in(select top '
+@Id2+' '+@FdName+' from '+@QueryStr+@FdOrder
+')'+@FdOrder
)
exec('select top '+@Id1+@FdShow+' from '+@QueryStr
+' where '+@FdName+' not in(select top '
+@Id2+' '+@FdName+' from '+@QueryStr+@FdOrder
+')'+@FdOrder
)
return
/*--表中有複合主鍵的處理方法--*/
lbusepk:
exec('select '+@FdShow+' from(select top '+@Id1+' a.* from
(select top 100 percent * from '+@QueryStr+@FdOrder+') a
left join (select top '+@Id2+' '+@strfd+'
from '+@QueryStr+@FdOrder+') b on '+@strjoin+'
where '+@strwhere+') a'
)
print ('select '+@FdShow+' from(select top '+@Id1+' a.* from
(select top 100 percent * from '+@QueryStr+@FdOrder+') a
left join (select top '+@Id2+' '+@strfd+'
from '+@QueryStr+@FdOrder+') b on '+@strjoin+'
where '+@strwhere+') a'
)
return
/*--用臨時表處理的方法--*/
lbusetemp:
select @FdName='[ID_'+cast(newid() as varchar(80))+']'
,@Id1=cast(@PageSize*(@PageCurrent-1) as varchar(50))
,@Id2=cast(@PageSize*@PageCurrent-1 as varchar(50))
exec('select '+@FdName+'=identity(int,0,1),'+@FdShow+'
into #tb from'+@QueryStr+@FdOrder+'
select '+@FdShow+' from #tb where '+@FdName+' between '
+@Id1+' and '+@Id2
)
print ('select '+@FdName+'=identity(int,0,1),'+@FdShow+'
into #tb from'+@QueryStr+@FdOrder+'
select '+@FdShow+' from #tb where '+@FdName+' between '
+@Id1+' and '+@Id2
)
GO
在頁面中調用代碼如下:
public String selectRS_ERP() {
String str = "{call p_show('" + this.sql + "'," + intPageSize + ","
+ this.intPage + ",'','" + this.orderby + "')}";
return selectRSERP(str);
}
stmt = conn.prepareCall(str);
rs2 = stmt.executeQuery();
ResultSetMetaData rsmd = rs2.getMetaData();
int numberOfColumns = rsmd.getColumnCount();
拿mysql来说,用limit
其他各种数据库有自己的分页机制
一次取一千萬條記錄...我也覺得此做法不好
String colvalue="";
rs=stmt.executeQuery(sql);
while(rs.next()){
for(int i=1;i <60;i++){
if(i!=3){
colvalue=rs.getString(i);
}else{
colvalue=new String(rs.getString("custName").trim().getBytes("iso-8859-1"),"GBK");
}
pw.print(colvalue+"|");
}
pw.println("");
}
rs.close();
代码里面加一个计数变量,只固定取N个值,等需要访问后面的值时再去数据库中查询后面的值(也就是分页)
这个就没法分页处理了。
如果数据量太大负载高也可以设置tomcat内存分配机制,调大些就行了。
(只试过一两万的,再大的估计不可行了)
估计不是
GC引起CPU和内存使用率过高,只能适当调整初始内存设置和最大内存设置.因为GC是根据服务器的这个设置值来进行垃圾回收的.
还有就是看看能不能修改DB的内存分配. 估计还是没有权限..
启动参数中加入:
-Xms256m -Xmx512m
具体不太清楚,lZ可以看看这个,
http://www.blogjava.net/phe441/archive/2006/12/11/87042.html
1、将现有的数据库中custName字段字符转换成GBK,这样获取时不用转码。应用系统中在保存记录时将custName存入GBK内容。
2、文件采用追加方式。
3、在pw.print(colvalue+"|"); 代码后增加“colvalue=null”。使gc时减少判断。
sql="select * from kh";
String colvalue="";
rs=stmt.executeQuery(sql);
while(rs.next()){
for(int i=1;i <60;i++){
if(i!=3){
colvalue=rs.getString(i);
}else{
colvalue=new String(rs.getString("custName").trim().getBytes("iso-8859-1"),"GBK");
}
pw.print(colvalue+"|");
}
pw.println("");
// 你在打印完以后已经没有指向new出来的String的引用了,
// 所以你可以在这里加上主动调用垃圾收集的代码试试,我没测试过哦^-^
System.gc();
}
rs.close();
我查了查 你的数据库是不是支持下面的分页语句。
select first n from TableName order by fieldName Asc
还有String colvalue="";这个换成StringBuffer效果能好不少 你用String会产生大量的对象 占用你的内存