<rt id="bn8ez"></rt>
<label id="bn8ez"></label>

  • <span id="bn8ez"></span>

    <label id="bn8ez"><meter id="bn8ez"></meter></label>

    自己選擇的路,摸爬滾打也要走下去

    【Oracle】極限挑戰(zhàn)—C#+ODP 100萬條數(shù)據(jù)導(dǎo)入Oracle數(shù)據(jù)庫僅用不到1秒

    作者: Aicken(李鳴)  來源: 博客園  發(fā)布時間: 2010-09-09 21:32  閱讀: 1021 次  原文鏈接   全屏閱讀  [收藏]  
    摘要:在這里我們將看到的是C#中利用ODP實現(xiàn)在Oracle數(shù)據(jù)庫中瞬間導(dǎo)入百萬級數(shù)據(jù),這對快速批量導(dǎo)入的實現(xiàn)有重要意義。

        .Net程序中可以通過ODP調(diào)用特性,對Oracle數(shù)據(jù)庫進(jìn)行操作,今天來講一下數(shù)據(jù)批量插入的功能,所用技術(shù)不高不深,相信很多朋友都接觸過,小弟班門弄斧了,呵呵。這篇文章是上篇文章的續(xù)集,因為上一次試驗的征集結(jié)果沒有突破4秒的方法,所以這次繼續(xù)挑戰(zhàn)與挖掘新方法,雖然是Oracle,但仍具有一定收藏意義。

        上一次文章中提及的試驗:

        極限挑戰(zhàn)—C#100萬條數(shù)據(jù)導(dǎo)入SQL SERVER數(shù)據(jù)庫僅用4秒 (附源碼)

        http://kb.cnblogs.com/page/73491/

        這個試驗是針對SQL SERVER數(shù)據(jù)庫的,宿主環(huán)境也是.Net,有興趣的朋友可以將這兩個試驗對比一下,為日后工作批量導(dǎo)數(shù)提供支持。

        另外,一些朋友對上次試驗環(huán)境有些異議,認(rèn)為應(yīng)該對數(shù)據(jù)庫和服務(wù)器做優(yōu)化或設(shè)置,以體現(xiàn)試驗最終的時間結(jié)果。這個固然會影響試驗的時間結(jié)果,但考慮到在試驗環(huán)境中,對數(shù)據(jù)庫優(yōu)化的標(biāo)準(zhǔn)與優(yōu)化程度不便統(tǒng)一與定量,試驗結(jié)果也不易說明其影響源,所以這次試驗依然以標(biāo)準(zhǔn)數(shù)據(jù)庫建庫后的配置為主,試驗所在服務(wù)器硬件環(huán)境與上次試驗保持一致。實驗?zāi)康脑谟谕诰颉Ρ人拗鞒绦蛑械臄?shù)據(jù)批量操作方法。

        有新方法提升性能時間指標(biāo)的朋友,歡迎互相切磋,互相提高,嘴上功夫就免了。。。

        好了正文開始。

        ● 普通肉墊式

        什么叫批量插入呢,就是一次性插入一批數(shù)據(jù),我們可以把這批數(shù)據(jù)理解為一個大的數(shù)組,而這些全部只通過一個SQL來實現(xiàn),而在傳統(tǒng)方式下,需要調(diào)用很多次的SQL才可以完成,這就是著名的“數(shù)組綁定”的功能。我們先來看一下傳統(tǒng)方式下,插入多行記錄的操作方式:

    代碼
    //設(shè)置一個數(shù)據(jù)庫的連接串,

    string connectStr = "User Id=scott;Password=tiger;Data Source=";

    OracleConnection conn
    = new OracleConnection(connectStr);

    OracleCommand command
    = new OracleCommand();

    command.Connection
    = conn;

    conn.Open();

    Stopwatch sw
    = new Stopwatch();

    sw.Start();

    //通過循環(huán)寫入大量的數(shù)據(jù),這種方法顯然是肉墊

    for (int i = 0; i < recc; i++)

    {

    string sql = "insert into dept values(" + i.ToString()

    + "," + i.ToString() + "," + i.ToString() + ")";

    command.CommandText
    = sql;

    command.ExecuteNonQuery();

    }

    sw.Stop();

    System.Diagnostics.Debug.WriteLine(
    "普通插入:" + recc.ToString()

    + "所占時間:" + sw.ElapsedMilliseconds.ToString());

        我們先準(zhǔn)備好程序,但是先不做時間的測定,因為在后面我們會用多次循環(huán)的方式來計算所占用的時間。

        ● 使用ODP特性

        看上面的程序,大家都很熟悉,因為它沒有用到任何ODP的特性,而緊接著我們就要來介紹一個神奇的程序了,我們看一下代碼,為了更直觀,我把所有的注釋及說明直接寫在代碼里:

    代碼
    //設(shè)置一個數(shù)據(jù)庫的連接串

    string connectStr = "User Id=scott;Password=tiger;Data Source=";

    OracleConnection conn
    = new OracleConnection(connectStr);

    OracleCommand command
    = new OracleCommand();

    command.Connection
    = conn;

    //到此為止,還都是我們熟悉的代碼,下面就要開始嘍

    //這個參數(shù)需要指定每次批插入的記錄數(shù)

    command.ArrayBindCount
    = recc;

    //在這個命令行中,用到了參數(shù),參數(shù)我們很熟悉,但是這個參數(shù)在傳值的時候

    //用到的是數(shù)組,而不是單個的值,這就是它獨特的地方

    command.CommandText
    = "insert into dept values(:deptno, :deptname, :loc)";

    conn.Open();

    //下面定義幾個數(shù)組,分別表示三個字段,數(shù)組的長度由參數(shù)直接給出

    int[] deptNo = new int[recc];

    string[] dname = new string[recc];

    string[] loc = new string[recc];

    // 為了傳遞參數(shù),不可避免的要使用參數(shù),下面會連續(xù)定義三個

    // 從名稱可以直接看出每個參數(shù)的含義,不在每個解釋了

    OracleParameter deptNoParam
    = new OracleParameter("deptno",

    OracleDbType.Int32);

    deptNoParam.Direction
    = ParameterDirection.Input;

    deptNoParam.Value
    = deptNo;

    command.Parameters.Add(deptNoParam);

    OracleParameter deptNameParam
    = new OracleParameter("deptname",

    OracleDbType.Varchar2);

    deptNameParam.Direction
    = ParameterDirection.Input;

    deptNameParam.Value
    = dname;

    command.Parameters.Add(deptNameParam);

    OracleParameter deptLocParam
    = new OracleParameter("loc",

    OracleDbType.Varchar2);

    deptLocParam.Direction
    = ParameterDirection.Input;

    deptLocParam.Value
    = loc;

    command.Parameters.Add(deptLocParam);

    Stopwatch sw
    = new Stopwatch();

    sw.Start();

    //在下面的循環(huán)中,先把數(shù)組定義好,而不是像上面那樣直接生成SQL

    for (int i = 0; i < recc; i++)

    {

    deptNo[i]
    = i;

    dname[i]
    = i.ToString();

    loc[i]
    = i.ToString();

    }

    //這個調(diào)用將把參數(shù)數(shù)組傳進(jìn)SQL,同時寫入數(shù)據(jù)庫

    command.ExecuteNonQuery();

    sw.Stop();

    System.Diagnostics.Debug.WriteLine(
    "批量插入:" + recc.ToString()

    + "所占時間:" +sw.ElapsedMilliseconds.ToString());

        以上代碼略顯冗長,但是加上注釋后基本也就表達(dá)清楚了。

        好了,到目前為止,兩種方式的插入操作程序已經(jīng)完成,就剩下對比了。我在主函數(shù)處寫了一個小函數(shù),循環(huán)多次對兩個方法進(jìn)行調(diào)用,并且同時記錄下時間,對比函數(shù)如下:

    for (int i = 1; i <= 50; i++)

    {

    Truncate();

    OrdinaryInsert(i
    * 1000);

    Truncate();

    BatchInsert(i
    * 1000);

    }
     

        當(dāng)數(shù)據(jù)量達(dá)到100萬級別時,所用時間依然令人滿意,最快一次達(dá)到890毫秒,一般為1秒左右。

        經(jīng)過試驗,得出一組數(shù)據(jù),可以看出兩種方式在效率方面驚人的差距(占用時間的單位為毫秒),部分?jǐn)?shù)據(jù)如下:

    記錄數(shù)

    標(biāo)準(zhǔn)

    批處理

    1000

    1545

    29

    2000

    3514

    20

    3000

    3749

    113

    4000

    5737

    40

    5000

    6820

    52

    6000

    9469

    72

    7000

    10226

    69

    8000

    15280

    123

    9000

    11475

    83

    10000

    14536

    121

    11000

    15705

    130

    12000

    16548

    145

    13000

    18765

    125

    14000

    20393

    116

    15000

    22181

    159

     
      因為篇幅原因,不再粘貼全部的數(shù)據(jù),但是我們可以看一下由此數(shù)據(jù)生成的散點圖:

    clip_image002

        其中有些數(shù)據(jù)有些跳躍,可能和數(shù)據(jù)庫本身有關(guān)系,但是大部分?jǐn)?shù)據(jù)已經(jīng)能說明問題了??戳诉@些數(shù)據(jù)后,是不是有些心動了?

        源程序放了一段時間直接拷貝貼過來了,可能需要調(diào)試一下才能跑通,不過不是本質(zhì)性問題,對了如果要測試別忘記安裝Oracle訪問組件。



    一天,一個月,一年??傆幸惶鞎兊貌灰粯?。

    posted on 2011-08-26 14:48 wokaoJune 閱讀(884) 評論(0)  編輯  收藏 所屬分類: Oracle

    <2011年8月>
    31123456
    78910111213
    14151617181920
    21222324252627
    28293031123
    45678910

    導(dǎo)航

    統(tǒng)計

    公告

    GO ,GO,GO
    自己選擇的路,摸爬滾打也要走下去

    常用鏈接

    留言簿

    隨筆分類(26)

    隨筆檔案(29)

    文章分類

    最新隨筆

    搜索

    最新評論

    閱讀排行榜

    評論排行榜

    主站蜘蛛池模板: 亚洲性一级理论片在线观看| 亚洲第一页中文字幕| 国产精品久久久亚洲| 亚洲高清在线视频| 久久久久亚洲AV无码观看| 亚洲精品人成网在线播放影院| 亚洲hairy多毛pics大全| 羞羞视频免费网站日本| 国产成人免费ā片在线观看老同学 | 亚洲人成综合网站7777香蕉| 色欲aⅴ亚洲情无码AV| 亚洲精品偷拍视频免费观看| 四虎影视在线影院在线观看免费视频| 国产无人区码卡二卡三卡免费| 国产大片91精品免费看3| 亚洲韩国精品无码一区二区三区 | 天天综合亚洲色在线精品| 成年免费a级毛片免费看无码| 67pao强力打造高清免费| 国产免费午夜a无码v视频| 亚洲欧洲自拍拍偷午夜色无码| 亚洲国产精品成人精品小说| 国产AV无码专区亚洲AV琪琪| 特级无码毛片免费视频尤物| 日本一区免费电影| 亚洲av无码片在线播放| 亚洲色偷偷色噜噜狠狠99| CAOPORN国产精品免费视频| 99久久99这里只有免费费精品| 亚洲А∨精品天堂在线| 亚洲精品美女在线观看播放| 国产成人亚洲毛片| 中文字幕在线免费观看| 亚洲av无码成人精品区在线播放| 亚洲色偷偷偷网站色偷一区| 特级毛片全部免费播放| 青娱乐免费视频在线观看| 亚洲中文字幕无码日韩| 亚洲欧美日韩中文字幕一区二区三区| a级午夜毛片免费一区二区| 日韩一级免费视频|