Java性能调优

本文详述了在编程中如何避免循环内的资源消耗,提倡在循环外集中处理,减少数据库交互次数,并强调了正确处理异常和资源释放的重要性。针对文件读写,建议采用加锁机制解决并发问题。SQL优化方面,文章提到了索引的有效利用、避免全表扫描、减少联表查询以及使用预处理语句等策略,以提升数据库性能。最后,讨论了事务处理、分库分表和逻辑删除等最佳实践,旨在提供全面的程序优化方案。
摘要由CSDN通过智能技术生成

一 循环问题

1 避免循环中创建连接数据库、读写数据库、读写文件、调用接口、new 新对象等。否则会影响接口响应速度,导致服务器资源高位占用。

不推荐的写法:

public void run(){
for (int i=0;i<integers.length;i++) {
	String content = “测试”+i;
	RandomAccessFile rFile = new RandomAccessFile(fName, "rw");
	long fileLength = rFile.length();
	rFile.seek(fileLength);
	rFile.writeBytes(content);
	rFile.close();
	}
}

推荐的写法:

public void run(){
String content = “”;
for (int i=0;i<integers.length;i++) {
	content = content  + “测试” + i;
}
RandomAccessFile rFile = new RandomAccessFile(fName, "rw");
long fileLength = rFile.length();
rFile.seek(fileLength);
rFile.writeBytes(content);
rFile.close();
}

2 不要在循环中使用try…catch…,推荐把其放在最外层。

不推荐的写法:

public void run(){
	int [] integers={1,2,3,4};
	for (int i=0;i<integers.length;i++) {
		try {
			//业务处理逻辑
			} catch (FileNotFoundException e) {
				e.printStackTrace();
			}
	}
}

推荐的写法:

public void run(){
	int [] integers={1,2,3,4};
	try {
		for (int i=0;i<integers.length;i++) {
		//业务处理逻辑
	}
	} catch (FileNotFoundException e) {
		e.printStackTrace();
	}
}

二 资源释放

1 文件句柄、scoket连接、数据库连接、redis连接等资源类,在任何情况下确保释放资源。

不推荐的写法:

try {
      	 XXX.close();  //抛异常,导致YYY.close不能释放资源
         YYY.close();
} catch (Exception e) { 

}

推荐的写法:

try {
         XXX.close();  //抛异常
} catch (Exception e) { 

}

try {
         YYY.close();  //抛异常
} catch (Exception e) { 

}

2 Socket设置即时释放。

推荐的写法:

public void run(String[] args) {
       try {
          Socket socket = new Socket();
        //设置立即释放连接
                  socket.setSoLinger(true, 0);

                  //设置读取超时时间,单位毫秒
                  socket.setSoTimeout(2000);

       SocketAddress address = new InetSocketAddress(host, port);
       socket.connect(address);

       OutputStream output = socket.getOutputStream();
       StringBuilder strB = new StringBuilder();
       strB.append("a");
       byte[] request = strB.toString().getBytes("utf-8");
       output.write(request);
  }  catch (IOException e)  {
       throw e;
  } finally {
       socket.close();
  }
}

三 文件读写

1 文件读写增加锁机制,解决高并发读写问题。

推荐的写法:

public void run(String[] args) {
	RandomAccessFile randomAccessFile = null;
    FileChannel channel = null;
    try {
            randomAccessFile = new RandomAccessFile("test.txt", "rw");
            channel = randomAccessFile.getChannel();
            FileLock lock = null;
            
            int sum=0;
            while (null == lock) {
                if(sum > 10) {
				    return false;  //超过重试次数后退出
				}
                try {
                    lock = channel.lock();
                } catch (Exception e) {
					sum++;
                 	sleep(500);
                }
            }
            randomAccessFile.writeByte(A);
            lock.release();
    } catch (Exception e) {
       	    e.printStackTrace();
    } finally {
	        if (null != randomAccessFile) {
	             randomAccessFile.close();
	        }
	        if (null != channel) {
	             channel.close();
	        }
    }
}

四 SQL优化

  1. 确保where 子句查询条件必须走索引,尽量使用主键或唯一索引列,大批数据应考虑分页方式处理数据。
    确认where 及 order by 涉及的列上建立索引。

  2. 避免where 子句中对字段进行null、!= 、<>、not in、not exists值或
    区间范围过大,将导致引擎放弃使用索引而进行全表扫描。
    可以在num上设置默认值0,确保表中num列没有null值:

select id from t where num is null;

推荐改为:

select id from t where num = 0;
  1. 表的索引数最好不要超过6个,索引可提高相应的 select 的效率,但同时
    降低了 insert 及 update 的效率,因为 insert 或 update 时有可能会重
    建索引,所以怎样建索引需要慎重考虑。

  2. 避免在索引列上使用计算
    在where字句中,如果索引列是计算或者函数的一部分,DBMS的优化器将不
    会使用索引而使用全表查询,函数属于计算的一种。
    低效:

select id from t where id+1=8;

优化:

select id from t where id=9;
  1. SQL不用 * 查询,需要明确查询所需字段。

  2. 使用表的别名,当在SQL语句中连接多个表时,请使用表的别名并把别名前缀于每个列名上。这样就可以减少解析的时间并减少哪些有列名歧义引起的语法错误。

  3. SQL语句的合并和拆分。尽量将多条SQL语句压缩到一句SQL中
    合并案例:

update t set status=01,updatetime=now() where id=1update t set status=01,updatetime=now() where id=2

合并成:

update t set status=01,updatetime=now() where id in(1,2)

拆分案例:

select id, num from t where num=10 or num=20

拆分成:

select id, num from t where num=10
union all
select id, num from t where num=20
  1. 尽量使用union all替换union,因为union需要增加去重处理。
  2. ORACLE使用 MERGE INTO 代替 UPDATE 执行批量更新,会提升执行效率。
merge into s_manager a
using(SELECT 1 managerid from DUAL) b on (a.managerid = b.managerid)
when matched then update set a.CNAME='abc'
when not matched then insert(managerid,CNAME) values(1,'abcdef');

MYSQL Innodb引擎的on duplicate key update实现merge into语法。

insert into user(id,name) values(1, 'abc') on duplicate key update
name= 'abcdef';
  1. 尽量避免使用游标。

  2. 用varchar/nvarchar 代替 char/nchar,因为首先变长字段存储空间小,可以节省存储空间,其次对于查询来说,在一个相对较小的字段内搜索效率显然要高些。比如:char(100) 型,在字段建立时,空间就固定了,不管是否插入值(NULL也包含在内),都是占用 100个字符的空间,如果是varchar这样的变长字段,null 不占用空间。

  3. 用where子句替换having字句,having只会在检索出所有记录之后才对结果集进行过滤,而where则是在聚合前。

  4. 尽量不要使用联表查询,特别是大数据表操作时;使用多条SQL批量查询后,组装结果。

  5. 经常使用的小表考虑改成配置文件方式,减少数据库查询。经常使用的多列大表考虑拆分2个表,常用字段内容放小热表中,减少数据库块读取的压力。

  6. SQL多个排序条件,确保排序唯一,否则分页时会有异常。

  7. 数据库尽量不要用大内容字段,否则在查询和编辑时影响性能。

  8. 使用SQL预处理语句绑定参数方式,防止sql注入,提高SQL执行效率。

  9. 数据事务处理时,SQL执行语句按照表名顺序执行,控制SQL影响行数,提高每条SQL执行速度,尽可能减少死锁情况发生。

  10. 数据库表增加字段,如果设置为内容必填时,需要考虑跨系统异常,因为其他系统有可能新增记录时,这个新字段未做处理。

  11. 根据业务合理使用分库分表,对合理清理历史数据,提高查询速度。

  12. 尽量使用逻辑删除,删除\修改操作必须确保查询条件范围可控,否则可能删除\修改期望之外的数据,甚至全表。
    update t_user set status=’09’ where 1=1; 代码缺陷导致没指定条件。

  13. 注意int最大值2147483647,合理使用bigint字段类型。

  14. mysql参数binlog_row_image默认值full这个对alibaba/canal有影响:
    full:在“before”和“after”影像中,记录所有的列值;
    minimal:在“before”和“after”影像中,仅仅记录被更改的以及能够唯一识别数据行的列值;
    noblob:在“before”和“after”影像中,记录所有的列值,但是BLOB 与 TEXT列除外(如未更改)。
    查询:select @@global.binlog_row_image;
    设置:set @@global.binlog_row_image=‘full’;

  15. 使用短索引,如果有一个CHAR(255)的列,如果在前10 个或20 个字符内,多数值是惟一的,那么就不要对整个列进行索引。短索引不仅可以提高查询速度而且可以节省磁盘空间和I/O操作。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值