<em>Mac</em>Book项目 2009年学校开始实施<em>Mac</em>Book项目,所有师生配备一本<em>Mac</em>Book,并同步更新了校园无线网络。学校每周进行电脑技术更新,每月发送技术支持资料,极大改变了教学及学习方式。因此2011
2021-06-01 09:32:01
進行測試之前首先保證你已經可以對資料庫進行讀寫:參見
要求:對MYSQL資料庫的讀寫讀寫效能進行測試。支援多並行、支援調整事物提交記錄數。
注意事項:
要執行測試需要
1. 需要修改資料庫的設定資訊DB_DRIVER、DB_URL、DB_USERNAME、DB_PASSWORD;
2.DB_URL中還要指定哪個資料庫。“dbc:mysql://localhost:3306/test”其中的test就是我鎖用的那個資料庫;
3. 修改TABLE_NAME指定資料庫測試的表名(此處是student表),測試程式會查詢這個表的定義來生成寫入SQL語句;
4.還有此語句 if (column.equalsIgnoreCase("name")) 中的那麼為你建立的表的key,這個也要對用調整過來;
5. 修改concurrentList指定需要測試並行數列表,預設測試1,5,10,20四種並行數;
6. 修改batchSizeList指定每次測試的事務提交記錄資料,預設是100,200,500,1000
最後執行測試,會生成類似下面的結果:
測試完成後檢查該student表,輸入select * from student; 可以看到源源不斷的資料的輸出,插入的表項太多了。
具體查了多少資料呢?使用select count(*) from student;檢視。
可能遇到的問題:
(1)UUID.randomUUID().toString()生成的主鍵會很長,因此主鍵name的長度應設的長一些否則會出現如下報錯:
由上上截圖可以看到生成的主鍵還是蠻長的。
(2)每次測試的時候最好將上一次測試的table刪除重新建一個。否則測試的資料之間相差很大。
建立student表的SQL語句如下:
--刪除student表的SQL語句 drop table student; --查詢表格項數大小的語句 select count(*) from student; --建立student表,注意key的預留空間較大 create table student (name varchar(120) not null, goal varchar(20) not null, primary key(name));
程式程式碼如下:
import java.sql.Connection; import java.sql.DriverManager; import java.sql.PreparedStatement; import java.sql.ResultSet; import java.sql.ResultSetMetaData; import java.sql.SQLException; import java.sql.Statement; import java.sql.Timestamp; import java.sql.Types; import java.util.ArrayList; import java.util.Calendar; import java.util.Collections; import java.util.Formatter; import java.util.LinkedHashMap; import java.util.List; import java.util.Map; import java.util.Random; import java.util.UUID; import java.util.concurrent.CountDownLatch; import java.util.logging.Level; import java.util.logging.Logger; public class InsertTest { private static Logger logger = Logger.getLogger(InsertTest.class.getName()); //驅動程式名 private static final String DB_DRIVER = "com.mysql.cj.jdbc.Driver"; //URL指向要存取的資料庫名mysql private static final String DB_URL = "jdbc:mysql://localhost:3306/test?rewriteBatchedStatements=true&useSSL=false&serverTimezone=UTC"; //MySQL設定時的使用者名稱 private static final String DB_USERNAME = "root"; //MySQL設定時的密碼 private static final String DB_PASSWORD = "…………"; private static Random random = new Random(10000); //我們要測試的表的名稱 private static final String TABLE_NAME = "student"; private int batchSize;//一批提交的事務數 private int concurrent;// private int sampling;// public static void main(String[] args) throws Exception { printHeader(); int[] concurrentList = new int[]{1, 5, 10, 20};//預設測試1,5,10,20個並行 int[] batchSizeList = new int[] {100, 200, 500, 1000};//一批提交的事務數 for (int concurrent : concurrentList) { for (int batchSize : batchSizeList) { //對以上每種組合都run一次 new InsertTest(batchSize, concurrent).run(true); } Thread.sleep(10000); } } /*-----------InsertTest類別建構函式一-------------*/ public InsertTest(final int batchSize, final int concurrent) throws Exception { this.batchSize = batchSize; this.concurrent = concurrent; this.sampling = 100; } /*-----------InsertTest類別建構函式二-------------*/ public InsertTest(final int batchSize, final int concurrent, final int sampling) throws Exception { this.batchSize = batchSize; this.concurrent = concurrent; this.sampling = sampling; } /*-----------開始執行run方法-------------*/ public void run(boolean printResult) throws Exception { final List<Long> results = Collections.synchronizedList(new ArrayList<Long>()); final CountDownLatch startGate = new CountDownLatch(concurrent); final CountDownLatch endGate = new CountDownLatch(concurrent); for (int idxConcurrent = 0; idxConcurrent < concurrent; idxConcurrent++) { new Thread(new Runnable() { public void run() { startGate.countDown(); try { long time = execute(); long avg = batchSize * sampling * 1000 / time;; results.add(Long.valueOf(avg)); } catch(Exception ex) { ex.printStackTrace(); } finally { endGate.countDown(); } } }).start(); } endGate.await(); Collections.sort(results); //每種組合跑完之後都列印出一行資料 if (printResult) { printResult(batchSize, concurrent, results); } } public long execute() throws Exception { Connection conn = getConnection(); Map<String, Integer> columns = queryTableColumns(conn); String insertSQL = generateInsertSQL(columns); PreparedStatement ps = conn.prepareStatement(insertSQL); try { long start = System.currentTimeMillis(); for (int i = 0; i < sampling; i++) { execute(conn, ps, columns); } long stop = System.currentTimeMillis(); return stop - start; } catch(Exception ex) { logger.log(Level.SEVERE, null, ex); conn.rollback(); conn.close(); throw ex; } finally { conn.close(); } } //執行插入語句出錯。 ps:INSERT INTO student1(name,goal)VALUES(** NOT SPECIFIED **,** NOT SPECIFIED **) public void execute(Connection conn, PreparedStatement ps, Map<String, Integer> columns) throws Exception { try { for (int idx = 0; idx < batchSize; idx++) { int idxColumn = 1; //這個地方實際上是對每一列進行迴圈。(1)如果該列是key對應的列………… (2)該列為普通列 for (String column : columns.keySet()) { //如果該列為name列即key對應的列,就單獨為他生成一個主鍵。 //為了執行忽略大小寫的比較,使用equalsIgnoreCase if (column.equalsIgnoreCase("name")) { //給JDBC的SQL語句的預留位置賦值的,即是下面的「? connection.prepareStatement("insert into t_user values (?,?)"); //UUID.randomUUID().toString()是java JDK提供的一個自動生成主鍵的方法。 ps.setObject(idxColumn, UUID.randomUUID().toString()); } //否則就是普通列,隨便填充點東西進去就好了。 else { ps.setObject(idxColumn, generateColumnValue(columns.get(column))); } idxColumn ++; } ps.addBatch(); } //批次執行SQL語句 ps.executeBatch(); conn.commit(); ps.clearBatch(); } //如果上面出錯了就捕獲其異常 catch (SQLException ex) { logger.log(Level.SEVERE, null, ex); if (null != ex.getNextException()) { logger.log(Level.SEVERE, null, ex.getNextException()); } conn.rollback(); throw ex; } } //根據獲取的列資訊,生成插入的sql語句。 private String generateInsertSQL(Map<String, Integer> columns) throws SQLException { StringBuilder sb = new StringBuilder(); StringBuffer sbColumns = new StringBuffer(); StringBuffer sbValues = new StringBuffer(); sb.append("INSERT INTO ").append(TABLE_NAME); for (String column : columns.keySet()) { if (sbColumns.length() > 0) { sbColumns.append(","); sbValues.append(","); } sbColumns.append(column); sbValues.append("?"); } sb.append("(").append(sbColumns).append(")"); sb.append("VALUES"); sb.append("(").append(sbValues).append(")"); return sb.toString(); } private Map<String, Integer> queryTableColumns(Connection conn) throws Exception { Map<String, Integer> columns = new LinkedHashMap<String, Integer>(); String sql = "SELECT * FROM " + TABLE_NAME + " WHERE 1=0"; Statement stmt = conn.createStatement(); ResultSet rs = stmt.executeQuery(sql); ResultSetMetaData rsmd = rs.getMetaData(); for (int i = 1; i <= rsmd.getColumnCount(); i++) { columns.put(rsmd.getColumnName(i), rsmd.getColumnType(i)); } return columns; } //生成列值 private Object generateColumnValue(int type) { Object obj = null; switch (type) { case Types.DECIMAL: case Types.NUMERIC: case Types.DOUBLE: case Types.FLOAT: case Types.REAL: case Types.BIGINT: case Types.TINYINT: case Types.SMALLINT: case Types.INTEGER: obj = random.nextInt(10000); break; case Types.DATE: obj = Calendar.getInstance().getTime(); break; case Types.TIMESTAMP: obj = new Timestamp(System.currentTimeMillis()); break; default: obj = String.valueOf(random.nextInt(10000)); break; } return obj; } //連線MYSQL資料庫。 private Connection getConnection() throws Exception { Class.forName(DB_DRIVER); Connection conn = DriverManager.getConnection(DB_URL, DB_USERNAME, DB_PASSWORD); conn.setAutoCommit(false); return conn; } //列印出表頭(即列的資訊) private static void printHeader() { StringBuilder sb = new StringBuilder(); sb.append("n"); sb.append(new Formatter().format("%15s|%15s|%15s|%15s|%15s", "BATCH_SIZE", "CONCURRENT", "AVG (r/s)", "MIN (r/s)", "MAX (r/s)")); System.out.println(sb.toString()); } //列印每次跑完後的統計資訊 private static void printResult(int batch, int concurrent, List<Long> results) { Long total = Long.valueOf(0); for (Long result : results) { total += result; } StringBuilder sb = new StringBuilder(); sb.append(new Formatter().format("%15s|%15s|%15s|%15s|%15s", batch, concurrent, (total/results.size()), results.get(0), results.get(results.size() - 1))); System.out.println(sb.toString()); } }
到此這篇關於MYSQL讀寫效能測試的簡單記錄的文章就介紹到這了,更多相關MYSQL讀寫效能測試內容請搜尋it145.com以前的文章或繼續瀏覽下面的相關文章希望大家以後多多支援it145.com!
相關文章
<em>Mac</em>Book项目 2009年学校开始实施<em>Mac</em>Book项目,所有师生配备一本<em>Mac</em>Book,并同步更新了校园无线网络。学校每周进行电脑技术更新,每月发送技术支持资料,极大改变了教学及学习方式。因此2011
2021-06-01 09:32:01
综合看Anker超能充系列的性价比很高,并且与不仅和iPhone12/苹果<em>Mac</em>Book很配,而且适合多设备充电需求的日常使用或差旅场景,不管是安卓还是Switch同样也能用得上它,希望这次分享能给准备购入充电器的小伙伴们有所
2021-06-01 09:31:42
除了L4WUDU与吴亦凡已经多次共事,成为了明面上的厂牌成员,吴亦凡还曾带领20XXCLUB全队参加2020年的一场音乐节,这也是20XXCLUB首次全员合照,王嗣尧Turbo、陈彦希Regi、<em>Mac</em> Ova Seas、林渝植等人全部出场。然而让
2021-06-01 09:31:34
目前应用IPFS的机构:1 谷歌<em>浏览器</em>支持IPFS分布式协议 2 万维网 (历史档案博物馆)数据库 3 火狐<em>浏览器</em>支持 IPFS分布式协议 4 EOS 等数字货币数据存储 5 美国国会图书馆,历史资料永久保存在 IPFS 6 加
2021-06-01 09:31:24
开拓者的车机是兼容苹果和<em>安卓</em>,虽然我不怎么用,但确实兼顾了我家人的很多需求:副驾的门板还配有解锁开关,有的时候老婆开车,下车的时候偶尔会忘记解锁,我在副驾驶可以自己开门:第二排设计很好,不仅配置了一个很大的
2021-06-01 09:30:48
不仅是<em>安卓</em>手机,苹果手机的降价力度也是前所未有了,iPhone12也“跳水价”了,发布价是6799元,如今已经跌至5308元,降价幅度超过1400元,最新定价确认了。iPhone12是苹果首款5G手机,同时也是全球首款5nm芯片的智能机,它
2021-06-01 09:30:45