亚洲视频二区_亚洲欧洲日本天天堂在线观看_日韩一区二区在线观看_中文字幕不卡一区

公告:魔扣目錄網(wǎng)為廣大站長(zhǎng)提供免費(fèi)收錄網(wǎng)站服務(wù),提交前請(qǐng)做好本站友鏈:【 網(wǎng)站目錄:http://www.430618.com 】, 免友鏈快審服務(wù)(50元/站),

點(diǎn)擊這里在線(xiàn)咨詢(xún)客服
新站提交
  • 網(wǎng)站:51998
  • 待審:31
  • 小程序:12
  • 文章:1030137
  • 會(huì)員:747

 

最近做一個(gè)數(shù)據(jù)可視化項(xiàng)目時(shí),需要 Mock 大量的數(shù)據(jù)(千萬(wàn)級(jí))來(lái)進(jìn)行接口開(kāi)發(fā)。本文將記錄探索實(shí)踐的全部過(guò)程。

1. 如何快速 Mock 大量數(shù)據(jù)

1.1 逐條插入數(shù)據(jù)

因?yàn)椴┲髦鳂I(yè)是搞前端開(kāi)發(fā)的,對(duì) MySQL 其實(shí)不是特別在行了。要 Mock 數(shù)據(jù),第一想法當(dāng)然是寫(xiě)個(gè)程序或腳本來(lái)自動(dòng)插入數(shù)據(jù)了。于是說(shuō)干就干,很快一個(gè)基于 NodeJs 的 demo 就完成了。

建表 sql(為了演示方便,這里僅取4個(gè)字段,原測(cè)試 demo 有 21 個(gè)字段):

use test;
CREATE TABLE test.data (
 `id` INT NOT NULL,
 `nt` VARCHAR(100) NOT NULL,
 `imei` VARCHAR(100) NOT NULL,
 `model` VARCHAR(50) NOT NULL,
 PRIMARY KEY (id)
)

逐條插入數(shù)據(jù)代碼:

let mysql = require('mysql');
const uuidv1 = require('uuid/v1');
let connection = mysql.createConnection({
 host: 'localhost',
 port: '6666',
 user: 'root',
 password: '123456',
 database: 'test'
});
const close = () => connection.end();
function network() {
 return ['"wifi"', '"g4"', '"g3"', '"g2"'][Math.floor(Math.random() * 4)]
}
function phone_model() {
 return ['"NEX"','"x23"','"x21"','"x20"'][Math.floor(Math.random() * 4)]
}
function imei() {
 return `"${uuidv1()}"`;
}
connection.connect();
let s = Date.now();
let i = 0;
function insert() {
 connection.query(`insert into data(id, nt, imei, model) values (${i}, ${network()}, ${imei()}, ${phone_model()})`,
 function (error, results, fields) {
 if (error) throw error;
 if (i + 1 < 100000) {
 i++;
 insert();
 } else {
 console.log('done:' + (Date.now() - s));
 }
 });
}
insert();

用 10 條數(shù)據(jù)測(cè)試了下,perfect!完美工作。清空表,數(shù)量加大到1萬(wàn)條數(shù)據(jù)測(cè)試,勉強(qiáng) perfect ,這次插入1萬(wàn)數(shù)據(jù)耗時(shí)48192ms,也就是48s左右,還能勉強(qiáng)接受。

繼續(xù)擴(kuò)量到10萬(wàn)條數(shù)據(jù),這下就尷尬的很明顯了,生成10萬(wàn)條數(shù)據(jù),一共耗時(shí)618983ms,618s,也就是10分鐘左右。大概心里估計(jì)了下,就算以線(xiàn)性遞增來(lái)算,那么100萬(wàn)條數(shù)據(jù)大概就是100分鐘,1000萬(wàn)數(shù)據(jù)大概是1000分鐘,也就是近17個(gè)小時(shí)。

很明顯,這效率太慢了,必須尋找效率更高的方式。

1.2 使用儲(chǔ)存過(guò)程批量插入數(shù)據(jù)

在網(wǎng)上搜索了一會(huì)兒,果然找到了一種新方式:使用 mysql 儲(chǔ)存過(guò)程來(lái)批量插入數(shù)據(jù)。所謂“儲(chǔ)存過(guò)程”,個(gè)人認(rèn)為就是批處理。

建表 sql,因?yàn)閿?shù)據(jù)量大,這里加上了分區(qū):

use test;
CREATE TABLE test.data (
 `id` INT NOT NULL,
 `nt` VARCHAR(100) NOT NULL,
 `imei` VARCHAR(100) NOT NULL,
 `model` VARCHAR(50) NOT NULL,
 PRIMARY KEY (id)
) ENGINE = MyISAM ROW_FORMAT = DEFAULT
 partition BY RANGE (id) (
 partition p0 VALUES LESS THAN (10000000),
 partition p1 VALUES LESS THAN (20000000),
 partition p2 VALUES LESS THAN (30000000),
 partition p3 VALUES LESS THAN (40000000),
 partition p4 VALUES LESS THAN (50000000),
 partition p5 VALUES LESS THAN (60000000),
 partition p6 VALUES LESS THAN (70000000),
 partition p7 VALUES LESS THAN (80000000),
 partition p8 VALUES LESS THAN (90000000),
 Partition p9 VALUES LESS THAN MAXVALUE
 );

接著是創(chuàng)建 mysql 儲(chǔ)存過(guò)程,不過(guò)在編寫(xiě)儲(chǔ)存過(guò)程代碼時(shí),遇到了一個(gè)問(wèn)題,如何實(shí)現(xiàn)下面函數(shù)的功能,即隨機(jī)從 wigi, 4g, 3g, 2g 中返回一個(gè)網(wǎng)絡(luò)類(lèi)型。

function network() {
 return ['"wifi"', '"g4"', '"g3"', '"g2"'][Math.floor(Math.random() * 4)]
}

2. 如何在儲(chǔ)存過(guò)程中基于數(shù)組來(lái)生成隨機(jī)值

查了大量資料,發(fā)現(xiàn) mysql 儲(chǔ)存過(guò)程不支持?jǐn)?shù)組操作。一時(shí)間,似乎走到了死胡同。最后發(fā)現(xiàn)了這篇文章:MySQL函數(shù)和存儲(chǔ)過(guò)程生成電話(huà)號(hào)碼。作者生成電話(huà)號(hào)碼的思路給了我啟發(fā),于是我參照他的思路,實(shí)現(xiàn)了隨機(jī)生成網(wǎng)絡(luò)類(lèi)型的功能。

----------------------------
-- 生成網(wǎng)絡(luò)類(lèi)型的函數(shù)
----------------------------
DELIMITER $$
create function network() returns char(4)
begin 
 declare networks varchar(100) default "wifi4g 3g 2g "; -- 1,5,9,13
 declare idx int;
 declare ret char(4);
 set idx = 1+floor(rand()*4)*4;
 set ret = trim(substring(networks,idx,4));
 return ret;
end $$
DELIMITER ;

大概思路就是:

  • 找出數(shù)組中最長(zhǎng)的字符串項(xiàng),比如 wifi,4g,3g,2g 中最長(zhǎng)的項(xiàng)是 'wifi',長(zhǎng)度為4
  • 將數(shù)組所有項(xiàng)用空格填充,讓其與最長(zhǎng)項(xiàng)長(zhǎng)度一樣,即wifi4g 3g 2g
  • 隨機(jī)生成固定的字符截取起始點(diǎn)。這里的隨機(jī),固定可能會(huì)不太好理解。看這個(gè)表達(dá)式1+floor(rand()*4)*4就清楚了,此表達(dá)式總是返回 1,5,9,13中某個(gè)值
  • 截取字符串,同時(shí)去掉填充的空格,trim(substring(networks,idx,4)),就得到隨機(jī)值了

解決隨機(jī)生成值的問(wèn)題后,儲(chǔ)存過(guò)程的代碼也就出來(lái)了:

----------------------------
-- 生成網(wǎng)絡(luò)類(lèi)型的函數(shù)
----------------------------
DELIMITER $$
create function network() returns char(4)
begin 
 declare networks varchar(100) default "wifi4g 3g 2g "; -- 1,5,9,13
 declare idx int;
 declare ret char(4);
 set idx = 1+floor(rand()*4)*4;
 set ret = trim(substring(networks,idx,4));
 return ret;
end $$
DELIMITER ;
----------------------------
-- 生成機(jī)型的函數(shù)
----------------------------
DELIMITER $$
create function phone_model() returns char(10)
begin 
 declare phone_types varchar(100) default "NEX x23 x21 x20 x9 x7 x6 x5 Z1 Z2 Z3 Y97 Y91 Y85 Y83 Y81 Y79 ";
 declare idx int;
 declare ret char(10);
 set idx = 1+floor(rand()*17)*4;
 set ret = trim(substring(phone_types,idx,4));
 return ret;
end $$
DELIMITER ;
----------------------------
-- 生成IMEI的函數(shù)
----------------------------
DELIMITER $$
create function randchar() returns char(5)
begin
 declare ret char(5); 
 set ret = substring("ABCDEFGHIJKLMNOPQRSTUVWXYZ",floor(1+26*rand()),1);
 return ret;
end $$
DELIMITER ;
DELIMITER $$
create function imei() returns char(50)
begin
 declare ret char(50) default ""; 
 declare imeiLen int default 11;
 DECLARE idx INT default 0;
 WHILE idx < imeiLen DO
 SET idx = idx + 1;
 SET ret = CONCAT(ret, randchar());
 END WHILE;
 return ret;
end $$
DELIMITER ;
----------------------------
-- 創(chuàng)建儲(chǔ)存過(guò)程
----------------------------
use test;
DROP PROCEDURE IF EXISTS test.BatchInsertCustomer;
delimiter //
CREATE PROCEDURE BatchInsertCustomer(IN start INT,IN loop_time INT)
 BEGIN
 DECLARE Var INT;
 DECLARE ID INT;
 SET Var = 0;
 SET ID= start;
 WHILE Var < loop_time DO
 insert into data(`id`, `nt`, `imei`, `model`) 
 values (ID, network(), imei(), phone_model());
 SET Var = Var + 1;
 SET ID = ID + 1;
 END WHILE;
 END;
 //
delimiter ;

調(diào)用儲(chǔ)存過(guò)程:

-- 調(diào)用
ALTER TABLE test DISABLE KEYS;
CALL BatchInsertCustomer(1, 10);
ALTER TABLE test ENABLE KEYS;

在測(cè)試時(shí),使用儲(chǔ)存過(guò)程生成1000萬(wàn)數(shù)據(jù)大概是140分鐘,不到2個(gè)半小時(shí)。相比逐條插入的17個(gè)小時(shí),快了8,9倍,效率提升不少。

3. 小結(jié)

使用 mysql 儲(chǔ)存過(guò)程可以快速地生成 Mock 數(shù)據(jù)。同時(shí)本文還提供了一種“如何在儲(chǔ)存過(guò)程中基于數(shù)組來(lái)生成隨機(jī)值“的思路,希望對(duì)大家有些幫助。

3.1 參考

  • MySQL批量插入大量數(shù)據(jù)方法
  • MySQL函數(shù)和存儲(chǔ)過(guò)程生成電話(huà)號(hào)碼

分享到:
標(biāo)簽:性能測(cè)試 mysql
用戶(hù)無(wú)頭像

網(wǎng)友整理

注冊(cè)時(shí)間:

網(wǎng)站:5 個(gè)   小程序:0 個(gè)  文章:12 篇

  • 51998

    網(wǎng)站

  • 12

    小程序

  • 1030137

    文章

  • 747

    會(huì)員

趕快注冊(cè)賬號(hào),推廣您的網(wǎng)站吧!
最新入駐小程序

數(shù)獨(dú)大挑戰(zhàn)2018-06-03

數(shù)獨(dú)一種數(shù)學(xué)游戲,玩家需要根據(jù)9

答題星2018-06-03

您可以通過(guò)答題星輕松地創(chuàng)建試卷

全階人生考試2018-06-03

各種考試題,題庫(kù),初中,高中,大學(xué)四六

運(yùn)動(dòng)步數(shù)有氧達(dá)人2018-06-03

記錄運(yùn)動(dòng)步數(shù),積累氧氣值。還可偷

每日養(yǎng)生app2018-06-03

每日養(yǎng)生,天天健康

體育訓(xùn)練成績(jī)?cè)u(píng)定2018-06-03

通用課目體育訓(xùn)練成績(jī)?cè)u(píng)定