8. 探究SQL插入(insert)大量數(shù)據(jù)時(shí)的效率問題

  1. 首先, 解釋一下出入數(shù)據(jù)時(shí)的執(zhí)行過程

    • 當(dāng)SQL調(diào)用執(zhí)行一個(gè)語句的時(shí)候, 都會(huì)開啟一個(gè)稱謂事務(wù): transaction的東西, 并且在執(zhí)行完畢之后, 提交事務(wù)
      • 開啟事務(wù): begin transaction
      • 提交事務(wù): commit transaction
  2. 首先來測試: 使用普通的sql語句來插入10000條數(shù)據(jù)

    • 耗時(shí): 37.504418秒(一般來說不應(yīng)該這么慢的, 不知道這次測試為什么會(huì)這樣)

    • 如果在你的APP中, 提交一些10000條數(shù)據(jù), 需要讓用戶等待37秒的話, 那么用戶肯定是很不樂意的

        // 1. 編寫sql語句 insert into t_stu(name, age, score) values ('\(name)', \(age), \(score))
        NSString *sql = [NSString stringWithFormat:@"insert into T_human(name, age, height) values('%@', %li, %f)", self.name, self.age, self.height];
        
        // 2. 執(zhí)行SQL
        [[SQLiteTool shareInstance] excuteSQL:sql];
      
  3. 使用參數(shù)綁定, 來插入數(shù)據(jù)

    • 耗時(shí): 耗時(shí)13.305384秒, 相比上面的方法有很大的提升

    • 準(zhǔn)備語句會(huì)在一定程度上優(yōu)化數(shù)據(jù)的插入, 他不會(huì)因?yàn)榉磸?fù)的編譯準(zhǔn)備語句而導(dǎo)致性能的降低

        // 插入數(shù)據(jù)
        - (void)insertHumanBind {
            
            // 1. 留給準(zhǔn)備語句用的語句
            NSString *sql = @"insert into T_human(name, age, height) values(?, ?, ?)";
            
            // 2. 創(chuàng)建準(zhǔn)備語句
            sqlite3 *db = [SQLiteTool shareInstance].db;
            sqlite3_stmt *stmt = nil; // 準(zhǔn)備語句的引用指針
            if (sqlite3_prepare_v2(db, sql.UTF8String, -1, &stmt, nil) != SQLITE_OK) {
                NSLog(@"編譯失敗");
                return;
            }
        
            // 3. 綁定參數(shù)
                sqlite3_bind_text(stmt, 1, @"lilchunjiang".UTF8String, -1, SQLITE_TRANSIENT);
                sqlite3_bind_int(stmt, 2, 16);
                sqlite3_bind_double(stmt, 3, 99);
                
                // 4. 執(zhí)行, 這里要判斷執(zhí)行是否完成
                if (sqlite3_step(stmt) != SQLITE_DONE) {
                    NSLog(@"執(zhí)行失敗");
                    return;
                }
                
                // 5. 重置, 將綁定的值清空
                sqlite3_reset(stmt);
            
            // 6. 銷毀
            sqlite3_finalize(stmt);
        }
      
  4. 盡管經(jīng)過上面的優(yōu)化, 我們?nèi)匀贿_(dá)不到預(yù)期的效果, 這主要是由于

    • 如果執(zhí)行10000次SQL語句, 那么就會(huì)經(jīng)歷10000次開啟事務(wù) -> 執(zhí)行語句 -> 提交事務(wù), 這樣會(huì)嚴(yán)重影響存儲(chǔ)的性能

    • 因此我們的解決方案為: 手動(dòng)開啟事務(wù), 然后重復(fù)10000次的執(zhí)行, 最后手動(dòng)提交事務(wù)

    • 這時(shí)我們得到的耗時(shí)為: 0.040238秒, 這絕對(duì)是驚人的效率提升, 這主要是由于我們避免了重復(fù)的開啟/提交事務(wù)以及處理語句這些執(zhí)行的切換, 而是專注于語句的執(zhí)行

        // 開啟事務(wù)
        - (void)beginTransaction {
            NSString *sql = @"begin transaction";
            [self excuteSQL:sql];
        }
        
        // 提交事務(wù)
        - (void)commitTransaction {
            NSString *sql = @"commit transaction";
            [self excuteSQL:sql];
        }   
        
        // 插入1w條數(shù)據(jù)
        - (void)insertBind10000 {
            
            // 1. 語句
            NSString *sql = @"insert into T_human(name, age, height) values(?, ?, ?)";
            
            // 2. 創(chuàng)建準(zhǔn)備語句
            sqlite3 *db = [SQLiteTool shareInstance].db;
            sqlite3_stmt *stmt = nil;
            if (sqlite3_prepare_v2(db, sql.UTF8String, -1, &stmt, nil) != SQLITE_OK) {
                NSLog(@"編譯失敗");
                return;
            }
            
            // 3. 開啟事務(wù)
            [[SQLiteTool shareInstance] beginTransaction];
            
            for (int i = 0; i < 10000; i++) {
                // 4. 綁定參數(shù)
                sqlite3_bind_text(stmt, 1, @"lilchunjiang".UTF8String, -1, SQLITE_TRANSIENT);
                sqlite3_bind_int(stmt, 2, 16);
                sqlite3_bind_double(stmt, 3, 99);
                
                // 5. 執(zhí)行
                if (sqlite3_step(stmt) != SQLITE_DONE) {
                    NSLog(@"執(zhí)行失敗");
                    return;
                }
                
                // 6. 重置, 將綁定的值清空
                sqlite3_reset(stmt);
            }
            
            // 7. 提交事務(wù)
            [[SQLiteTool shareInstance] commitTransaction];
            
            // 8. 銷毀準(zhǔn)備語句
            sqlite3_finalize(stmt);
        }
      
  5. 小結(jié)

    • 如果我們只需要插入幾條語句的話, 那么就直接使用單條語句即可, 因?yàn)檫@樣很簡單
    • 但是如果需要數(shù)據(jù)的大批量插入, 就一定要使用最后一種方法, 這樣會(huì)讓數(shù)據(jù)存儲(chǔ)有極大的性能提升
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末鲜锚,一起剝皮案震驚了整個(gè)濱河市重荠,隨后出現(xiàn)的幾起案子泳炉,更是在濱河造成了極大的恐慌妖啥,老刑警劉巖舍扰,帶你破解...
    沈念sama閱讀 211,265評(píng)論 6 490
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件与纽,死亡現(xiàn)場離奇詭異赦颇,居然都是意外死亡嗜桌,警方通過查閱死者的電腦和手機(jī)示惊,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,078評(píng)論 2 385
  • 文/潘曉璐 我一進(jìn)店門好港,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人米罚,你說我怎么就攤上這事钧汹。” “怎么了录择?”我有些...
    開封第一講書人閱讀 156,852評(píng)論 0 347
  • 文/不壞的土叔 我叫張陵拔莱,是天一觀的道長。 經(jīng)常有香客問我隘竭,道長塘秦,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 56,408評(píng)論 1 283
  • 正文 為了忘掉前任动看,我火速辦了婚禮尊剔,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘菱皆。我一直安慰自己须误,他們只是感情好挨稿,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,445評(píng)論 5 384
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著京痢,像睡著了一般奶甘。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上历造,一...
    開封第一講書人閱讀 49,772評(píng)論 1 290
  • 那天甩十,我揣著相機(jī)與錄音,去河邊找鬼吭产。 笑死侣监,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的臣淤。 我是一名探鬼主播橄霉,決...
    沈念sama閱讀 38,921評(píng)論 3 406
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼邑蒋!你這毒婦竟也來了姓蜂?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 37,688評(píng)論 0 266
  • 序言:老撾萬榮一對(duì)情侶失蹤医吊,失蹤者是張志新(化名)和其女友劉穎钱慢,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體卿堂,經(jīng)...
    沈念sama閱讀 44,130評(píng)論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡束莫,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,467評(píng)論 2 325
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了草描。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片览绿。...
    茶點(diǎn)故事閱讀 38,617評(píng)論 1 340
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖穗慕,靈堂內(nèi)的尸體忽然破棺而出饿敲,到底是詐尸還是另有隱情,我是刑警寧澤逛绵,帶...
    沈念sama閱讀 34,276評(píng)論 4 329
  • 正文 年R本政府宣布怀各,位于F島的核電站,受9級(jí)特大地震影響术浪,放射性物質(zhì)發(fā)生泄漏瓢对。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,882評(píng)論 3 312
  • 文/蒙蒙 一添吗、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧份名,春花似錦碟联、人聲如沸妓美。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,740評(píng)論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽壶栋。三九已至,卻和暖如春普监,著一層夾襖步出監(jiān)牢的瞬間贵试,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 31,967評(píng)論 1 265
  • 我被黑心中介騙來泰國打工凯正, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留毙玻,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 46,315評(píng)論 2 360
  • 正文 我出身青樓廊散,卻偏偏與公主長得像桑滩,于是被迫代替她去往敵國和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子允睹,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,486評(píng)論 2 348

推薦閱讀更多精彩內(nèi)容