2010-10-25 5 views
10

У нас есть около 7-8 таблиц в нашем приложении для Android, каждый из которых имеет около 8 столбцов в среднем. Операции чтения и записи выполняются в базе данных, и я экспериментирую и пытаюсь найти способы повышения производительности уровня DataAccess. Итак, пока я попытался следующий:Оптимизация SQLite для Android

  1. Используйте позиционные аргументы в которых положение (Причина: так что SQLite использует тот же план выполнения)
  2. заключите вставки и обновление с транзакциями (Причина: каждая операция дб заключен в транзакцию по умолчанию. Выполнение этого приведет к удалению этих служебных данных)
  3. Индексирование: я не создал никакого явного индекса, кроме тех, которые созданы по умолчанию для столбцов первичного ключа и уникальных ключей. (Причина: индексирование улучшит время поиска)

У меня есть m упом нуто мои предположения в paranthesis; пожалуйста, поправьте меня, если я ошибаюсь.

Вопросы:

  1. Могу ли я добавить что-нибудь еще в этом списке? Я где-то читал, что избежать использования db-журнала может повысить производительность обновлений? Это миф или факт? Как это можно сделать, если их рекомендовать?

  2. Разрешены ли вложенные транзакции в SQLite3? Как они влияют на производительность? Дело в том, что у меня есть функция, которая запускает обновление в цикле, поэтому я вложил цикл в блок транзакций. Иногда эта функция вызывается из другого цикла внутри некоторой другой функции. Вызывающая функция также охватывает цикл внутри блока транзакций. Как такое вложение транзакций влияет на производительность?

  3. В тех случаях, когда в моих предложениях используется более одного столбца для построения предиката. Эти столбцы могут не обязательно иметь первичный ключ или уникальные столбцы. Должен ли я создавать индексы на этих столбцах? Это хорошая идея создать несколько индексов для такой таблицы?

ответ

12
  1. Pin вниз точно, какие запросы вам нужно оптимизировать. Возьмите копию типичной базы данных и используйте REPL для запросов времени. Используйте это, чтобы сравнить любые выгоды при оптимизации.

  2. Используйте ANALYZE, чтобы позволить планировщику запросов SQLite работать более эффективно.

  3. Для SELECT s и UPDATE s индексы могут быть полезными, но только если создаваемые вами индексы могут фактически использоваться запросами, которые вам нужно ускорить.Используйте EXPLAIN QUERY PLAN в своих запросах, чтобы узнать, какой индекс будет использоваться, или если запрос требует полного сканирования таблицы. Для больших таблиц полное сканирование таблицы плохое, и вам, вероятно, нужен индекс. Только один индекс будет использоваться для любого заданного запроса. Если у вас есть несколько предикатов, то индекс, который будет использоваться, - это тот, который, как ожидается, максимально уменьшит результирующий набор (на основе ANALYZE). У вас могут быть индексы, которые содержат несколько столбцов (для поддержки запросов с несколькими предикатами). Если у вас есть индексы с несколькими столбцами, они могут использоваться только в том случае, если предикаты соответствуют индексу слева направо без пробелов (но неиспользуемые столбцы в конце являются точными). Если вы используете предикат заказа (<, <=, > и т. Д.), То это должно быть в последнем использованном столбце индекса. Используя оба предиката WHERE и ORDER BY, оба требуют индекса, и SQLite может использовать только один, так что это может быть точка, в которой работает производительность. Чем больше у вас индексов, тем медленнее будет ваш INSERT с, поэтому вам придется разработать лучший компромисс для вашей ситуации.

  4. Если у вас есть более сложные запросы, которые не могут использовать любые индексы, которые вы можете создать, вы можете де-нормализовать свою схему, структурируя свои данные таким образом, чтобы запросы были проще и на которые можно ответить, используя индексов.

  5. Если вы делаете большое количество INSERT s, попробуйте сбросить индексы и воссоздать их в конце. Вам нужно будет сравнить это.

  6. SQLite does support nested transactions с использованием точек сохранения, но я не уверен, что вы получите что-то там, где есть производительность.

  7. gain lots of speed by compromising on data integrity. Если вы можете самостоятельно восстановить повреждение базы данных, это может сработать для вас. Возможно, это возможно только при интенсивных операциях, которые вы можете восстановить вручную.

Я не уверен, сколько из этого вы можете получить в приложении для Android. Для оптимизации SQLite в документации SQLite существует more detailed guide.

+0

Спасибо, что нашли время, чтобы ответить на этот вопрос. – Samuh

1

Я хотел бы добавить эти:

  1. Использование rawQuery() вместо того, чтобы строить, используя ContentValues ​​скрепит в некоторых случаях. конечно, немного утомительно писать сырые запросы.

  2. Если у вас много данных типа string/text, подумайте о создании виртуальных таблиц с использованием полнотекстового поиска (FTS3), который может запускать более быстрый запрос. вы можете искать в google для точного повышения скорости.

8

Вот немного кода, чтобы получить EXPLAIN QUERY PLAN результатов в Android-коде Android с Android-приложения. Я начинаю с SQLiteOpenHelper dbHelper и SQLiteQueryBuilder qb.

String sql = qb.buildQuery(projection,selection,selectionArgs,groupBy,having,sortOrder,limit); 
android.util.Log.d("EXPLAIN",sql + "; " + java.util.Arrays.toString(selectionArgs)); 
Cursor c = dbHelper.getReadableDatabase().rawQuery("EXPLAIN QUERY PLAN " + sql,selectionArgs); 
if(c.moveToFirst()) { 
    do { 
     StringBuilder sb = new StringBuilder(); 
     for(int i = 0; i < c.getColumnCount(); i++) { 
      sb.append(c.getColumnName(i)).append(":").append(c.getString(i)).append(", "); 
     } 
     android.util.Log.d("EXPLAIN",sb.toString()); 
    } while(c.moveToNext()); 
} 
c.close(); 

я бросил это в моем ContentProvider.query() и теперь я могу видеть, как именно все запросы становятся выполняются. (В моем случае похоже, что проблема слишком много запросов, а не плохое использование индексирования, но, возможно, это поможет кому-то еще ...)

0

Незначительный пункт, который нужно добавить к ответному решению Robo: в SQLite (который в основном связан с блокировкой) могут быть заменены альтернативами. Вы могут найти один из вариантов, например unix-excl или unix-none чтобы быть быстрее, но прислушайтесь к предупреждениям на SQLite VFS page!

Normalization (структуры таблиц) также стоит рассмотреть (если вы еще этого не сделали) просто потому, что он имеет тенденцию предоставлять наименьшее представление данных в базе данных; это компромисс, меньше ввода-вывода для большего количества процессоров, и тот, который обычно стоит в средних корпоративных базах данных (я больше всего знаком с ними), но, боюсь, я понятия не имею, компромисс хорошо работает на небольших платформах, таких как Android.