Подтвердить что ты не робот

Лучшая практика хранения данных в памяти и базе данных в то же время на Android

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

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

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

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

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

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

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

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

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

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

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

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

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

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

4b9b3361

Ответ 1

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

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

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

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

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

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

Update:

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

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

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

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

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

Ответ 2

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

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

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