25

Мы разрабатываем приложение для Android, которое имеет множество данных («клиенты», «продукты», «заказы» ...), и мы надеваем Не хотите запрашивать SQLite каждый раз, когда нам нужна запись. Мы хотим избежать запросов к базе данных как можно больше, поэтому мы решили хранить определенные данные всегда в памяти.Лучшая практика хранения данных в памяти и базе данных в то же время на Android

Наша первоначальная идея заключается в том, чтобы создать два простых классов:

  1. "MemoryRecord": класс, который будет содержать в основном массив объектов (строка, INT, двойной, DateTime и т.д ...), это данные из записи таблицы и все методы для получения этих данных из этого массива.

  2. «MemoryTable»: класс, который будет содержать в основном карту [Key, MemoryRecord] и все методы для управления этой Картой и вставки/обновления/удаления записи в/из базы данных.

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

Итак, при запуске приложения мы будем загружать эти таблицы из базы данных SQLite в память с помощью этих классов, и каждый раз, когда нам нужно менять некоторые данные, мы будем менять их в памяти и после этого вносить в базу данных сразу после.

Но мы хотим получить помощь/совет от вас. Можете ли вы предложить что-то более простое или эффективное для реализации такого? Или, может быть, некоторые существующие классы, которые уже делают это для нас?

Я понимаю, что вы, ребята, пытаетесь показать мне, и я благодарю вас за это.

Но, скажем, у нас есть таблица с 2000 записями, и мне нужно будет перечислить эти записи. Для каждого из них я должен запросить другие 30 таблиц (некоторые из них с 1000 записями, другие с 10 записями), чтобы добавить дополнительную информацию в список, и это пока «летает» (и, как вы знаете, мы должны быть очень быстрыми в данный момент).

Теперь вы скажете: «Просто создайте свой основной запрос со всеми этими« объединениями »и принесите все, что вам нужно за один шаг. SQLite может быть очень быстрым, если ваша база данных хорошо разработана и т. Д. .. ".

OK, но этот запрос станет очень сложным и уверенным, хотя SQLite очень быстр, он будет слишком «медленным» (2 раза в 4 секунды, как я уже подтвердил, и это не приемлемое для нас время).

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

Итак, альтернатива - это только основные записи (это никогда не изменится, независимо от того, что пользователь делает или хочет) без соединения (это очень быстро!) И запрашивать другие таблицы каждый раз, когда нам нужны некоторые данные. Обратите внимание, что в таблице, содержащей только 10 записей, мы будем извлекать одни и те же записи много и много раз. В этом случае это пустая трата времени, потому что, несмотря на быстрый SQLite, всегда будет дороже запрос, курсор, выборка и т. Д., А не просто захват записи из своего «кэша памяти». Я хочу пояснить, что мы не планируем постоянно хранить все данные в памяти, а просто некоторые таблицы, которые мы запрашиваем очень часто.

И мы пришли к первому вопросу: что является лучшим способом «кэшировать» эти записи? Мне очень нравится сосредоточиться на этом обсуждении, а не «зачем вам кэшировать данные?«

+2

«Мы хотим избежать запроса базы данных как можно больше, поэтому мы решили сохранить определенные данные в памяти». - Вы использовали Traceview, чтобы подтвердить, что это проблема для вашего приложения? «мы хотим получить от вас какую-то помощь/советы» - мой совет: докажите, что в первую очередь проблема. У вас очень мало оперативной памяти для работы. Построение некоторых больших рамок для решения несуществующей проблемы было бы пустой тратой усилий. Если вы продемонстрировали, что это проблема, мне бы понравился указатель на сообщение в блоге, где вы его написали, так как меня всегда интересуют результаты теста производительности. – CommonsWare

+0

@CommonsWare: Я понимаю вашу точку зрения и полностью согласен с вами. Но, как разработчики PalmOS и .NetCF, мы уже сталкиваемся с этой проблемой раньше. В PalmOS все данные хранятся в памяти по дизайну (.pdb), и при получении данных нет проблем с производительностью. В другой раздаче, в WM мы сталкиваемся с «проблемой», а затем мы создали это «решение», перечисленное выше. Но теперь, в Android, мы хотим сделать «правильный путь». Мы хотим знать, будем ли мы сталкиваться с проблемами производительности при запросе базы данных «каждый раз». Поэтому мы решили попросить здесь предложения. Спасибо, в любом случае. – Christian

+2

«Мы хотим знать, будем ли мы сталкиваться с проблемами производительности при каждом запросе базы данных». Поэтому мы решили попросить предложения здесь ». -- Нет, ты не сделал. Я бы хотел, чтобы ты это сделал. Вместо этого вы заявили о существовании проблемы («мы не хотим запрашивать sqlite каждый раз, когда нам нужна запись»), и вам нужна помощь в решении. Как и в случае с большинством платформ, ответ на вопрос, «если вы столкнетесь с проблемами производительности при запросе базы данных», «это зависит от запросов». Поверьте мне, только потому, что проблема с WM не означает, что одна и та же проблема существует в другом месте. Используйте Traceview. – CommonsWare

ответ

61

Подавляющее большинство приложений на платформе (контакты, электронная почта, Gmail, календарь и т. Д.) Этого не делают. Некоторые из них имеют чрезвычайно сложные схемы базы данных с потенциально большим объемом данных и не требуют этого. То, что вы предлагаете сделать, это вызвать огромный боль для вас, без ясного усиления.

Прежде всего, вы должны сосредоточиться на разработке своей базы данных и схемы, чтобы иметь возможность делать эффективные запросы. Есть две основные причины, по которым я могу думать о медленном доступе к базе данных:

  • У вас действительно сложные схемы данных.
  • У вас очень большой объем данных.

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

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

Вы также можете попытаться найти источник некоторых баз данных платформы, чтобы получить представление о том, как проектировать для хорошей производительности. Например, база данных контактов (особенно начиная с версии 2.0) чрезвычайно сложна и имеет множество оптимизаций для обеспечения хорошей производительности на относительно больших данных и расширяемых наборах данных с большим количеством различных запросов.

Update:

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

Инженер сделал оптимизацию, которая сократила время обновления реальной тестовой базы данных с 8 минут до 8 секунд. Улучшение производительности 60х.

Какова была эта оптимизация?

Это было создание временного индекса в точке обновления в важном столбце, используемом в операциях обновления.(И затем удалите его, когда закончите.) Таким образом, это 60-кратное повышение производительности происходит даже при том, что оно также включает время, необходимое для создания индекса на одном из столбцов, используемых во время обновления.

SQLite - одна из тех вещей, где, если вы знаете, что делаете, это может быть замечательно эффективным. И если вы не позаботитесь о том, как вы его используете, вы можете получить жалкую производительность. Это безопасная ставка, хотя, если у вас возникают проблемы с производительностью, вы можете исправить их, улучшив, как вы используете SQLite.

5

Проблема с кешем памяти, конечно, заключается в том, что вам нужно синхронизировать ее с базой данных. Я обнаружил, что запрос базы данных на самом деле довольно быстрый, и вы можете быть предварительно оптимизированы здесь. вы сделали много тестов по запросам с разными наборами данных, и они никогда не занимают более 10-20 мс.

Все зависит от того, как вы используете данные, конечно. ListViews хорошо оптимизированы для обработки больших количество строк (я тестировал в диапазоне 5000 без каких-либо реальных проблем).

Если вы собираетесь хранить кеш памяти, вы можете захотеть, чтобы база данных уведомила кеш при его изменении содержимого, а затем вы можете обновить кеш. любой может обновить базу данных, не зная о кешировании. Кроме того, если вы создаете ContentProvider над своей базой данных, вы можете использовать ContentResolver для уведомления об изменениях, если вы зарегистрируетесь с помощью registerContentObserver.

+0

Мне хорошо знать эти статистические данные. Я совершенно уверен, что мы предварительно оптимизируем, но это потому, что наш опыт в прошлом с использованием мобильных устройств SQLite e (WM). Синхронизация между памятью и базой данных - это не то, о чем мы беспокоимся, потому что одно и то же «время» мы меняем что-то, что мы опубликуем в базе данных. Кэш будет глобальным, поэтому все приложение увидит то же самое. И все изменения будут сделаны сначала в памяти и так в базе данных (в «атомной» операции, реализованной в этих классах). – Christian

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

  • Нет связанных вопросов^_^