Лучшая практика для одновременного хранения данных в памяти и базе данных на Android - PullRequest
27 голосов
/ 09 сентября 2010

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

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

  1. «MemoryRecord»: класс, который будет содержать в основном массив объектов (string, int, double, datetime и т. Д.), Которые представляют собой данные из записи таблицы, и все методы для их получения. данные в / из этого массива.

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

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

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

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

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

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

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

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

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

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

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

Ответы [ 2 ]

66 голосов
/ 10 сентября 2010

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

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

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

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

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

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

Обновление:

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

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

Что это была за оптимизация?

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

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

5 голосов
/ 09 сентября 2010

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

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

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

...