2012-11-16 53 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