2013-05-27 3 views
0

Я тестирую возможности устройства - показать заказчику размер данных, которые могут быть сохранены внутри устройства, как быстро его можно найти, как быстро поиск работает и т. Д.Android SQLite: как создать большую таблицу для целей тестирования?

Я использую моему провайдеру контента для доступа к таблице базы данных product с несколькими столбцами. Я уже переместил код в контент-провайдер, чтобы избежать дополнительной связи при вставке тестовых записей. Следующий код вызывается через меню из деятельности, чтобы заполнить таблицу с содержанием испытательной

Uri uri = Uri.parse(DemoContentProvider.PRODUCTS_CONTENT_URI + "/insertdemo"); 
getContentResolver().insert(uri, null); 

URI, распознаваемый в .insert методом контент-провайдера и следующего частного метода (одного и того же контента провайдера) является призван заполнить таблицу (обратите внимание на 100 тысяч предметов):

private void insertDemoProducts() { 
    for (int i = 1; i <= 100000; ++i) { 
     String id = Integer.toString(i); 
     insertProduct(id, "Test product " + id, "100", "75.50", "70.27"); 
    } 
} 

внутренний insertProduct() выглядит следующим образом:

private void insertProduct(String code, String name, String stock, 
          String price, String listprice) { 
    SQLiteDatabase sqlDB = database.getWritableDatabase(); 
    ContentValues values = new ContentValues(); 

    values.put(ProductTable.COLUMN_CODE, code); 
    values.put(ProductTable.COLUMN_NAME, name); 
    values.put(ProductTable.COLUMN_STOCK, stock); 
    values.put(ProductTable.COLUMN_PRICE, price); 
    values.put(ProductTable.COLUMN_LISTPRICE, listprice); 

    sqlDB.insert(ProductTable.TABLE_PRODUCT, null, values); 
} 

Это работает, но он принимает «навсегда». Как я могу сделать это быстрее? Какой самый быстрый метод вы знаете, чтобы заполнить таблицу?

Просто некоторые номера для рассмотрения: 1000 предметов занимают около 20 секунд.

ответ

1

Вам необходимо использовать транзакции при записи в базу данных sqlite, иначе она будет сохраняться в данных для каждой вставки. Сохраните ее на sd, который займет «навсегда».

, например, сделать insertProduct взять список продуктов и сохранить их в одной транзакции:

private void insertProducts(List<Product> products) { 
    try { 
     db.beginTransaction(); 
     for(Product product : products) { 
      insertProduct(...); 
     } 
     db.setTransactionSuccessful(); 
    } finally { 
     db.endTransaction(); 
    } 
} 

Это, как вы можете реализовать его в существующем коде:

private void insertDemoProducts() { 
    SQLiteDatabase sqlDB = database.getWritableDatabase(); 
    try { 
     sqlDB.beginTransaction(); 
     for (int i = 1; i <= 100000; ++i) { 
      String id = Integer.toString(i); 
      insertProduct(id, "Test product " + id, "100", "75.50", "70.27"); 
     } 
     sqlDB.setTransactionSuccessful(); 
    } finally { 
     sqlDB.endTransaction(); 
    } 
} 
+0

Я не могу проверить это сейчас, но как дополнительная функциональность (транзакция) может ускорить работу? Можете ли вы указать мне какую-либо документацию, объясняющую причину? – pepr

+0

Метод beginTransaction сообщает базе данных, что вы собираетесь начать транзакцию, и что ей не нужно ничего записывать в sd до тех пор, пока не будет запущен метод endTransaction. Затем он оценивает, было ли изменение базы данных успешным, и в этом случае он записывает все изменения сразу или, если это не удается, т. Е. SetTransactionSuccessful не был запущен, он делает откат. Вы можете прочитать больше в [SQLiteDatabase] (http://developer.android.com/reference/android/database/sqlite/SQLiteDatabase.html) в документации – Dean

+0

Надеюсь, я понимаю механизм транзакций. Однако при использовании транзакций вставка в db должна быть выполнена в любом случае. Кроме того, необходимо создать дополнительные структуры данных для реализации механизма транзакции. Тогда почему простая «вставка» без транзакции сложнее, чем «вставить» плюс транзакцию? – pepr

0

Во всяком случае, я я не полностью удовлетворен принятым вопросом, потому что я не понимаю причину, по которой добавление транзакции делает ее быстрее.

Глядя на Android источниках, я обнаружил, что sqlDB.insert(...) вызовов insertWithOnConflict(...) и что один построить строку для команды SQL, используя StringBuilder класс (с questionmarks в качестве заполнителей для вставляемых значений). Только после этого строка передается в конструктор SQLiteStatement вместе с массивом вставленных значений. Это означает, что строка с командой SQL создается снова и снова.

Кроме того, строковое представление шаблона команды SQL может быть предварительно скомпилировано, что позволяет избежать повторной компиляции команды. Затем для вставки желаемых записей в таблицу можно использовать методы .bindXxx и .execute. Когда вместе взятые, я использовал код followig (Iside внешней транзакции, как Dean suggested):

 StringBuilder sql = new StringBuilder(); 
     sql.append("INSERT INTO "); 
     sql.append(ProductTable.TABLENAME); 
     sql.append("("); 
     sql.append(ProductTable.COLUMN_CODE); 
     sql.append(","); 
     sql.append(ProductTable.COLUMN_NAME); 
     sql.append(","); 
     sql.append(ProductTable.COLUMN_STOCK); 
     sql.append(","); 
     sql.append(ProductTable.COLUMN_PRICE); 
     sql.append(","); 
     sql.append(ProductTable.COLUMN_LISTPRICE); 
     sql.append(") VALUES (?, ?, 100, 75.50, 70.27)"); 

     SQLiteStatement insert = sqldb.compileStatement(sql.toString()); 

     for (int i = 1; i <= 300000; ++i) { 
      insert.bindLong(1, i); 
      insert.bindString(2, "Test product " + i); 
      insert.execute(); 
     } 

По сравнению с добавлением только сделки, результат примерно в 3 раза быстрее. 300 тысяч записей были вставлены примерно через 3 минуты и 15 секунд на Nexus 7.

Смежные вопросы