2012-11-16 55 views
4

我想從json中解析出的數據批量插入db。我使用下面的方法插入批處理。問題是,mDbWritable.beginTransaction();執行時間太長。通常像6秒!我不知道問題在哪裏。有些想法是什麼會導致這麼長的執行時間?非常感謝。Android sqlite begintransaction執行太長

@Override 
public ContentProviderResult[] applyBatch(ArrayList<ContentProviderOperation> operations) 
     throws OperationApplicationException { 
    long start = System.currentTimeMillis(); 
    mDbWritable.beginTransaction(); 
    long time = System.currentTimeMillis() - start; 
    Alog.i(TAG, "Time applyBatch beginTransaction: " + time); 

    final int numOperations = operations.size(); 
    final ContentProviderResult[] results = new ContentProviderResult[numOperations]; 
    try { 
     for (int i = 0; i < numOperations; i++) { 
      results[i] = operations.get(i).apply(this, results, i); 
     } 

     mDbWritable.setTransactionSuccessful(); 

    } finally { 
     mDbWritable.endTransaction(); 
    } 
    return results; 
} 

從日誌中的一些例子:

11-16 15:14:53.726: I/ApiProvider(21442): Time applyBatch beginTransaction: 6025 
11-16 15:15:00.713: I/ApiProvider(21442): Time applyBatch beginTransaction: 4940 
11-16 15:15:17.819: I/ApiProvider(21442): Time applyBatch beginTransaction: 8651 
11-16 15:15:45.346: I/ApiProvider(21442): Time applyBatch beginTransaction: 12672 
11-16 15:16:16.807: I/ApiProvider(21442): Time applyBatch beginTransaction: 12411 
11-16 15:16:45.685: I/ApiProvider(21442): Time applyBatch beginTransaction: 12247 
11-16 15:17:01.500: I/ApiProvider(21442): Time applyBatch beginTransaction: 12788 

編輯:我使用JSON解析時循環應用批處理。例如爲json中的每個項目分析並應用批處理。批量包含插入,更新,刪除操作。

下面是代碼,我如何進行迭代,並調用applyBatch

Cursor starredChannelsCursor = 
     mContentResolver.query(ApiContract.Channels.CONTENT_URI, 
           new String[] {BaseColumns._ID, ChannelsTable.ID, ChannelsTable.SLUG }, 
           ChannelsTable.IS_STARRED + "=?",new String[] { "1" }, null); 

String userName = mSettings.getUserName(); 

if (starredChannelsCursor != null && starredChannelsCursor.moveToFirst()) {  
    while (!starredChannelsCursor.isAfterLast()) { 
     String channelSlug = starredChannelsCursor.getString(2); 
     ChannelHandler channelHandler = new ChannelHandler(this); 
     URI channelApiUri = Constants.getChannelApiURI(channelSlug,userName); 
     //execute update make applybatch call 
     executeUpdate(channelApiUri, channelHandler); 

     starredChannelsCursor.moveToNext(); 
    } 
} 

if (starredChannelsCursor != null) { 
    starredChannelsCursor.close(); 
} 


/** 
* Make call to Uri, parse response and apply batch operations to 
* contentResolver 
* 
* @param apiUri 
* @param handler 
*   - handles parsing 
*/ 
private boolean executeUpdate(URI apiUri, AbstractJSONHandler handler) { 
    ApiResponse apiResponse = mHttpHelper.doHttpCall(apiUri); 

    ArrayList<ContentProviderOperation> batch = 
        new ArrayList<ContentProviderOperation>(); 

    if (apiResponse != null) { 
     batch = handler.parse(apiResponse); 
     Alog.v(TAG, "update user data from " + apiUri); 
    } 

    if (batch.size() > 0) { 
     try { 
      mContentResolver.applyBatch(ApiContract.CONTENT_AUTHORITY, batch); 
     } catch (Exception e) { 
      Alog.v(TAG, "Error: " + e.getMessage()); 
     } 
    } 
    return true; 
} 
+0

'numOperations'的值是多少? – waqaslam

+0

通常喜歡70,但問題只在mDbWritable.beginTransaction();正如你所看到的,我測量這個方法執行的時間。其他部分快速 – vandzi

+0

我認爲你應該採取** applyBatch **方法以外的交易 – waqaslam

回答

2

這似乎是唯一可能的問題是,不同的線程獲得同樣的鎖,而調用beginTransaction()浪費時間只是等待其他線程釋放鎖。看看你的代碼,看看你如何管理線程,以及從哪個線程調用applyBatch(..)方法。

對您來說,查看beginTransaction()SQLiteDatabase類的調用層次結構可能也很有用。

+0

我不知道什麼可以阻止beginTransaction 12秒左右。這可能是因爲我在循環中調用了應用批處理,但它不應該是因爲我在之前的事務結束後調用beginTransaction。 – vandzi

+0

根據'SQLiteDatabase'類的來源,如果從不同的線程訪問,它甚至可能被阻塞30秒。你能提供你調用'applyBatch(..)'方法的代碼嗎? –

+0

我添加了代碼,我將applyBatch添加到我原來的問題 – vandzi