某社區600萬用戶數據導入MYSQL、MSSQL、Oracle數據庫方法


1.導入MySql數據庫

參考文獻:http://zhuaxia.org/blog/post/145

1.1.LOAD DATA INFILE語法

因為獲得的數據庫文件是一個文本文件www.csdn.net.sql,因此需要用到mysql中的LOAD DATA INFILE命令,LOAD DATA INFILE的語法結構如下:

View Code
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,...]

1.2.創建存放數據的表

觀察文本結構,發現每一行都是如下所示結構:

username # password # email

中間用"#"進行分割。因此我們創建的表必定含有username,password和email字段,但是我們還必須為表添加一個主鍵列,並讓其自動增長,這樣我們在添加數據的時候就不需要手動添加主鍵列。因此表結構如下:

View Code
CREATE TABLE `csdnuser` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `username` varchar(255) DEFAULT NULL,
  `password` varchar(255) DEFAULT NULL,
  `email` varchar(255) DEFAULT NULL,
  PRIMARY KEY (`id`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8;

注意:MySQL中MyISAM引擎與InnoDB引擎有一些區別,但是這並不是本篇博客的主題,因此略過不提。

1.3.導入數據

在創建表以后,我們就可以通過 load data infile命令導入數據了,具體的導入命令如下:

load data local infile 'd:\\www.csdn.net.sql' into table csdnuser2 fields terminated by ' # ' (username,password,email);

大概運行了1分鍾左右就導入完成了,導入完成以后顯示:

Query OK, 6428632 rows affected, 2030 warnings (54.47 sec)
Records: 6428632  Deleted: 0  Skipped: 0  Warnings: 295

注意:

  安裝的MySQL5.1默認的數據庫文件存放的路徑是:C:\Documents and Settings\All Users\Application Data\MySQL 中,比如我們的csdndb就在路徑C:\Documents and Settings\All Users\Application Data\MySQL\MySQL Server 5.1\data\csdndb當中。如果經常恢復系統的話,放在c盤不安全,可以在安裝的時候修改安裝路徑。如下圖所示:

2.導入Sql Server數據庫

參考文獻:http://qiaolevip.iteye.com/blog/1324649

2.1.BULK INSERT語法

在Sql Server中,使用BULK INSERT命令導入數據,該命令以用戶指定的格式將數據文件導入到數據庫表或視圖中。BULK INSERT語法結構如下:

View Code
BULK INSERT 
   [ database_name . [ schema_name ] . | schema_name . ] [ table_name | view_name ] 
      FROM 'data_file' 
     [ WITH 
    ( 
   [ [ , ] BATCHSIZE = batch_size ] 
   [ [ , ] CHECK_CONSTRAINTS ] 
   [ [ , ] CODEPAGE = { 'ACP' | 'OEM' | 'RAW' | 'code_page' } ] 
   [ [ , ] DATAFILETYPE = 
      { 'char' | 'native'| 'widechar' | 'widenative' } ] 
   [ [ , ] FIELDTERMINATOR = 'field_terminator' ] 
   [ [ , ] FIRSTROW = first_row ] 
   [ [ , ] FIRE_TRIGGERS ] 
   [ [ , ] FORMATFILE = 'format_file_path' ] 
   [ [ , ] KEEPIDENTITY ] 
   [ [ , ] KEEPNULLS ] 
   [ [ , ] KILOBYTES_PER_BATCH = kilobytes_per_batch ] 
   [ [ , ] LASTROW = last_row ] 
   [ [ , ] MAXERRORS = max_errors ] 
   [ [ , ] ORDER ( { column [ ASC | DESC ] } [ ,...n ] ) ] 
   [ [ , ] ROWS_PER_BATCH = rows_per_batch ] 
   [ [ , ] ROWTERMINATOR = 'row_terminator' ] 
   [ [ , ] TABLOCK ] 
   [ [ , ] ERRORFILE = 'file_name' ] 
    )] 

2.2. 創建數據庫表

View Code
if exists(select * from sysobjects where name = 'csdn1')
    drop table csdn1
create table csdn1(
    --id int identity(1,1) primary key,
    username varchar(50) not null,
    [password] varchar(50) not null,
    email varchar(50) not null
)

2.3.使用bulk insert導入數據

View Code
bulk insert csdn1
from 'D:\www.csdn.net.sql'
with(
    --FORMATFILE = 'C:\BCPFORMAT.xml',
    --FirstRow --default 1
    --KEEPIDENTITY,
    fieldterminator = ' # ',
    rowterminator = '\n'
)

(6428632 行受影響),耗時:00:02:00

其中fieldterminator = ' # ',表示列分隔符,rowterminator = '\n'表示行分隔符。

2.4.添加主鍵列

參考:http://topic.csdn.net/u/20090913/15/fa2e7e65-73d8-4b64-b6e0-bd583f564d86.html?95717

上面的操作雖然將數據導入到了數據庫中,但是我們會發現數據庫表csnd1沒有主鍵列,那么如果我們在表中添加一個www.csdn.net.sql文件中沒有的主鍵列以后,該如何進行數據庫導入呢?經過多次測試,無法使用原來的bulk insert命令進行導入,但是可以用類似bulk的命令進行導入。

首先創建帶主鍵id的csdnuser表:

View Code
--創建csdnuser表
if exists(select * from sysobjects where name = 'csdnuser')
    drop table csdnuser
create table csdnuser(
    id int identity(1,1) primary key,
    username varchar(50) not null,
    [password] varchar(50) not null,
    email varchar(50) not null
)

然后使用如下命令進行導入:

View Code
--導入數據
INSERT INTO csdnuser([username],[password],[email]) 
SELECT * FROM OPENROWSET(
    BULK 'D:/www.csdn.net.sql',
    FORMATFILE='d:/BCPFORMAT.xml'
) AS T;

(6428632 行受影響),耗時:00:01:25

3.導入Oracle數據庫

3.1.目標表只有三列

參考:http://www.cnblogs.com/nocode/archive/2011/12/26/2302343.html

 首先創建數據庫表,我們在scott用戶下創建csdn表

View Code
CREATE TABLE "SCOTT"."CSDN"
  (
    "USERNAME"    VARCHAR2(256 BYTE),
    "PASSWORD"   VARCHAR2(256 BYTE),
    "EMAIL" VARCHAR2(256 BYTE)
  )

創建控制文件D:\www.csdn.net.sql

View Code
UNRECOVERABLE
LOAD DATA INFILE 'D:\www.csdn.net.sql' 
INSERT into table CSDN 
fields terminated by '#'
(
    USERNAME,
    PASSWORD,
    EMAIL
)

打開cmd命令行,使用sqlldr命令進行導入,導入命令如下:

C:\Users\xuwei>sqlldr userid=scott/tiger@orcl control=D:/ora_csdn.ctrl DIRECT=TRUE log=resulthis.out

輸出的日志文件為resulthis.out,他在C:\Users\xuwei目錄下,因為上述sqlldr就在該目錄下運行的。resulthis.out內容如下:

View Code
SQL*Loader: Release 11.1.0.6.0 - Production on 星期一 6月 11 15:17:07 2012

Copyright (c) 1982, 2007, Oracle.  All rights reserved.

控制文件:      D:/ora_csdn.ctrl
數據文件:      D:\www.csdn.net.sql
  錯誤文件:    D:/www.csdn.net.bad
  廢棄文件:    未作指定
 
(可廢棄所有記錄)

要加載的數: ALL
要跳過的數: 0
允許的錯誤: 50
繼續:    未作指定
所用路徑:       直接


加載是 UNRECOVERABLE;產生無效的恢復操作。

表 CSDN,已加載從每個邏輯記錄
插入選項對此表 INSERT 生效

   列名                        位置      長度  中止 包裝數據類型
------------------------------ ---------- ----- ---- ---- ---------------------
USERNAME                            FIRST     *   #       CHARACTER            
PASSWORD                             NEXT     *   #       CHARACTER            
EMAIL                                NEXT     *   #       CHARACTER            


表 CSDN:
  6428632 行 加載成功。
  由於數據錯誤, 0 行 沒有加載。
  由於所有 WHEN 子句失敗, 0 行 沒有加載。
  由於所有字段都為空的, 0 行 沒有加載。

在直接路徑中沒有使用綁定數組大小。
列數組  行數:    5000
流緩沖區字節數:  256000
讀取   緩沖區字節數: 1048576

跳過的邏輯記錄總數:          0
讀取的邏輯記錄總數:       6428632
拒絕的邏輯記錄總數:          0
廢棄的邏輯記錄總數:        0
由 SQL*Loader 主線程加載的流緩沖區總數:     1370
由 SQL*Loader 加載線程加載的流緩沖區總數:        0

從 星期一 6月  11 15:17:07 2012 開始運行
在 星期一 6月  11 15:17:22 2012 處運行結束

經過時間為: 00: 00: 15.08
CPU 時間為: 00: 00: 05.52

通過上述日志可以發現導入耗時為29.86秒。

3.2為數據表添加主鍵列,並且自動增長

參考:

(1)Mysql,SqlServer,Oracle主鍵自動增長的設置

(2)sqlldr 中使用sequence

  起初考慮為主鍵創建sequence,然后通過觸發器來插入主鍵,但是一直報錯。后來通過控制文件中使用sequence來插入主鍵完成操作。

創建數據庫表:CSDNUSER

View Code
CREATE TABLE "SCOTT"."CSDNUSER"
  (
    "ID" int primary key not null,
    "USERNAME"    VARCHAR2(256),
    "PASSWORD"   VARCHAR2(256),
    "EMAIL" VARCHAR2(256)
  )

_______________________________________________

PS:2012-6-11

如果要求索引的等級BLEVEL,可以通過以下查詢語句求出:

select index_name, blevel, num_rows from user_indexes where table_name = 'CSDNUSER'; 

但是發現查找結果為0。后來發現是因為上述建表出現問題,就是沒有為primary key命名,如果沒有指定primary key的名稱,那么系統為默認設定一個名稱,比如SYS_C0038642之類的主鍵名稱。因此我們首先刪除上述主鍵,然后再添加主鍵。

View Code
--刪除主鍵
alter table csdnuser drop constraint SYS_C0038642;
--添加主鍵
alter table csdnuser add constraint pk_csdnuser primary key(ID);

當然也可以直接在建表到時候就創建主鍵名稱

View Code
CREATE TABLE "CSDNUSER"
  (
    "ID"      INT ,
    "USERNAME" VARCHAR2(256),
    "PASSWORD" VARCHAR2(256),
    "EMAIL"    VARCHAR2(256),
    CONSTRAINT "PK_CSDNUSER" PRIMARY KEY ("ID") 
)

在創建主鍵的時候,我們發現花費了一些時間,這是因為主鍵也是占據一定磁盤空間的。

————————————————————————————

創建控制文件:ora_csdn2.ctrl

View Code
load data
infile 'D:\www.csdn2.net.sql'
Append into table CSDNUSER2
fields terminated by ' # '
trailing nullcols
(    ID sequence(max,1),
    USERNAME,
    PASSWORD,
    EMAIL
)

在cmd中執行sqlldr命令

C:\Users\xuwei>sqlldr userid=scott/tiger@orcl control=D:/ora_csdn2.ctrl direct=true  log=resulthis.out

resulthis.out內容如下:

View Code
SQL*Loader: Release 11.1.0.6.0 - Production on 星期一 6月 11 15:30:00 2012

Copyright (c) 1982, 2007, Oracle.  All rights reserved.

控制文件:      D:/ora_csdn2.ctrl
數據文件:      D:\www.csdn.net.sql
  錯誤文件:    D:/www.csdn.net.bad
  廢棄文件:    未作指定
 
(可廢棄所有記錄)

要加載的數: ALL
要跳過的數: 0
允許的錯誤: 50
繼續:    未作指定
所用路徑:       直接


加載是 UNRECOVERABLE;產生無效的恢復操作。

表 CSDNUSER,已加載從每個邏輯記錄
插入選項對此表 INSERT 生效
TRAILING NULLCOLS 選項生效

   列名                        位置      長度  中止 包裝數據類型
------------------------------ ---------- ----- ---- ---- ---------------------
ID                                                        SEQUENCE (MAX, 1)
USERNAME                            FIRST     *           CHARACTER            
    終止符字符串:  ' # '
PASSWORD                             NEXT     *           CHARACTER            
    終止符字符串:  ' # '
EMAIL                                NEXT     *           CHARACTER            
    終止符字符串:  ' # '

表 CSDNUSER 的以下索引已處理:
索引 SCOTT.SYS_C0038642 已成功加載, 具有 6428632 個關鍵字

表 CSDNUSER:
  6428632 行 加載成功。
  由於數據錯誤, 0 行 沒有加載。
  由於所有 WHEN 子句失敗, 0 行 沒有加載。
  由於所有字段都為空的, 0 行 沒有加載。

在直接路徑中沒有使用綁定數組大小。
列數組  行數:    5000
流緩沖區字節數:  256000
讀取   緩沖區字節數: 1048576

跳過的邏輯記錄總數:          0
讀取的邏輯記錄總數:       6428632
拒絕的邏輯記錄總數:          0
廢棄的邏輯記錄總數:        0
由 SQL*Loader 主線程加載的流緩沖區總數:     1370
由 SQL*Loader 加載線程加載的流緩沖區總數:        2

從 星期一 6月  11 15:30:00 2012 開始運行
在 星期一 6月  11 15:31:02 2012 處運行結束

經過時間為: 00: 01: 02.45
CPU 時間為: 00: 00: 15.32

 3.3為數據表添加年齡列(2012-6-13)

  如果要利用上述數據進行數據分析,會發現內容太單調了,下面我們就要為原始數據添加一個年齡age列。即將原始的"username # password # email"的數據源文件變成"username # password # email # age"的文件,age是通過java代碼寫入文件的一個[18,99]區間的一個隨機數。隨機數的生成可以參考前一篇博客:java生成指定范圍的隨機數

通過java程序為www.csdn.net.sql源文件添加一列age,生成一個新的文件www.csdn22.net.sql

View Code
package edu.sjtu.erplab.io;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.FileReader;
import java.io.IOException;
import java.util.Random;

public class FileAddCol {
    public static void main(String[] args) {
        File file = new File("D:\\www.csdn22.net.sql");//
        try {
            FileOutputStream fos = new FileOutputStream(file);//定義輸出流
            BufferedReader br = new BufferedReader(new FileReader("D:\\www.csdn.net.sql"));
            String temp = null;//用於存儲從文件中讀取的每一行。
            StringBuffer sb = new StringBuffer();//變動字符串修改使用StringBuffer
    
            /**
             * 添加年齡列
             */
            int max=99;
            int min=18;
            Random random = new Random();
            while ((temp = br.readLine()) != null) //每次讀取一行,直到文本末尾。
            {
                //如果不清空,則會報錯:java.lang.OutOfMemoryError: Java heap space
                if(sb.length()>1000000)
                {
                    fos.write(sb.toString().getBytes());
                    sb.delete(0, sb.length()-1);
                }
                int s = random.nextInt(max)%(max-min+1) + min;
                temp =temp+" # "+s;
                sb.append(temp + "\r\n"); 
            }
            fos.write(sb.toString().getBytes());
        } catch (FileNotFoundException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }
}

創建數據庫表:csdnuser3

View Code
  CREATE TABLE "SCOTT"."CSDNUSER3"
  (
    "ID"       INT,
    "USERNAME" VARCHAR2(256),
    "PASSWORD" VARCHAR2(256),
    "EMAIL"    VARCHAR2(256),
    "AGE" INT,
    CONSTRAINT "PK_CSDNUSER3_ID" PRIMARY KEY ("ID") 
  )

創建控制文件ora_csdn3.ctrl

View Code
UNRECOVERABLE
load data
infile 'D:\www.csdn22.net.sql'
insert into table CSDNUSER3
fields terminated by ' # '
trailing nullcols
(    ID sequence(max,1),
    USERNAME,
    PASSWORD,
    EMAIL,
    AGE
)

打開cmd命令行,使用sqlldr命令進行導入,導入命令如下:

C:\Users\xuwei>sqlldr userid=scott/tiger@orcl control=D:/ora_csdn3.ctrl DIRECT=TRUE log=resulthis.out

輸出的日志文件為resulthis.out,他在C:\Users\xuwei目錄下,因為上述sqlldr就在該目錄下運行的。resulthis.out內容如下:

View Code
SQL*Loader: Release 11.1.0.6.0 - Production on 星期三 6月 13 12:18:21 2012

Copyright (c) 1982, 2007, Oracle.  All rights reserved.

控制文件:      D:/ora_csdn3.ctrl
數據文件:      D:\www.csdn22.net.sql
  錯誤文件:    D:/www.csdn22.net.bad
  廢棄文件:    未作指定
 
(可廢棄所有記錄)

要加載的數: ALL
要跳過的數: 0
允許的錯誤: 50
繼續:    未作指定
所用路徑:       直接


加載是 UNRECOVERABLE;產生無效的恢復操作。

表 CSDNUSER3,已加載從每個邏輯記錄
插入選項對此表 INSERT 生效
TRAILING NULLCOLS 選項生效

   列名                        位置      長度  中止 包裝數據類型
------------------------------ ---------- ----- ---- ---- ---------------------
ID                                                        SEQUENCE (MAX, 1)
USERNAME                            FIRST     *           CHARACTER            
    終止符字符串:  ' # '
PASSWORD                             NEXT     *           CHARACTER            
    終止符字符串:  ' # '
EMAIL                                NEXT     *           CHARACTER            
    終止符字符串:  ' # '
AGE                                  NEXT     *           CHARACTER            
    終止符字符串:  ' # '

表 CSDNUSER3 的以下索引已處理:
索引 SCOTT.PK_CSDNUSER3_ID 已成功加載, 具有 6428632 個關鍵字

表 CSDNUSER3:
  6428632 行 加載成功。
  由於數據錯誤, 0 行 沒有加載。
  由於所有 WHEN 子句失敗, 0 行 沒有加載。
  由於所有字段都為空的, 0 行 沒有加載。

在直接路徑中沒有使用綁定數組大小。
列數組  行數:    5000
流緩沖區字節數:  256000
讀取   緩沖區字節數: 1048576

跳過的邏輯記錄總數:          0
讀取的邏輯記錄總數:       6428632
拒絕的邏輯記錄總數:          0
廢棄的邏輯記錄總數:        0
由 SQL*Loader 主線程加載的流緩沖區總數:     1523
由 SQL*Loader 加載線程加載的流緩沖區總數:     1202

從 星期三 6月  13 12:18:21 2012 開始運行
在 星期三 6月  13 12:18:59 2012 處運行結束

經過時間為: 00: 00: 38.00
CPU 時間為: 00: 00: 15.88

通過上述日志可以發現導入耗時為38.00秒。

提高 SQL*Loader 的性能:

  1. 一個簡單而容易忽略的問題是,沒有對導入的表使用任何索引和/或約束(主鍵)。如果這樣做,甚至在使用ROWS=參數時,會很明顯降低數據庫導入性能。
  2. 可以添加 DIRECT=TRUE來提高導入數據的性能。當然,在很多情況下,不能使用此參數。
  3. 通過指定 UNRECOVERABLE選項,可以關閉數據庫的日志。這個選項只能和 direct 一起使用。
  4. 可以同時運行多個導入任務。

常規導入與direct導入方式的區別:

常規導入可以通過使用 INSERT語句來導入數據。Direct導入可以跳過數據庫的相關邏輯(DIRECT=TRUE),而直接將數據導入到數據文件中。比如direct導入將不檢測主鍵的唯一性

SQLLDR用法

用法: SQLLDR keyword=value [,keyword=value,...]有效的關鍵字:

View Code
userid -- ORACLE username/password
control -- Control file name
log -- Log file name
bad -- Bad file name
data -- Data file name
discard -- Discard file name
discardmax -- Number of discards to allow        (全部默認)
skip -- Number of logical records to skip  (默認0)
load -- Number of logical records to load  (全部默認)
errors -- Number of errors to allow          (默認50)
rows -- Number of rows in conventional path bind array or between direct path data saves(默認: 常規路徑 64, 所有直接路徑)
bindsize -- Size of conventional path bind array in bytes(默認256000)
silent -- Suppress messages during run (header,feedback,errors,discards,partitions)
direct -- use direct path                    (默認FALSE)
parfile -- parameter file: name of file that contains parameter specifications
parallel -- do parallel load                   (默認FALSE)
file -- File to allocate extents from
skip_unusable_indexes -- disallow/allow unusable indexes or index partitions(默認FALSE)
skip_index_maintenance -- do not maintain indexes, mark affected indexes as unusable(默認FALSE)
readsize -- Size of Read buffer                (默認1048576)
external_table -- use external table for load; NOT_USED, GENERATE_ONLY, EXECUTE(默認NOT_USED)
columnarrayrows -- Number of rows for direct path column array(默認5000)
streamsize -- Size of direct path stream buffer in bytes(默認256000)
multithreading -- use multithreading in direct path
resumable -- enable or disable resumable for current session(默認FALSE)
resumable_name -- text string to help identify resumable statement
resumable_timeout -- wait time (in seconds) for RESUMABLE(默認7200)
date_cache -- size (in entries) of date conversion cache(默認1000)

導入的四種類型

  1. insert     --為缺省方式,在數據裝載開始時要求表為空
  2. append  --在表中追加新記錄
  3. replace  --刪除舊記錄(用 delete from table 語句),替換成新裝載的記錄
  4. truncate --刪除舊記錄(用 truncate table 語句),替換成新裝載的記錄

TRAILING NULLCOLS -- 表的字段沒有對應的值時允許為空

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM