1. 程式人生 > >在MySQL中快速的插入大量測試數據

在MySQL中快速的插入大量測試數據

cep starting pda current class sts nor cat mes

很多時候為了測試數據庫設計是否恰當,優化SQL語句,需要在表中插入大量的數據,怎麽插入大量的數據就是個問題了。

最開始想到的辦法就是寫一個程序通過一個很大的循環來不停的插入,比如這樣:

int i = LOOP_COUNT;
while(i-->=0){
    //insert data here.
}

不過我在這麽做的時候發現這樣插入數據非常的慢,一秒鐘插入的數據量還不到100條,於是想到不要一條一條的插入,而是通過

INSERT INTO TABLE VALUES (),(),(),()...

這樣的方式來插入。於是修改程序為:

int i = LOOP_COUNT;
StringBuilder stringBuilder;
while(i-->=0){
    if(LOOP_COUNT!=i && i%5000==0){
     //通過insert values的方式插入這5000條數據並清空stringBuilder
    }
    stringBuilder.append("(數據)");
}
//插入剩余的數據

這樣做的插入速度是上升了很多,不過如果想要插入大量的輸入,比如上億條,那麽花費的時間還是非常長的。

查詢MySQL的文檔,發現了一個頁面:LOAD DATA INFILE 光看這個名字,覺得有戲,於是仔細看了下。

官方對於這個命令的描述是:

LOAD DATA [LOW_PRIORITY | CONCURRENT] [LOCAL] INFILE ‘file_name‘
    [REPLACE | IGNORE]
    INTO TABLE tbl_name
    [CHARACTER SET charset_name]
    [{FIELDS | COLUMNS}
        [TERMINATED BY ‘string‘]
        [[OPTIONALLY] ENCLOSED BY ‘char‘]
        [ESCAPED BY ‘char‘]
    ]
    [LINES
        [STARTING BY ‘string‘]
        [TERMINATED BY ‘string‘]
    ]
    [IGNORE number LINES]
    [(col_name_or_user_var,...)]
    [SET col_name = expr,...]

命令不復雜,具體的每個參數的意義和用法請看官方的解釋 http://dev.mysql.com/doc/refman/5.5/en/load-data.html

那麽現在做的就是生成數據了,我習慣用\t作為數據的分隔符、用\n作為一行的分隔符,所以生成數據的代碼如下:

long start = System.currentTimeMillis() / 1000;
try {
    File file = new File(FILE);

    if (file.exists()) {
        file.delete();
    }
    file.createNewFile();

    FileOutputStream outStream = new FileOutputStream(file, true);

    StringBuilder builder = new StringBuilder(10240);
    DateFormat dateFormat = new SimpleDateFormat(DATE_FORMAT);
    Random rand = new Random();

    String tmpDate = dateFormat.format(new Date());
    Long tmpTimestamp = System.currentTimeMillis() / 1000;

    int i = 0;
    while (i++ < LOOP) { 
        if (i > 0 && i % 30000 == 0) {
            System.out.println("write offset:" + i);
            outStream.write(builder.toString().getBytes(CHARCODE));
            builder = new StringBuilder(10240);
        }

        if (tmpTimestamp.compareTo(System.currentTimeMillis() / 1000) != 0) {
            tmpDate = dateFormat.format(new Date());
            tmpTimestamp = System.currentTimeMillis() / 1000;
        }

        builder.append(tmpDate);
        builder.append("\t");
        builder.append(rand.nextInt(999));
        builder.append("\t");
        builder.append(Encrypt.md5(System.currentTimeMillis() + "" + rand.nextInt(99999999)));
        builder.append("\t");
        builder.append(rand.nextInt(999) % 2 == 0 ? "AA." : "BB");
        builder.append("\t");
        builder.append(rand.nextFloat() * 2000);
        builder.append("\t");
        builder.append(rand.nextInt(9));
        builder.append("\n");
    }

    System.out.println("write data:" + i);
    outStream.write(builder.toString().getBytes(CHARCODE));

    outStream.close();
} catch (Exception e) {
    e.printStackTrace();
}

System.out.println(System.currentTimeMillis() / 1000 - start);

這段代碼會生成一個數據文件,每一行為一條記錄,然後再使用上面提到的 LOAD DATA 來導入數據就可以了,我在公司的電腦下(2G內存+垃圾雙核CPU,MySQL直接裝在windows下,沒任何優化,developer模式)每秒能達到近萬條的插入速度,比其他方式都快很多。

另外如果想直接用GUI工具操作也可以,比如SQLYog中,右鍵要導入的表,選擇Import – Import CSV Data Using Load Local.. 然後設置好編碼、分隔符後就可以直接導入了。

在MySQL中快速的插入大量測試數據