真機iOS fmdb sqlite插入數據慢

fmdb sqlite插入數據慢


之前使用FMDB加載一個全國的行政區(qū)劃的數據庫表到客戶端闯狱,好讓用戶在選擇收獲地址時在本地加載煞赢,提高用戶的使用體驗,在模擬器上跑時非常方便哄孤,但在測試時非常慢照筑,真機加載時格外慢,加載8萬多條的數據差不多要半個小時,這簡直不能忍受凝危,后來查找了很多資料波俄,發(fā)現只要添加了事務就好了, 一行代碼提升了好幾十倍蛾默,原本半小時才可以的現在一分鐘內就好了懦铺,10萬條數據測試結果如下(結論,開啟事務普通出入數據最快):

模擬器上的結果:(時間差別不大)
2017-07-25 16:02:06.233 TestFMDB[66270:4375010] *** 創(chuàng)建數據花費時間 0.409968 s
2017-07-25 16:02:59.004 TestFMDB[66270:4375010] *** 普通方式插入數據花費時間 52.770025 s
2017-07-25 16:02:59.004 TestFMDB[66270:4375010] *** address fmdb 加載數據庫結束

2017-07-25 16:02:06.233 TestFMDB[66270:4375010] *** 創(chuàng)建數據花費時間 0.409968 s
2017-07-25 16:02:59.004 TestFMDB[66270:4375010] *** 普通方式插入數據花費時間 52.770025 s
2017-07-25 16:02:59.004 TestFMDB[66270:4375010] *** address fmdb 加載數據庫結束

2017-07-25 16:08:38.285 TestFMDB[66420:4379160] *** 創(chuàng)建數據花費時間 0.433273 s
2017-07-25 16:08:51.874 TestFMDB[66420:4379157] *** 多線程開啟事務方式插入數據花費時間 13.587659 s
2017-07-25 16:09:03.745 TestFMDB[66420:4379158] *** 多線程開啟事務方式插入數據花費時間 25.459356 s
2017-07-25 16:09:23.915 TestFMDB[66420:4379222] *** 多線程開啟事務方式插入數據花費時間 45.629394 s
2017-07-25 16:09:40.919 TestFMDB[66420:4379211] *** 多線程開啟事務方式插入數據花費時間 62.632683 s

真機測試結果(沒有重現我項目中不開啟事務特別慢的情況)
// 普通插入數據
2017-07-25 16:23:21.120660+0800 TestFMDB[2152:677046] *** 創(chuàng)建數據花費時間 1.374888 s
2017-07-25 16:24:14.512719+0800 TestFMDB[2152:677046] *** 普通方式插入數據花費時間 53.391885 s
2017-07-25 16:24:14.512885+0800 TestFMDB[2152:677046] *** address fmdb 加載數據庫結束

// 普通開啟事務的結果
2017-07-25 16:21:22.480394+0800 TestFMDB[2147:676024] *** 創(chuàng)建數據花費時間 1.359878 s
2017-07-25 16:22:00.316775+0800 TestFMDB[2147:676024] *** 開啟事務方式插入數據花費時間 37.836121 s
2017-07-25 16:22:00.316933+0800 TestFMDB[2147:676024] *** address fmdb 加載數據庫結束

// 開啟4個線程的結果
2017-07-25 16:14:07.000092+0800 TestFMDB[2135:671904] *** 創(chuàng)建數據花費時間 1.484458 s
2017-07-25 16:14:16.818597+0800 TestFMDB[2135:671902] *** 線程1開啟事務方式插入數據花費時間 9.818329 s
2017-07-25 16:14:26.386697+0800 TestFMDB[2135:671903] *** 線程2開啟事務方式插入數據花費時間 19.386441 s
2017-07-25 16:14:36.702309+0800 TestFMDB[2135:671900] *** 線程3開啟事務方式插入數據花費時間 29.702041 s
2017-07-25 16:14:47.890248+0800 TestFMDB[2135:671901] *** 線程4開啟事務方式插入數據花費時間 40.889873 s

開啟2個線程的結果
2017-07-25 16:15:52.293433+0800 TestFMDB[2137:672875] *** 創(chuàng)建數據花費時間 2.423719 s
2017-07-25 16:16:13.158949+0800 TestFMDB[2137:672877] *** 線程1開啟事務方式插入數據花費時間 20.865313 s
2017-07-25 16:16:32.692071+0800 TestFMDB[2137:672876] *** 線程2開啟事務方式插入數據花費時間 40.398287 s

開啟2個線程不開啟事務的結果
2017-07-25 16:17:20.354732+0800 TestFMDB[2140:673793] *** 創(chuàng)建數據花費時間 1.563348 s
2017-07-25 16:17:47.615129+0800 TestFMDB[2140:673794] *** 線程1開啟事務方式插入數據花費時間 27.260129 s
2017-07-25 16:18:16.670929+0800 TestFMDB[2140:673796] *** 線程2開啟事務方式插入數據花費時間 56.316027 s

具體代碼如下:

#pragma mark - ###### 將數據存入數控庫
- (void)testInsertDB
{
    __weak typeof(self) weakSelf = self;
    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
        // 創(chuàng)建測試數據
        NSTimeInterval createDataBegin = [[NSDate date] timeIntervalSince1970];
        NSMutableArray *arrayM = [NSMutableArray array];
        for (int i=0; i<10*10000; i++) {
            NSMutableDictionary *item = [NSMutableDictionary dictionary];
            item[@"addr_id"] = [NSString stringWithFormat:@"addr_id_%d",i];
            item[@"parent_addr_id"] = [NSString stringWithFormat:@"parent_addr_id_%d",i];
            item[@"addr_value"] = [NSString stringWithFormat:@"addr_value_%d",i];
            [arrayM addObject:item];
        }
        NSTimeInterval createDataEnd = [[NSDate date] timeIntervalSince1970];
        CGFloat createDataCost = (createDataEnd - createDataBegin);
        NSLog(@"*** 創(chuàng)建數據花費時間 %f s",createDataCost);
        // 調用
        // 普通插入
        [weakSelf normalSaveData2LocalDataBaseWithNSArray:arrayM];
        // 開啟事務插入
        //[weakSelf transationSaveData2LocalDataBaseWithNSArray:arrayM];
        // 開啟多個Queue和事務插入
        //[weakSelf mutalQueueSaveData2LocalDataBaseWithNSArray:arrayM];
    });
    
}
#pragma mark - ******** 普通一條一條插入
- (void)normalSaveData2LocalDataBaseWithNSArray:(NSArray *)addressList
{
        NSTimeInterval insertDataBegin = [[NSDate date] timeIntervalSince1970];
        // 獲得Documents目錄路徑
        NSString *documentsPath = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) lastObject];
        
        // 文件路徑
        NSString *filePath = [documentsPath stringByAppendingPathComponent:@"testAddress.sqlite"];
        
        // 實例化FMDataBase對象
        
        FMDatabase *db = [FMDatabase databaseWithPath:filePath];
        
        [db open];
        NSString *dropSql = @"DROP TABLE t_test_address;";
        [db executeUpdate:dropSql];
        // 初始化數據表
        NSString *createSql = @"CREATE TABLE IF NOT EXISTS 't_test_address' ('id' INTEGER PRIMARY KEY AUTOINCREMENT  NOT NULL ,'addr_id' VARCHAR(255),'parent_addr_id' VARCHAR(255),'addr_value' VARCHAR(255)) ";
        
        [db executeUpdate:createSql];
    
        for (NSDictionary *item in addressList) {
            // 初始化數據表
            NSString *insertSql = @"INSERT INTO t_address (addr_id, parent_addr_id,addr_value) VALUES (?,?,?)";
            BOOL insertRes = [db executeUpdate:insertSql withArgumentsInArray:@[item[@"addr_id"],item[@"parent_addr_id"],item[@"addr_value"]]];
            
            
        }
        NSTimeInterval insertDataEnd = [[NSDate date] timeIntervalSince1970];
        CGFloat insertDataCost = (insertDataEnd - insertDataBegin);
        NSLog(@"*** 普通方式插入數據花費時間 %f s",insertDataCost);
        NSLog(@"*** address fmdb 加載數據庫結束");

}
#pragma mark - ******** 開啟事務插入
- (void)transationSaveData2LocalDataBaseWithNSArray:(NSArray *)addressList
{
    NSTimeInterval insertDataBegin = [[NSDate date] timeIntervalSince1970];
    // 獲得Documents目錄路徑
    NSString *documentsPath = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) lastObject];
    
    // 文件路徑
    NSString *filePath = [documentsPath stringByAppendingPathComponent:@"testAddress.sqlite"];
    
    // 實例化FMDataBase對象
    
    FMDatabase *db = [FMDatabase databaseWithPath:filePath];
    
    [db open];
    NSString *dropSql = @"DROP TABLE t_test_address;";
    [db executeUpdate:dropSql];
    // 初始化數據表
    NSString *createSql = @"CREATE TABLE IF NOT EXISTS 't_test_address' ('id' INTEGER PRIMARY KEY AUTOINCREMENT  NOT NULL ,'addr_id' VARCHAR(255),'parent_addr_id' VARCHAR(255),'addr_value' VARCHAR(255)) ";
    
    [db executeUpdate:createSql];
    
    
    [db beginTransaction];
    for (NSDictionary *item in addressList) {
        // 初始化數據表
        NSString *insertSql = @"INSERT INTO t_address (addr_id, parent_addr_id,addr_value) VALUES (?,?,?)";
        BOOL insertRes = [db executeUpdate:insertSql withArgumentsInArray:@[item[@"addr_id"],item[@"parent_addr_id"],item[@"addr_value"]]];
        
        
    }
    [db commit];
    NSTimeInterval insertDataEnd = [[NSDate date] timeIntervalSince1970];
    CGFloat insertDataCost = (insertDataEnd - insertDataBegin);
    NSLog(@"*** 開啟事務方式插入數據花費時間 %f s",insertDataCost);
    NSLog(@"*** address fmdb 加載數據庫結束");

}
#pragma mark - ******** 多線程務事務插入
- (void)mutalQueueSaveData2LocalDataBaseWithNSArray:(NSArray *)addressList
{
    NSTimeInterval insertDataBegin = [[NSDate date] timeIntervalSince1970];
    // 獲得Documents目錄路徑
    NSString *documentsPath = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) lastObject];
    
    // 文件路徑
    NSString *filePath = [documentsPath stringByAppendingPathComponent:@"testAddress.sqlite"];
    
    // 實例化FMDataBase對象
    
    FMDatabase *db = [FMDatabase databaseWithPath:filePath];
    
    [db open];
    NSString *dropSql = @"DROP TABLE t_test_address;";
    [db executeUpdate:dropSql];
    // 初始化數據表
    NSString *createSql = @"CREATE TABLE IF NOT EXISTS 't_test_address' ('id' INTEGER PRIMARY KEY AUTOINCREMENT  NOT NULL ,'addr_id' VARCHAR(255),'parent_addr_id' VARCHAR(255),'addr_value' VARCHAR(255)) ";
    
    
    
    __block NSTimeInterval insertDataEnd = [[NSDate date] timeIntervalSince1970];
    
    
     //創(chuàng)建連個線程(模擬多線程操作)
     dispatch_queue_t q1 = dispatch_queue_create("queue1", NULL);
     dispatch_queue_t q2 = dispatch_queue_create("queue2", NULL);
     dispatch_queue_t q3 = dispatch_queue_create("queue3", NULL);
     dispatch_queue_t q4 = dispatch_queue_create("queue4", NULL);
    
     FMDatabaseQueue *queue = [FMDatabaseQueue databaseQueueWithPath:filePath];
     NSInteger range = addressList.count / 2;
     //線程一
     dispatch_async(q1, ^{
     
         [queue inDatabase:^(FMDatabase *db2) {
             [db2 beginTransaction];
             for (NSInteger i = range*0; i < range*1;i++) {
                 NSDictionary *item = addressList[i];
                 // 初始化數據表
                 NSString *insertSql = @"INSERT INTO t_address (addr_id, parent_addr_id,addr_value) VALUES (?,?,?)";
                 BOOL insert = [db2 executeUpdate:insertSql withArgumentsInArray:@[item[@"addr_id"],item[@"parent_addr_id"],item[@"addr_value"]]];
             }
             [db2 commit];
             NSTimeInterval insertDataEnd1 = [[NSDate date] timeIntervalSince1970];
             if (insertDataEnd1 > insertDataEnd) {
                 insertDataEnd = insertDataEnd1;
                 CGFloat insertDataCost = (insertDataEnd - insertDataBegin);
                 NSLog(@"*** 線程1開啟事務方式插入數據花費時間 %f s",insertDataCost);
                 
             }
        }];
        
     });
     
     //線程二
     dispatch_async(q2, ^{
         [queue inDatabase:^(FMDatabase *db2) {
             [db2 beginTransaction];
             for (NSInteger i = range*1; i < addressList.count; i++) {
                 NSDictionary *item = addressList[i];
                 // 初始化數據表
                 NSString *insertSql = @"INSERT INTO t_address (addr_id, parent_addr_id,addr_value) VALUES (?,?,?)";
                 BOOL insert = [db2 executeUpdate:insertSql withArgumentsInArray:@[item[@"addr_id"],item[@"parent_addr_id"],item[@"addr_value"]]];
             }
             [db2 commit];
             NSTimeInterval insertDataEnd2 = [[NSDate date] timeIntervalSince1970];
             if (insertDataEnd2 > insertDataEnd) {
                 insertDataEnd = insertDataEnd2;
                 CGFloat insertDataCost = (insertDataEnd - insertDataBegin);
                 NSLog(@"*** 線程2開啟事務方式插入數據花費時間 %f s",insertDataCost);
                 
             }
         }];
     });
    /*
     //線程三
     dispatch_async(q3, ^{
         [queue inDatabase:^(FMDatabase *db2) {
             [db2 beginTransaction];
             for (NSInteger i = range*2; i < range*3; i++) {
                 NSDictionary *item = addressList[i];
                 // 初始化數據表
                 NSString *insertSql = @"INSERT INTO t_address (addr_id, parent_addr_id,addr_value) VALUES (?,?,?)";
                 BOOL insert = [db2 executeUpdate:insertSql withArgumentsInArray:@[item[@"addr_id"],item[@"parent_addr_id"],item[@"addr_value"]]];
             }
             [db2 commit];
             NSTimeInterval insertDataEnd3 = [[NSDate date] timeIntervalSince1970];
             if (insertDataEnd3 > insertDataEnd) {
                 insertDataEnd = insertDataEnd3;
                 CGFloat insertDataCost = (insertDataEnd - insertDataBegin);
                 NSLog(@"*** 線程3開啟事務方式插入數據花費時間 %f s",insertDataCost);
                 
             }
         }];
     });
    
     //線程四
     dispatch_async(q4, ^{
         [queue inDatabase:^(FMDatabase *db2) {
             [db2 beginTransaction];
             for (NSInteger i = range*3; i < addressList.count; i++) {
                 NSDictionary *item = addressList[i];
                 // 初始化數據表
                 NSString *insertSql = @"INSERT INTO t_address (addr_id, parent_addr_id,addr_value) VALUES (?,?,?)";
                 BOOL insert = [db2 executeUpdate:insertSql withArgumentsInArray:@[item[@"addr_id"],item[@"parent_addr_id"],item[@"addr_value"]]];
             }
             [db2 commit];
             NSTimeInterval insertDataEnd4 = [[NSDate date] timeIntervalSince1970];
             if (insertDataEnd4 > insertDataEnd) {
                 insertDataEnd = insertDataEnd4;
                 CGFloat insertDataCost = (insertDataEnd - insertDataBegin);
                 NSLog(@"*** 線程4開啟事務方式插入數據花費時間 %f s",insertDataCost);
                 
             }
         }];
     });
    */

}
最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
  • 序言:七十年代末趴生,一起剝皮案震驚了整個濱河市阀趴,隨后出現的幾起案子,更是在濱河造成了極大的恐慌苍匆,老刑警劉巖刘急,帶你破解...
    沈念sama閱讀 222,627評論 6 517
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現場離奇詭異浸踩,居然都是意外死亡叔汁,警方通過查閱死者的電腦和手機,發(fā)現死者居然都...
    沈念sama閱讀 95,180評論 3 399
  • 文/潘曉璐 我一進店門检碗,熙熙樓的掌柜王于貴愁眉苦臉地迎上來据块,“玉大人,你說我怎么就攤上這事折剃×砑伲” “怎么了?”我有些...
    開封第一講書人閱讀 169,346評論 0 362
  • 文/不壞的土叔 我叫張陵怕犁,是天一觀的道長边篮。 經常有香客問我,道長奏甫,這世上最難降的妖魔是什么戈轿? 我笑而不...
    開封第一講書人閱讀 60,097評論 1 300
  • 正文 為了忘掉前任,我火速辦了婚禮阵子,結果婚禮上思杯,老公的妹妹穿的比我還像新娘。我一直安慰自己挠进,他們只是感情好色乾,可當我...
    茶點故事閱讀 69,100評論 6 398
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著领突,像睡著了一般暖璧。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上攘须,一...
    開封第一講書人閱讀 52,696評論 1 312
  • 那天漆撞,我揣著相機與錄音,去河邊找鬼于宙。 笑死浮驳,一個胖子當著我的面吹牛,可吹牛的內容都是我干的捞魁。 我是一名探鬼主播至会,決...
    沈念sama閱讀 41,165評論 3 422
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼谱俭!你這毒婦竟也來了奉件?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 40,108評論 0 277
  • 序言:老撾萬榮一對情侶失蹤昆著,失蹤者是張志新(化名)和其女友劉穎县貌,沒想到半個月后,有當地人在樹林里發(fā)現了一具尸體凑懂,經...
    沈念sama閱讀 46,646評論 1 319
  • 正文 獨居荒郊野嶺守林人離奇死亡煤痕,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 38,709評論 3 342
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現自己被綠了接谨。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片摆碉。...
    茶點故事閱讀 40,861評論 1 353
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖脓豪,靈堂內的尸體忽然破棺而出巷帝,到底是詐尸還是另有隱情,我是刑警寧澤扫夜,帶...
    沈念sama閱讀 36,527評論 5 351
  • 正文 年R本政府宣布楞泼,位于F島的核電站,受9級特大地震影響历谍,放射性物質發(fā)生泄漏现拒。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 42,196評論 3 336
  • 文/蒙蒙 一望侈、第九天 我趴在偏房一處隱蔽的房頂上張望印蔬。 院中可真熱鬧,春花似錦脱衙、人聲如沸侥猬。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,698評論 0 25
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽退唠。三九已至,卻和暖如春荤胁,著一層夾襖步出監(jiān)牢的瞬間瞧预,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,804評論 1 274
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留垢油,地道東北人盆驹。 一個月前我還...
    沈念sama閱讀 49,287評論 3 379
  • 正文 我出身青樓,卻偏偏與公主長得像滩愁,于是被迫代替她去往敵國和親躯喇。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 45,860評論 2 361

推薦閱讀更多精彩內容