刘勇    Email: lyssym@sina.com

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

简介

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

测试环境

硬件环境

10.1.120.34:Intel Core I5-4590, 主频:3.30G,  内存:16G, 有固态硬盘

软件环境:

10.1.120.34: Cent OS 6.5,  MySQL 5.6.26 (社区版)

表结构:

 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;

table transaction

配置文件:即数据库配置文件,见/etc/my.cnf

 # read_rnd_buffer_size = 2M
datadir=/var/lib/mysql
socket=/var/lib/mysql/mysql.sock
innodb_flush_log_at_trx_commit = 2
innodb_autoinc_lock_mode = 2
query_cache_type = 1
query_cache_size = 20M
innodb_buffer_pool_size = 2G
innodb_flush_method = O_DSYNC
# Disabling symbolic-links is recommended to prevent assorted security risks
symbolic-links=0

my.cnf

性能测试

事务处理

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

本文采用写入多条数据执行事务处理。因为10.1.120.34上采用固态硬盘作为存储介质,其安装有MySQL,根据应用场景,第一种从远程访问,即测试主机10.1.25.50访问MySQL,第二种从本地访问10.1.120.34访问MySQL。以下分别从事务处理条目为1000、2000和3000下展开测试。

以1000条数据为基础执行事务处理,结果见表-1。

表-1  1000条下事务处理MySQL测试结果

节点

数据库IP

数据量(K)

平均写入速率(条/s)
远程节点 10.1.120.34 60 2328
远程节点 10.1.120.34 100 2366
远程节点 10.1.120.34 600 2372
本地节点 10.1.120.34 60 14936
本地节点 10.1.120.34 100 16526
本地节点 10.1.120.34 600 21169

以2000条数据为基础执行事务处理,结果见表-2。

表-2  2000条下事务处理MySQL测试结果

节点

数据库IP

数据量(K)

平均写入速率(条/s)
远程节点 10.1.120.34 60 2318
远程节点 10.1.120.34 100 2333
远程节点 10.1.120.34 600 2320
本地节点 10.1.120.34 60 12714
本地节点 10.1.120.34 100 17914
本地节点 10.1.120.34 600 20214

以3000条数据为基础执行事务处理,结果见表-3。

表-3  3000条下事务处理MySQL测试结果

节点

数据库IP

数据量(K)

     平均写入速率     (条/s)
  远程节点   10.1.120.34         60      2319
  远程节点   10.1.120.34       100      2377
  远程节点   10.1.120.34       600      2429
  本地节点   10.1.120.34        60     11202
  本地节点   10.1.120.34       100     17587
  本地节点   10.1.120.34       600     18577

小结

从表1-3可知:1)在远程节点访问MySQL,即使采用固态硬盘,其速率还是较慢,无法满足需求;2)在本地节点,访问MySQL,则能够满足高频生产的需求。

批处理

为比较批处理方式和事务处理方式的性能,本文针对其进行比较测试。

每1000条数据,执行一次批处理,测试结果如表-4。

表-4  1000条下批处理与事务处理MySQL测试结果

方式

数据库IP

数据量(K)

平均写入速率(条/s)
批处理 10.1.120.34 60 15974
批处理 10.1.120.34 100 16328
批处理 10.1.120.34 600 17633
事务处理 10.1.120.34 60 14936
事务处理 10.1.120.34 100 16526
事务处理 10.1.120.34 600 21169

每2000条数据,执行一次批处理,测试结果如表-5。

表-5  2000条下批处理与事务处理MySQL测试结果

方式

数据库IP

数据量(K)

平均写入速率(条/s)
批处理 10.1.120.34 60 14840
批处理 10.1.120.34 100 16310
批处理 10.1.120.34 600 17364
事务处理 10.1.120.34 60 12714
事务处理 10.1.120.34 100 17914
事务处理 10.1.120.34 600 20214
每3000条数据,执行一次批处理,测试结果如表-6。

表-6  3000条下批处理与事务处理MySQL测试结果

节点

数据库IP

数据量(K)

平均写入速率(条/s)
批处理 10.1.120.34 60 14641
批处理 10.1.120.34 100 16371
批处理 10.1.120.34 600 17593
事务处理 10.1.120.34 60 11202
事务处理 10.1.120.34 100 17587
事务处理 10.1.120.34 600 18577

         小结

从表4-6测试结果来看,在写入数据量少时,批处理方式较事务方式速率快一些,但是随着访问数据量增加,事务处理方式稍微快一些。

总结

从上述测试结果来看,以固态硬盘作为存储介质,在本地访问MySQL可以满足高频生产的需求。此外,鉴于高频生产高负载的需求,优先选择事务处理方式。

附录

测试部分源代码:

 import java.sql.Date;
import java.math.BigDecimal; public class Transaction {
private Date tradedate;
private String symbol;
private String symbolName;
private String trdmintime;
private BigDecimal startprice;
private BigDecimal highprice;
private BigDecimal lowprice;
private BigDecimal endprice;
private BigDecimal change;
private BigDecimal changeratio;
private BigDecimal minvolume;
private BigDecimal minamout;
private long unix;
private String market; public Transaction(Date tradedate,
String symbol,
String symbolName,
String trdmintime,
BigDecimal startprice,
BigDecimal highprice,
BigDecimal lowprice,
BigDecimal endprice,
BigDecimal change,
BigDecimal changeratio,
BigDecimal minvolume,
BigDecimal minamout,
long unix,
String market)
{
this.symbol = symbol;
this.symbolName = symbolName;
this.trdmintime = trdmintime;
this.startprice = startprice;
this.highprice = highprice;
this.lowprice = lowprice;
this.endprice = endprice;
this.change = change;
this.changeratio = changeratio;
this.minvolume = minvolume;
this.minamout = minamout;
this.unix = unix;
this.market = market;
} public void setTradedate(Date tradedate) {
this.tradedate = tradedate;
} public void setSymbol(String symbol) {
this.symbol = symbol;
} public void setSymbolName(String symbolName) {
this.symbolName = symbolName;
} public void setTrdmintime(String trdmintime) {
this.trdmintime = trdmintime;
} public void setStartprice(BigDecimal startprice) {
this.startprice = startprice;
} public void setHighprice(BigDecimal highprice) {
this.highprice = highprice;
} public void setLowprice(BigDecimal lowprice) {
this.lowprice = lowprice;
} public void setEndprice(BigDecimal endprice) {
this.endprice = endprice;
} public void setChange(BigDecimal change) {
this.change = change;
} public void setChangeratio(BigDecimal changeratio) {
this.changeratio = changeratio;
} public void setMinvolume(BigDecimal minvolume) {
this.minvolume = minvolume;
} public void setMinamout(BigDecimal minamout) {
this.minamout = minamout;
} public void setUnix(long unix) {
this.unix = unix;
} public void setMarket(String market) {
this.market = market;
} public Date getTradedate() {
return tradedate;
} public String getSymbol() {
return symbol;
} public String getSymbolName() {
return symbolName;
} public String getTrdmintime() {
return trdmintime;
} public BigDecimal getStartprice() {
return startprice;
} public BigDecimal getHighprice() {
return highprice;
} public BigDecimal getLowprice() {
return lowprice;
} public BigDecimal getEndprice() {
return endprice;
} public BigDecimal getChange() {
return change;
} public BigDecimal getChangeratio() {
return changeratio;
} public BigDecimal getMinvolume() {
return minvolume;
} public BigDecimal getMinamout() {
return minamout;
} public long getUnix() {
return unix;
} public String getMarket() {
return market;
} }

Class Transcation

 import java.sql.*;
import java.math.BigDecimal;
import java.math.RoundingMode; public class Test {
public static int PREFIX = 1000; // 批处理量
public static int FIX = 600; // 操作数据 K
private Connection conn;
private PreparedStatement pstm;
private String sql;
private int count; public static void main(String[] args) {
// TODO Auto-generated method stub Transaction ts = new Transaction(null,
"",
"",
"010000",
new BigDecimal(15.857).setScale(3, RoundingMode.HALF_UP),
new BigDecimal(18.550).setScale(3, RoundingMode.HALF_UP),
new BigDecimal(13.147).setScale(3, RoundingMode.HALF_UP),
new BigDecimal(16.383).setScale(3, RoundingMode.HALF_UP),
new BigDecimal(0.151).setScale(3, RoundingMode.HALF_UP),
new BigDecimal(1.550).setScale(3, RoundingMode.HALF_UP),
new BigDecimal(5000000).setScale(3, RoundingMode.HALF_UP),
new BigDecimal(500000000).setScale(3, RoundingMode.HALF_UP),
System.currentTimeMillis(),
"SSE"); Test test = new Test();
int symbolData = 100000;
test.initMySQL(); long start = test.getRunTime();
for(int i = 0; i < Test.FIX*1000; i++) {
ts.setTradedate(new Date(System.currentTimeMillis()));
ts.setSymbol(Integer.toString(symbolData));
symbolData++ ;
ts.setSymbolName("中国银行");
ts.setUnix(ts.getUnix()+1);
test.insertData(ts);
}
long end = test.getRunTime();
System.out.println("写入速率为: " + Test.FIX*1000*1000/(end-start)); test.down();
} public void initMySQL()
{
String driver = "com.mysql.jdbc.Driver";
String url = "jdbc:mysql://10.1.120.34:3306/hdfs";
String user = "root";
String password = ""; 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);
conn.setAutoCommit(false);
} catch (SQLException e) {
e.printStackTrace();
}
} 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.executeUpdate();
count++;
if (count == Test.PREFIX) {
conn.commit();
conn.setAutoCommit(false);
count = 0;
} } catch (SQLException e) {
try {
conn.rollback();
} catch (SQLException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
e.printStackTrace();
}
} public long getRunTime()
{
return System.currentTimeMillis();
} public void down()
{
try {
if (!conn.isClosed()) {
conn.close();
System.out.println("Close MySQL!");
}
} catch (Exception e) {
e.printStackTrace();
}
} }

Class Test

  


  作者:志青云集
  出处:http://www.cnblogs.com/lyssym
  如果,您认为阅读这篇博客让您有些收获,不妨点击一下右下角的【推荐】。
  如果,您希望更容易地发现我的新博客,不妨点击一下左下角的【关注我】。
  如果,您对我的博客所讲述的内容有兴趣,请继续关注我的后续博客,我是【志青云集】。
  本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接。


数据库选型之MySQL(固态硬盘)的更多相关文章

  1. 数据库选型之MySQL(普通硬盘)

    刘勇   Email:lyssym@sina.com 本博客记录作者在工作与研究中所经历的点滴,一方面给自己的工作与生活留下印记,另一方面若是能对大家有所帮助,则幸甚至哉矣! 简介 鉴于高频中心库ta ...

  2. 数据库选型之MySQL(多线程并发)

    刘勇    Email: lyssym@sina.com 本博客记录作者在工作与研究中所经历的点滴,一方面给自己的工作与生活留下印记,另一方面若是能对大家有所帮助,则幸甚至哉矣! 简介 鉴于高频中心库 ...

  3. 论 数据库 B Tree 索引 在 固态硬盘 上 的 离散存储

    传统的做法 , 数据库 的 B Tree 索引 在 磁盘上是 顺序存储 的 , 这是考虑到 磁盘 机械读写 的 特性 . 实际上 , B Tree 是一个 树形结构 , 可以采用 链式 存储 , 就是 ...

  4. 基于SSD固态硬盘的数据库性能优化

    基于SSD固态硬盘的数据库性能优化 2010-11-08 00:0051cto佚名   关键字:固态硬盘 数据库管理 SSD 企业软件热点文章 Java内存结构与模型结构分析 Oracle触发器的语法 ...

  5. 数据库选型之内存数据库eXtremeDB

    刘勇    Email:lyssym@sina.com 简介 鉴于内存数据库访问速率快的特点,本文分别从单线程.多线程(并发访问)和多线程读/写混合访问角度对eXtremeDB数据库读写速率展开测试. ...

  6. nosql数据库选型

    http://blogread.cn/it/article/6654 今天在书店里翻完了一遍<七天七数据库>.这本书简单介绍了postgreSQL,riak,mongodb,HBase,r ...

  7. {MySQL数据库初识}一 数据库概述 二 MySQL介绍 三 MySQL的下载安装、简单应用及目录介绍 四 root用户密码设置及忘记密码的解决方案 五 修改字符集编码 六 初识sql语句

    MySQL数据库初识 MySQL数据库 本节目录 一 数据库概述 二 MySQL介绍 三 MySQL的下载安装.简单应用及目录介绍 四 root用户密码设置及忘记密码的解决方案 五 修改字符集编码 六 ...

  8. 固态硬盘和机械硬盘的比较和SQLSERVER在两种硬盘上的性能差异

    固态硬盘和机械硬盘的比较和SQLSERVER在两种硬盘上的性能差异 在看这篇文章之前可以先看一下下面的文章: SSD小白用户收货!SSD的误区如何解决 这样配会损失性能?实测6种特殊装机方式 听说固态 ...

  9. 重新学习MySQL数据库3:Mysql存储引擎与数据存储原理

    重新学习Mysql数据库3:Mysql存储引擎与数据存储原理 数据库的定义 很多开发者在最开始时其实都对数据库有一个比较模糊的认识,觉得数据库就是一堆数据的集合,但是实际却比这复杂的多,数据库领域中有 ...

随机推荐

  1. 在WPF中实现玻璃模糊效果

    在WPF中实现玻璃模糊效果还是比较简单的,主要方式如下: 添加一个Rectangle或其它控件作为玻璃放到顶部图层 将底部图像作为Brush(大多数的时候用VisualBrush)填充到Rectang ...

  2. Dual-voltage regulator meets USB-power needs

    This Design Idea stems from the limited availability of IC voltage regulators that can meet key USB- ...

  3. TCP/IP具体解释--TCP/UDP优化设置总结&amp; MTU的相关介绍

    首先要看TCP/IP协议,涉及到四层:链路层,网络层.传输层,应用层. 当中以太网(Ethernet)的数据帧在链路层 IP包在网络层 TCP或UDP包在传输层 TCP或UDP中的数据(Data)在应 ...

  4. WinForm中DataGridView验证单元格输入的是数字

    转载:http://www.cnblogs.com/ganqiyin/archive/2013/02/18/2915491.html 事件:DataGridView验证单元格输入的是数字,DataGr ...

  5. linux里install命令和cp命令的区别

    转:http://blog.yikuyiku.com/?p=2659 基本上,在Makefile里会用到install,其他地方会用cp命令. 它们完成同样的任务——拷贝文件,它们之间的区别主要如下: ...

  6. combogrid 摘要

    可装载组合框 - ComboBox 继承自$.fn.combo.defaults,通过$.fn.combobox.defaults覆盖默认值 combobox显示的是一个可以编辑的文本框和一个下拉列表 ...

  7. 神经网络可以拟合任意函数的视觉证明A visual proof that neural nets can compute any function

    One of the most striking facts about neural networks is that they can compute any function at all. T ...

  8. mysql中避免使用保留字和关键字做列的名字

    设计数据表时,应尽量避免使用MySQL的关键字和保留字作为表名或列名. 比如key和keys为保留字,如果不小心使用关键字或者保留字作为列名字,执行下面的语句会出现语法错误: select * fro ...

  9. selinux改变状态不需要重启的方法

    1.selinux的配置路径/var/selinux/config,配置内容为 2.配置文件修改完,需要重启系统,才能生效 3.使用sestatus -v 查看当前selinux功能情况: 4.使用s ...

  10. TYVJ 2002 扑克牌 题解

    P2002 扑克牌 时间: 1000ms / 空间: 131072KiB / Java类名: Main 背景 Admin生日那天,Rainbow来找Admin玩扑克牌……玩着玩着Rainbow觉得太没 ...