转载

数据库选型之MySQL(一)

刘勇   Email: lyssym@sina.com

本博客记录作者在工作与研究中所经历的点滴,一方面给自己的工作与生活留下印记,另一方面若是能对大家有所帮助,则幸甚至哉矣!

简介

鉴于高频中心库task部分(核心业务处理、存储逻辑)占用机器较多,为节省成本,调研数据库或缓存,以期满足高频生产的需求:1)峰值1w条/s;2)峰值60w条/m。本着节省成本的角度,本文对开源、免费的数据库MySQL和PostgreSQL从单一处理和批处理角度展开测试,测试目标平均写入速率达 10000条/s 以上则能满足要求。

测试环境

硬件环境:

10.1.120.37:Intel Pentium, 主频:2.90G, 内存:6G

localhost: Intel Core I5, 主频:3.10G,  内存:4G

软件环境:

10.1.120.37:Cent OS 6.5,  MySQL 5.6.25 (社区版)

localhost: Win7,MySQL 5.6.26(社区版)

表结构:

数据库选型之MySQL(一)
DROP TABLE IF EXISTS ` transaction `; CREATE TABLE ` transaction ` ( `tradedate` datetime DEFAULT NOT NULL , `symbol` varchar ( 6 ) DEFAULT NOT NULL , `symbolname` varchar ( 8 ) DEFAULT NOT NULL , `trdmintime` varchar ( 6 ) DEFAULT NOT NULL , `startprice` decimal ( 9 , 3 ) DEFAULT NOT NULL , `highprice` decimal ( 9 , 3 ) DEFAULT NOT NULL , `lowprice` decimal ( 9 , 3 ) DEFAULT NOT NULL , `endprice` decimal ( 9 , 3 ) DEFAULT NOT NULL , `change` decimal ( 9 , 3 ) DEFAULT NOT NULL , `changeratio` decimal ( 6 , 3 ) DEFAULT NOT NULL , `minvolume` decimal ( 10 , 0 ) DEFAULT NOT NULL , `minamout` decimal ( 16 , 3 ) DEFAULT NOT NULL , `unix` bigint ( 20 ) DEFAULT NOT NULL , `market` varchar ( 3 ) DEFAULT NOT NULL
 ) ENGINE
= InnoDB DEFAULT CHARSET = utf8;
View Code

性能测试

MySQL测试

对高频生产的应用需求,本文构造高频中心库系统的数据结构,从单一处理和批处理角度,对远程节点和本地节点(对比性能所用)MySQL进行写入操作,分别存储数据量为60K、100K、600K条数据,对其速率进行测试。需要指出,由于常见I/O访问的瓶颈主要受限于写入测试,本文只针对写入操作进行测试,暂不考虑读取操作或者混合读写方式,若写入操作不满足要求,其它操作无需测试。

单一处理,即每次处理一条数据,对其性能进行测试,结果见表-1。

表-1 单一处理MySQL测试结果

数据库IP 数据量(K) 平均写入速率(条/s)
10.1.120.37 60 1533
10.1.120.37 100 1721
10.1.120.37 600 1772
localhost 60 4889
localhost 100 3875
localhost 600 5057

从表-1可知:1)随着处理数据量增加,其写入速率急剧下降;2)从10.1.120.37和localhost来看,采用单一处理方式,较难满足高频生产需求。

批处理方式,分别从批量处理1000、2000、3000条数据出发,对其性能展开测试,结果见表-2。

表-2批处理MySQL测试结果

1000 2000 3000
数据库IP 数据量(K) 平均写入速率(条/s) 平均写入速率(条/s) 平均写入速率(条/s)
10.1.120.37 60 1533 1575 1546
10.1.120.37 100 1721 1654 1614
10.1.120.37 600 1772 1710 1725
localhost 60 2236 3033 3654
localhost 100 2252 3589 3936
localhost 600 2289 4717 4759

从表-2可知:1)增加批处理数据量,远程节点的写入速率变化不大,可能受限网络资源速率;2)采用批处理方式,很难满足高频生产系统需求,本地节点尚且很难满足,寄希望于远程节点则更加困难。

小结

从上述测试情况来看,单独采用MySQL数据库,其实是很难满足要求I/O要求,针对60w/m的峰值,即10次/ms,对于普通的物理介质存储方案(硬盘)来说,该要求是很难满足的。因此,若要考虑物理介质来存储,固态硬盘是一个选择方案,具体有待于测试。

PostgreSQL测试

由于PostgreSQL可以完全胜任任何中上规模的范围内的业务,因此,本文也针对PostgreSQL是否满足高频生产的应用需求展开性能测试。目前只针对本地节点从单一处理和批处理出发,分别存储上述数据量(见MySQL测试),若本地节点很难满足需求,远程节点也无需测试了。

每次处理一条数据,结果见表-3。

表-3单一处理PostgreSQL测试结果

数据库IP 数据量(K) 平均写入速率(条/s)
localhost 60 2055
localhost 100 2303
localhost 600 2102

分别从批量处理1000、2000、3000条数据出发,对其性能展开测试,结果见表-4。

表-4单一处理PostgreSQL测试结果

1000 2000 3000
数据库IP 数据量(K) 平均写入速率(条/s) 平均写入速率(条/s) 平均写入速率(条/s)
localhost 60 2167 1755 2342
localhost 100 2200 2436 1423
localhost 600 1952 2184 2201

小结

从上述测试结果来看,PostgreSQL针对本文目标应用场景的需求,差距甚远。本地节点尚且无法胜任需求,同时其CPU的处理能力也较远程节点强一些,因此不再对远程节点展开测试。

总结

经上述测试,PostgreSQL相对MySQL的写入速率稍微缓慢一些。针对节省成本的考虑,拟采用单一服务器来满足应用需求,难度巨大,主要集中于,针对60w/m的峰值,即10次/ms,对于普通的物理介质存储方案(机械硬盘)来说,该I/O要求是很难满足的。因此,若要考虑物理介质来存储,固态硬盘是一个选择方案,具体有待于测试。

附录:

测试程序核心源代码:

数据库选型之MySQL(一)
public void initMySQL() { String driver = "com.mysql.jdbc.Driver" ; String url = "jdbc:mysql://10.1.120.37:3306/hdfs" ; String user = "root" ; String password = "root" ; try { Class.forName(driver); conn = DriverManager.getConnection(url, user, password); if (! conn.isClosed()) System.out.println( "Start MySQL!" ); } catch (Exception e) { e.printStackTrace(); } count = 0 ; sql = "insert into transaction" + " values(?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)" ; try { pstm = conn.prepareStatement(sql); } catch
 (SQLException e) {             e.printStackTrace();         }     }
View Code
数据库选型之MySQL(一)
public void insertData(Transaction ts) { try { pstm.setDate( 1 , ts.getTradedate()); pstm.setString( 2 , ts.getSymbol()); pstm.setString( 3 , ts.getSymbolName()); pstm.setString( 4 , ts.getTrdmintime()); pstm.setBigDecimal( 5 , ts.getStartprice()); pstm.setBigDecimal( 6 , ts.getHighprice()); pstm.setBigDecimal( 7 , ts.getLowprice()); pstm.setBigDecimal( 8 , ts.getEndprice()); pstm.setBigDecimal( 9 , ts.getChange()); pstm.setBigDecimal( 10 , ts.getChangeratio()); pstm.setBigDecimal( 11 , ts.getMinvolume()); pstm.setBigDecimal( 12 , ts.getMinamout()); pstm.setLong( 13 , ts.getUnix()); pstm.setString( 14 , ts.getMarket()); pstm.addBatch(); if (count == Test.PREFIX) { pstm.executeBatch(); count = 0 ; } count ++ ; } catch
 (SQLException e) {             e.printStackTrace();         }     }
View Code
正文到此结束
Loading...