性能测试阶段,预先插入一批数据到Mysql中。并分为三个阶段。
第一阶段:向Mysql的三张表里,插入有关联关系的18万+18 * 3万+18 * 4万的数据。
第二阶段:插入第一阶段数据量5倍的数据,即90万为基数
第三阶段;插入第一阶段数据量10倍的数据即180万为基数
方法1:本地JDBC插入。List<?>有1+3+4,共8个List<?>
方法1的问题有两点:
1.JDBC顺序执行效率很低
2.大数据量下,耗时会超过连接时间,导致连接超时。
方法2:本地或服务器端启动多个任务将基础数据List<?>插入。其他的关联数据,先检索基础数据List<?>,再将生成的关联数据插入。
将其余的7个List<?>做成7个类,在服务器上分别启动。
方法2的优点:
1.效率快,先插入基础数据后,时间复杂度O,其余数据数据并行插入。时间总共O*2;
但是在实际执行情况下,第一阶段和第二阶段都顺利执行。但是第三阶段却暴露了问题。
方法2的问题:
1.7个任务,将180万*7的数据检索到内存后,内存溢出(OutOfMemoryError)。(下班开了任务就走的我,第二天看日志,瞬间泪流满面)
鉴于方法2的问题,就在方法1的基础上,做了修改。 方法一也有优点,就是数据都在内存中,关联数据的生成比较方便。不需要再去检索数据库,再额外占用内存。方法三在此优点上修改 方法3:基础数据和关联数据生成后,开启多线程插入数据。8个List<?>就分8个线程插入。提升效率。
方法3暴露的问题:(也许此方法暴露的不是问题,而是我的智商)
问题如下:
1.程序改为多线程后,对应的List<?>没有改动。ArrayList<?>是线程非安全的。java.util.ConcurrentModificationException
2.线程的创建,阻塞,销毁。多线程(ExecutorService service = Executors.newFixedThreadPool(8);)的使用
线程安全的类:
CopyOnWriteArrayList<?> 参考资料(https://blog.csdn.net/liyu121/article/details/87873858)与(https://www.cnblogs.com/dolphin0520/p/3938914.html)
CocurrentHashMap<key,value> (https://blog.csdn.net/fwt336/article/details/81110760)
List<String> list = Collections.synchronizedList(new LinkedList<String>());(很low啊)
将LinkedList全部换成ConcurrentLinkedQueue(没用过)
最终被智商打败的我(阻塞处理不好,导致的连接提前关闭没有解决)选择了方法4
方法4:在方法2的基础上,将检索条件改为按id检索。并实现了可配置。 配置文件中,检索id为0-10000,然后7个任务并行,先检索0-10000,插入。 修改配置文件,检索id为10001-20000...以此类推。解决了内存不足的问题。