zoukankan      html  css  js  c++  java
  • 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的语法结构如下:

    复制代码
    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字段,但是我们还必须为表添加一个主键列,并让其自动增长,这样我们在添加数据的时候就不需要手动添加主键列。因此表结构如下:

    复制代码
    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 SettingsAll UsersApplication DataMySQL 中,比如我们的csdndb就在路径C:Documents and SettingsAll UsersApplication DataMySQLMySQL Server 5.1datacsdndb当中。如果经常恢复系统的话,放在c盘不安全,可以在安装的时候修改安装路径。如下图所示:

    2.导入Sql Server数据库

    参考文献:http://qiaolevip.iteye.com/blog/1324649

    2.1.BULK INSERT语法

    在Sql Server中,使用BULK INSERT命令导入数据,该命令以用户指定的格式将数据文件导入到数据库表或视图中。BULK INSERT语法结构如下:

    复制代码
    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. 创建数据库表

    复制代码
    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导入数据

    复制代码
    bulk insert csdn1
    from 'D:www.csdn.net.sql'
    with(
        --FORMATFILE = 'C:BCPFORMAT.xml',
        --FirstRow --default 1
        --KEEPIDENTITY,
        fieldterminator = ' # ',
        rowterminator = '
    '
    )
    复制代码

    (6428632 行受影响),耗时:00:02:00

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

    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表:

    复制代码
    --创建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
    )
    复制代码

    然后使用如下命令进行导入:

    复制代码
    --导入数据
    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表

    复制代码
    CREATE TABLE "SCOTT"."CSDN"
      (
        "USERNAME"    VARCHAR2(256 BYTE),
        "PASSWORD"   VARCHAR2(256 BYTE),
        "EMAIL" VARCHAR2(256 BYTE)
      )
    复制代码

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

    复制代码
    UNRECOVERABLE
    LOAD DATA INFILE 'D:www.csdn.net.sql' 
    INSERT into table CSDN 
    fields terminated by '#'
    (
        USERNAME,
        PASSWORD,
        EMAIL
    )
    复制代码

    打开cmd命令行,使用sqlldr命令进行导入,导入命令如下:

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

    输出的日志文件为resulthis.out,他在C:Usersxuwei目录下,因为上述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:Usersxuwei>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 + "
    "); 
                }
                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:Usersxuwei>sqlldr userid=scott/tiger@orcl control=D:/ora_csdn3.ctrl DIRECT=TRUE log=resulthis.out

    输出的日志文件为resulthis.out,他在C:Usersxuwei目录下,因为上述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 -- 表的字段没有对应的值时允许为空

  • 相关阅读:
    软件测试人员的年终绩效考核怎么应对
    收藏
    顶踩组件 前后两版
    订阅组件
    hdu 1963 Investment 完全背包
    hdu 4939 Stupid Tower Defense 动态规划
    hdu 4405 Aeroplane chess 动态规划
    cf 414B Mashmokh and ACM 动态规划
    BUPT 202 Chocolate Machine 动态规划
    hdu 3853 LOOPS 动态规划
  • 原文地址:https://www.cnblogs.com/bluedy1229/p/3723600.html
Copyright © 2011-2022 走看看