欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

记一次导数据经历

程序员文章站 2022-06-01 20:22:33
...

该博客没有什么技术含量,是一个技术废物的窘态记录!

这几天遇到了个无语的事情,某个客户的系统由于从java7升到了java8,导致系统崩了。

我就负责把数据库里的数据导出来,记录一下自己的窘态

毕竟写python写了好长时间,java又用的不好,窘态频出。

并且最妖的是,这个开发只能远程,不能测试,也就是连不到数据库。

先说需求吧,很简单:在配置文件中配置到导出的时间段,然后运行程序。

最开始,设置成了按整个时间段查询,直接卡在了查询上。

和客户了解了一下,一天的数据量大概是1亿

下面的这个程序就是 输入 起始日期和结束日期就会返回一个列表,用于之后的sql语句拼接

	public static List<ArrayList<String>> getDateList(String startDate, String endDate) throws ParseException {

		String begainDate = formatDateSting(StringDateClever(startDate));
		String finishDate = formatDateSting(StringDateClever(endDate));
		List<ArrayList<String>> dateList = new ArrayList<>();
		while (begainDate.compareTo(finishDate) <= 0) {
			List<String> subList = new ArrayList<>();
			subList.add(begainDate);
			String nextDate = nextHalfHour(begainDate);
			subList.add(nextDate);
			dateList.add(new ArrayList<>(subList));
			begainDate = nextDate;
		}
		dateList.remove(dateList.size() - 1);
		return dateList;
	}


	public static String nextHalfHour(String str) throws ParseException {
		SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
		Date date = sdf.parse(str);
		long time = date.getTime() + 1000L * 60 * 10;
		date = new Date(time);
		return sdf.format(date);
	}


public static Date StringDateClever(String str) {
		Date date = null;
		try {
			SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");

			if (str.length() == 19) {
				sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
			} else if (str.length() == 16) {
				sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm");
			} else if (str.length() == 13) {
				sdf = new SimpleDateFormat("yyyy-MM-dd HH");
			} else if (str.length() == 10) {
				sdf = new SimpleDateFormat("yyyy-MM-dd");
			}
			date = sdf.parse(str);
		} catch (ParseException e) {
			// System.out.println(e.getMessage());
		}

		return date;
	}


public static String formatDateSting(Date date) {
		SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
		String strDate = sdf.format(date);
		return strDate;
	}

然后  交互式对客户不友好,改成读配置文件,程序不能运行一次,要加上重试。

下面就是 怎么读取配置文件(config/init.properties)

	FileInputStream fileInputStream = new FileInputStream("config/init.properties");
				pro.load(fileInputStream);// 相对路径
				startDate = pro.getProperty("startDate");
				endDate = pro.getProperty("endDate");
				FINISHDATE = pro.getProperty("endDate");
				row = Integer.parseInt(pro.getProperty("row"));
				retryCount = Integer.parseInt(pro.getProperty("retryCount"));
				LOG.info("初始化配置成功");

这样就将 起始日期 和结束日期 和重试次数 都初始化了。

然后 就是断点查询,不能断了在启动还要重新跑吧,数据量那么大,这谁顶得住呢。

那就在查询出错或者有其他异常的时候记录断点

记录完断点就得在整个程序初始化的时候检查是否存在断点

记录断点的时候 我是这样处理的,记录下当前查询的时间段

startDate就是 新的起始时间

那么endDate就不是结束时间,只是startDate +10分钟的时间,所以还需要个FinishDate在读配置文件的时候记录下endDate

	public static void writeCheckPoint(String stratDate, String endDate, String finishDate, int row) throws Exception {
		String path = System.getProperty("user.dir") + "./log/checkPoint.txt";
		File file = new File(path);
		if (!file.exists()) {
			file.getParentFile().mkdir();
			try {
				file.createNewFile();
			} catch (IOException e) {
				System.out.println("创建文件时失败");
				e.printStackTrace();
			}
		}
		String string = stratDate + "|" + endDate + "|" + finishDate + "|" + String.valueOf(row);
		FileWriter fw = null;
		try {
			fw = new FileWriter(file, false);
			fw.write(string);
		} catch (IOException e) {
			System.out.println("断点文件输出失败");
			e.printStackTrace();
		} finally {
			
			try {
				if (fw != null)
					fw.close();
			} catch (IOException e) {
				System.out.println("断点文件关闭失败");
				e.printStackTrace();
			}
		}
		checkPointFlag = true;
		flag = false;
		 throw new Exception("查询异常");
	}

断点记录有了,那初始化时读断点的操作也得有

这里,我设置了一个标记位(checkPointFlag)来记录当前是否存在断点

public static void checkPointExist() {
		String path = System.getProperty("user.dir") + "./log/checkPoint.txt";
		File file = new File(path);
		if (file.exists()) {
			checkPointFlag = true;
		}
	}

下一步 该 记录数据,读写数据了。

记录数据就用List<hashmap>就好了

写数据的时候要注意使用StringBuilder

奈何自己渣,这都不知道。

String是不可变类型,所以在进行 “你好“ + “世界” 这样的拼接操作的时候。

是创建了新的内存地址,并将指针指向 “你好世界”。

这样对资源一种浪费。

内存中的无用的对象多了之后,GC处理的工作也就变多了,很影响效率。

(尤其是数据量很大并且有很多拼接的操作时)、

并且如果New String速度快于GC的清理的话,可能会导致内存溢出,一定要注意!

如果是多线程的话就用StringBuffer,这个类型线程安全。

 

相关标签: java