2013-01-31 15 views
7

Bir web hizmetinden aldığım 40000 kayıtları iPad uygulamasındaki bir sqlite veritabanına eklemek istiyorum.40000 kayıtlarını bir iPad'deki bir sqlite veritabanına nasıl ekleyebilirim

Aşağıdaki kodu yazdım, ancak yaklaşık 20 dakika sürüyor, daha hızlı bir yol var mı?

- (NSArray *)insertPriceSQLWithPrice:(Price *) price 
{ 

SQLiteManager *dbInfo = [SQLiteManager sharedSQLiteManagerWithDataBaseName:@"codefuel_catalogo.sqlite"]; 


sqlite3 *database; 

NSString *querySQL=[self formatStringQueryInsertWithTable:@"prices_list" andObject:price]; 


if(sqlite3_open([dbInfo.dataBasePath UTF8String], &database) == SQLITE_OK) 
{ 
    sqlite3_stmt * compiledStatement; 


    const char *query_stmt = [querySQL UTF8String]; 

    int result = sqlite3_prepare_v2(database, query_stmt, -1, &compiledStatement, NULL); 

    if (result == SQLITE_OK) 
    { 
     int success = sqlite3_step(compiledStatement); 

     NSLog(@"el numero de success es -> %i",success); 
     if (success == SQLITE_ERROR) 
      NSLog(@"Error al insertar en la base de datps"); 

    } 
    else 
     NSLog(@"Error %@ ERROR!!!!",querySQL); 

    sqlite3_finalize(compiledStatement); 
} 

sqlite3_close(database); 
return nil; 
} 
+8

Veritabanının açılmasını ve kapatılmasını yöntem dışı bırakırım. Bu size adil bir zaman harcıyor. Her bir 40.000 kesici uçtan biriyle bağlayıcıyı yaratın ve tamamlayın, ardından tamamlayın. Ayrıca, NSLog'lar gerçek yürütmeyi yavaşlatıyor olabilir. Ne kadar süreceğini görmek için günlükleri kullanmadan çalışırım. – Jeremy1026

+0

Veritabanını 40000 kez yeniden açar mısınız? (Ayrıca, kayıt başına bir kez yeniden ifade edilmesini de engellemeniz gerekir ve tüm eklemeleri tek bir işlemde yapmak daha iyidir - ancak bu her satır için yeniden açılmasından daha az önemlidir). –

+2

Doğru sorguya sahip her insert için birden çok satır ekleyebilir ve işlemin tamamını bir pakete sarabilirsiniz - şu anda SQLite, her bir ekleme işleminden sonra sizi yavaşlatan diske sığdırmak zorundadır. Ayrıca, her zaman –

cevap

22

Eğer eklemeleri hızlandırmak için yapmanız gereken üç şey vardır:

  • döngünün dışında sqlite3_open çağrısını Taşı . Eğer yerleştirme döngü önce işlem başlar ve döngü bittikten hemen sonra sonlandırmanız gerekli - Şu anda, döngü böylece kodunuzu
  • BEGIN TRANSACTION ve COMMIT TRANSACTION görüşmesi ekleme pasajı dışında öyle varsayalım, gösterilmez.
  • YapformatStringQueryInsertWithTable gerçekten parametreli - Şu anda nedeniyle sqlite3_prepare_v2 kullanarak rağmen onların sonuna kadar hazırlanmış deyimleri kullanmıyorsanız görünür, kodunuzda sqlite3_bind_XYZ hiçbir aramaları var.

İşte a nice post that shows you how to do all of the above. Düz C, ama bir Objective C programının bir parçası olarak iyi çalışır. Sonra COMMIT TRANSACTION çağırarak, daha sonra yaklaşık 20 ekler yükleniyor BEGIN TRANSACTıON'ı çağıran

Benim için
char* errorMessage; 
sqlite3_exec(mDb, "BEGIN TRANSACTION", NULL, NULL, &errorMessage); 
char buffer[] = "INSERT INTO example VALUES (?1, ?2, ?3, ?4, ?5, ?6, ?7)"; 
sqlite3_stmt* stmt; 
sqlite3_prepare_v2(mDb, buffer, strlen(buffer), &stmt, NULL); 
for (unsigned i = 0; i < mVal; i++) { 
    std::string id = getID(); 
    sqlite3_bind_text(stmt, 1, id.c_str(), id.size(), SQLITE_STATIC); 
    sqlite3_bind_double(stmt, 2, getDouble()); 
    sqlite3_bind_double(stmt, 3, getDouble()); 
    sqlite3_bind_double(stmt, 4, getDouble()); 
    sqlite3_bind_int(stmt, 5, getInt()); 
    sqlite3_bind_int(stmt, 6, getInt()); 
    sqlite3_bind_int(stmt, 7, getInt()); 
    if (sqlite3_step(stmt) != SQLITE_DONE) { 
     printf("Commit Failed!\n"); 
    } 
    sqlite3_reset(stmt); 
} 
sqlite3_exec(mDb, "COMMIT TRANSACTION", NULL, NULL, &errorMessage); 
sqlite3_finalize(stmt); 
5

, 18x performans artışı verdi - büyük ipucu! Hazırlanan ifadeleri önbelleğe almak az yardımcı oldu.

İlgili konular