【问题标题】:How to exec tons of Insert queries read from file in Sqlite Android如何在 Sqlite Android 中执行从文件中读取的大量插入查询
【发布时间】:2016-08-02 17:47:25
【问题描述】:

目前我有一个要求,我需要读取大量的插入查询,大约 100 000 个写在 .sql 文件中的查询。我需要从 SdCard 读取此文件并更新我的应用程序中的本地 sqlite 数据库。

我正在使用以下代码并成功更新:

同时我担心性能问题和应用程序挂起的风险,当它就像一个更重的 sql 文件的任务时。我需要改变我现在使用的方法吗? Sqlite 数据库是否有更好的实现来无风险地执行此任务。

/* Iterate through lines (assuming each insert has its own line 
   and theres no other stuff) */
while (insertReader.ready()) {
    String insertStmt = insertReader.readLine();
    db.execSQL(insertStmt);

    bytesRead += insertStmt.length();
    int percent = (int) (bytesRead * 100 / totalBytes);

    // To show the updating data progress
    if (previousPercent < percent) {
        System.out.println(percent);
        previousPercent = percent;
        Bundle b = new Bundle();
        b.putInt(AppConstants.KEY_PROGRESS_PERCENT, percent);
        Message msg = new Message();
        msg.setData(b);
        errorViewhandler.sendMessage(msg);
    }
    result++;
}
insertReader.close();

【问题讨论】:

    标签: java android database sqlite insert


    【解决方案1】:

    我发现将大量数据导入数据库的最快方法是在ContentProvider 上使用applyBatch()

    这是我从我的一个项目中简化的示例:

    ArrayList<ContentProviderOperation> cpoList = new ArrayList<ContentProviderOperation>();
    
    while (condition) {
        ContentProviderOperation.Builder b = ContentProviderOperation.newInsert(YourOwnContentProvider.CONTENT_URI);
        b.withYieldAllowed(true);
    
        b.withValue(COLUMN_ONE, 1);
        b.withValue(COLUMN_TWO, 2);
    
        cpoList.add(b.build());
    
        // You could check here, whether you have a lot of items in your list already. If you do, you should send them to applyBatch already.
    }
    
    if(cpoList.size() > 0) {
        context.get().getContentResolver().applyBatch(YourOwnContentProvider.AUTHORITY, cpoList);
    }
    

    作为 applyBatch 的示例实现:

    @Override
    public ContentProviderResult[] applyBatch(ArrayList<ContentProviderOperation> operations) {
        ContentProviderResult[] result = new ContentProviderResult[operations.size()];
        int i = 0;
        SQLiteDatabase sqlDB = db.getWritableDatabase();
    
        sqlDB.beginTransaction();
    
        try {
            for (ContentProviderOperation operation : operations) {
                result[i++] = operation.apply(this, result, i);
            }
    
            sqlDB.setTransactionSuccessful();
        } catch (OperationApplicationException e) {
            // Deal with exception
        } finally {
            sqlDB.endTransaction();
        }
    
        return result;
    }
    

    【讨论】:

    • 看起来很有希望,但我不清楚 EPGContentprovider 及其实现。我能否点击插入查询,我必须从位于 SdCard 中的文件中读取。
    • 那个 ContentProvider 实际上是我粘贴的代码中的 ContentProvider。在这种情况下,您需要创建自己的内容提供程序。
    • 是的,您可以从任何来源添加插入新行。所以 File 也可以。您只需要在while循环中逐个解析文件。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2018-08-07
    • 1970-01-01
    • 1970-01-01
    • 2011-08-28
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多