Налаштування Isar у Flutter: індекси, запити, реактивність

Коли база застосунку зростає, вибірки починають гальмувати, а інтерфейс — підвисати. Ми налаштовуємо локальне сховище у Flutter під ключ: проєктуємо схему, індекси та реактивні запити так, щоб швидкість не падала зі зростанням даних. Обговоримо вашу задачу і повернемося з оцінкою та планом.

Розробка та підтримка будь-яких видів мобільних додатків:

Інформаційні та розважальні мобільні програми
Новинки, ігри, довідники, онлайн-каталоги, погодні, фітнес та здоров'я, туристичні, освітні, соціальні мережі та месенджери, квіз, блоги та подкасти, форуми, агрегатори
Мобільні програми електронної комерції
Інтернет-магазини, B2B-додатки, маркетплейси, онлайн-обмінники, кешбек-сервіси, біржі, дропшиппінг-платформи, програми лояльності, доставка їжі та товарів, платіжні системи
Мобільні програми для управління бізнес-процесами
CRM-системи, ERP-системи, управління проектами, інструменти для команди продажів, облік фінансів, управління виробництвом, логістика та доставка, управління персоналом, системи моніторингу даних
Мобільні програми електронних послуг
Дошки оголошень, онлайн-школи, онлайн-кінотеатри, платформи надання електронних послуг, платформи кешбеку, відеохостинги, тематичні портали, платформи онлайн-бронювання та запису, платформи онлайн-торгівлі

Це лише деякі з типів мобільних додатків, з якими ми працюємо, і кожен із них може мати свої специфічні особливості та функціональність, а також бути адаптованим під конкретні потреби та цілі клієнта.

Послуги, які ми пропонуємо
Показано 1 з 1Усі 1734 послуг
Налаштування Isar у Flutter: індекси, запити, реактивність
Середній
від 1 дня до 3 днів
Часті запитання

Isar Flutter: чому запити до локальної бази гальмують на зростанні даних

Локальна база Flutter майже ніколи не гальмує на старті: на сотні записів будь-який запит відповідає миттєво, і це створює хибне відчуття, що схема спроєктована правильно.

Проблема проявляється пізніше, коли колекції виростають до десятків тисяч об'єктів — екран списку починає відкриватися із затримкою, пошук «підвисає» на введенні, а прокрутка смикається.

Причина не в самому сховищі, а в тому, що індекси та запити до Isar Flutter проєктувалися навмання, без опори на реальні сценарії читання.

Вузьке місце зазвичай одне з трьох. Перше — фільтрація за полем без індексу: замість вибірки за ключем двигун перебирає всю колекцію, і час відповіді зростає лінійно разом з даними.

Друге — сортування та пагінація «в лоб», коли потрібний порядок не підтриманий індексом і кожен запит заново перебудовує вибірку. Третє — реактивні підписки на занадто широкі запити: будь-яка зміна в колекції перебудовує весь список на екрані, хоча змінився один запис.

Ціна такої архітектури видна не відразу, але накопичується: користувач сприймає застосунок як «важкий», зростає кількість звернень у підтримку, а команда витрачає час на точкові «костулі» замість виправлення схеми.

Найгірше те, що деградація нелінійна — до певного обсягу все терпимо, а потім поведінка змінюється різко.

Розбираємо, як це закривається: як проєктувати індекси під реальні запити, обмежувати реактивні підписки та тримати час відгуку стабільним незалежно від того, скільки записів накопичилося в користувача.

Що дає вивірена схема зберігання та доступу до даних

Швидкість вибірки в Isar визначається не обсягом бази, а тим, чи потрапляє запит в індекс.

Поки фільтр іде по полю без індексу, двигун перебирає всі записи колекції — на десятках тисяч об'єктів це помітно неозброєним оком: список відкривається із затримкою, пошук «підгальмовує» під час введення.

Індекс перетворює такий перебір на точкове читання, і вибірка за ключем або діапазоном дат перестає залежати від того, скільки всього записів накопичилося.

Споживання пам'яті зростає через те, як застосунок читає дані. Запит, що повертає об'єкти цілком, тягне в пам'ять усі поля, включно з важкими — вкладені списки, довгі тексти, посилання на пов'язані колекції.

Якщо екрану потрібні лише ім'я та дата, розумніше повернути проєкцію з потрібних полів, а пов'язані сутності підвантажувати окремим запитом за ідентифікатором. Так пік пам'яті на екрані залишається рівним, а не стрибає щоразу при відкритті розділу.

Реактивність — третя частина картини. Підписка на запит віддає оновлення при зміні даних, але якщо підписатися на всю колекцію, перемальовування спрацьовує на будь-яку зміну й тягне за собою зайву роботу. Підписка на вузький запит з індексом оновлює лише ті екрани, яких зміна реально стосується.

Як це виглядає в цифрах

  • Вибірка за індексованим полем перестає сповільнюватися в міру зростання бази: час відповіді тримається на одному рівні при десятикратному збільшенні обсягу.
  • Проєкції замість повних об'єктів знижують пікове споживання пам'яті на списках у рази.
  • Точкові підписки прибирають перемальовування, не пов'язані зі зміною даних.

Стійкість до зростання — наслідок цих трьох рішень. Схема з продуманими індексами, проєкціями та вузькими підписками не потребує переписувати шар доступу до даних, коли колекції виростають на порядок.

Підходи до організації локального сховища: порівняння варіантів

Локальне сховище у Flutter — це не «одна бібліотека на все».

Вибір залежить від трьох речей: структури даних (плоскі пари ключ-значення чи пов'язані сутності), характеру доступу (точкове читання за ідентифікатором чи вибірки з фільтрами й сортуванням) і вимог до реактивності — чи має інтерфейс сам перемальовуватися при зміні запису. Нижче — реальні альтернативи, між якими обирають на старті проєкту.

Варіант Коли підходить Обмеження
Сховище ключ-значення Налаштування, прапорці, токени, невеликі довідники Немає зв'язків між сутностями та вибірок за умовою; складні фільтри доводиться робити в пам'яті
Реляційна база Строга схема, звіти, зв'язки «один-до-багатьох», агрегати Важча в налаштуванні, міграції схеми потребують ручного контролю
Документне сховище Гнучка схема, вкладені об'єкти, швидкий старт Слабше виражені зв'язки, частина перевірок лягає на код застосунку
Об'єктне сховище з індексами Пов'язані сутності, вибірки за полями, реактивні потоки Потрібно проєктувати індекси заздалегідь, інакше вибірки деградують на зростанні даних

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

Реактивний режим — підписка на зміни колекції — позбавляє від ручного оновлення екранів, але потребує акуратної відписки, інакше утечі пам'яті.

Практичний висновок: для налаштувань достатньо сховища ключ-значення, для облікових і пов'язаних даних — об'єктне сховище з індексами, реляційна база виправдана там, де потрібні звіти й агрегати. Змішувати режими в одному застосунку нормально: під кожен клас задач — свій інструмент.

Як ми налаштовуємо Isar Flutter: етапи інженерної роботи

Налаштування Isar у Flutter — це не «підключити пакет і забути», а робота зі схемою даних: від того, як спроєктовані індекси та запити, залежить, чи займатиме пошук по локальній базі частки секунди на десятках тисяч записів, чи впиратиметься в повний перебір колекції. Нижче — як ми ведемо таку роботу за кроками, від аудиту до передачі.

  1. Аудит поточної схеми. Дивимося колекції, зв'язки між ними, типи полів і те, які запити реально виконуються в застосунку. Часто з'ясовується, що частина фільтрів іде по неіндексованих полях, а вкладені об'єкти зберігаються так, що вибірка тягне за собою зайві дані.
  2. Проєктування індексів. Під кожен сценарій пошуку та сортування визначаємо складений індекс із правильним порядком полів: спочатку поле рівності, потім діапазон, потім сортування. Прибираємо дублювальні індекси — кожен із них прискорює читання, але сповільнює запис і займає місце у файлі бази.
  3. Налаштування запитів. Переписуємо вибірки під індекси: замінюємо фільтрацію в пам'яті на умови на боці бази, додаємо посторінкову видачу замість завантаження всієї колекції, для реактивних екранів підключаємо спостереження за запитом замість ручного перечитування даних після кожної зміни.
  4. Перевірка на реальних обсягах. Проганяємо сценарії на даних, близьких до бойових: десятки тисяч записів, конкурентний запис, холодний старт. Заміряємо час вибірки та запису, дивимося, де з'являються блокування, і коригуємо схему до того, як це побачать користувачі.
  5. Міграції та сумісність. Продумуємо, як схема змінюватиметься далі: версіонування, перенесення даних при оновленні застосунку, поведінка при відкаті на попередню версію. Це захищає від втрати локальних даних у частини користувачів після релізу.
  6. Документація та передача. Фіксуємо підсумкову схему, призначення кожного індексу та правила додавання нових запитів. Ваша команда отримує не разовий патч, а зрозумілий регламент, за яким база залишається швидкою при розвитку продукту.

Опишіть вашу задачу — повернемося з оцінкою та планом робіт за вашою схемою даних.

Індекси, реактивні запити та міграції схеми

Індекс в Isar — це не «прискорення на всяк випадок», а рішення конкретної вибірки. Складений індекс за парою полів працює, лише якщо порядок полів у запиті збігається з порядком в індексі; при фільтрі за одним «хвостовим» полем він не застосовується.

Тому індексуємо те, за чим реально йде фільтрація та сортування: зовнішні ідентифікатори, статуси, дати. Індекс на низькоселективному полі (прапор із двох значень) дає зростання файлу бази без виграшу на читанні — його краще не заводити.

Реактивність будуємо на watch-запитах, а не на ручному оновленні стану. Потік віддає нову вибірку при зміні заторкнутих об'єктів, і UI перемальовується точково.

Щоб не ловити зайві перебудови, звужуємо запит до конкретного списку або одного об'єкта і не підписуємося на всю колекцію: підписка на широкий набір смикає інтерфейс при кожному записі в базу.

Міграції схеми — найбільш недооцінена частина. Isar зберігає версію схеми, і при незбігу відкриття бази падає, якщо не описати перехід.

Ми фіксуємо версіонування даних явно: додаємо крок міграції, переносимо поля, при перейменуванні заводимо нове поле і переносимо значення, а не перевикористовуємо старе.

  • Індекси — лише під реальні фільтри та сортування, з перевіркою складу й порядку полів.
  • Реактивні підписки — точкові, з відпискою при виході з екрана, щоб не тримати потік.
  • Версіонування схеми — явна версія та покрокові міграції замість «перестворити базу».
  • Обробка помилок відкриття — окрема гілка на незбіг версії, а не падіння застосунку.
  • Тести міграцій — прогін на копії реальних даних до релізу, а не на порожній базі.

Такий підхід до Isar прибирає клас відмов, коли після оновлення застосунок не стартує у частини користувачів. Розбираємо далі, як це лягає на конкретну схему даних.

Що замовник отримує після налаштування сховища

Налаштування сховища — це не «встановили бібліотеку й забули».

Після робіт у команди замовника залишається комплект артефактів, за якими застосунок можна розвивати без автора: новий розробник відкриває репозиторій і бачить, як влаштовані дані, чому обрано саме такі індекси та що робити при зміні моделі. Нижче — що саме передаємо.

  • Схеми колекцій — опис кожної сутності з типами полів, зв'язками та правилами унікальності. За ними видно, які дані лежать локально, а які підтягуються із сервера, і де можливі конфлікти при синхронізації.
  • Конфігурації індексів — які поля проіндексовані, складені це індекси чи одиночні, під які запити вони заведені. Окремо позначаємо індекси, які дорого підтримувати при записі, щоб їх не додавали «про всяк випадок».
  • Регламенти міграцій — покроковий порядок зміни схеми: як додається поле, як переносяться дані, як відкочується невдала міграція. З версіонуванням, щоб оновлення не затирало дані користувача.
  • Документація щодо запитів — типові вибірки, фільтри та сортування з прикладами коду й поясненням, який індекс їх прискорює. Плюс список запитів, які свідомо не оптимізовані, і чому.
  • Правила реактивності — які потоки даних підписані на зміни колекцій, як оновлюється інтерфейс і як уникнути зайвих перемальовувань при масовому записі.
  • Тести сховища — перевірки на коректність міграцій, цілісність зв'язків і поведінку при паралельному записі. Прогоняються в загальній збірці, а не вручну.
  • Інструкція із супроводу — як додати колекцію, перезібрати індекси, відкотити реліз і куди дивитися при розходженні даних.

Комплект залишається у вашому репозиторії та оновлюється разом із кодом. Опишіть задачу — повернемося з оцінкою та планом робіт по вашому застосунку.

Чим відрізняється Isar від інших локальних рішень у Flutter?

Isar — це вбудована об'єктна база даних, яка зберігає дані в одному файлі та працює в тому самому процесі, що й застосунок.

На відміну від рішень, побудованих поверх SQL, тут немає окремого шару трансляції між об'єктами в коді та рядками в таблиці: модель описується класами, а запити будуються через типізований інтерфейс.

Це прибирає цілий клас помилок — розсинхронізацію схеми, ручний розбір результатів, невідповідність типів під час читання.

Ключова відмінність від класичних SQL-рішень — модель реактивності. Isar вміє віддавати потік, який сам оновлюється при зміні даних, тому інтерфейс перемальовується без ручного опитування бази та без проміжного шару керування станом.

Там, де на SQL довелося б вручну інвалідувати кеш і стежити за актуальністю вибірки, тут підписка на запит закриває задачу повністю.

За швидкістю на масових операціях Isar виграє завдяки відсутності накладних витрат на трансляцію запитів і роботі з пам'яттю напряму. Індекси та складені індекси налаштовуються декларативно, тому вибірка за кількома полями залишається передбачуваною навіть на великих обсягах.

Але виграш не універсальний: складні аналітичні вибірки з групуванням і об'єднаннями все ще зручніше й надійніше робити на SQL — там це рідна територія, а не надбудова.

Є й сценарії, де Isar поступається. Якщо потрібна синхронізація між пристроями з розв'язанням конфліктів, вбудованих механізмів тут немає — логіку доведеться будувати самим.

Для застосунків із жорсткими вимогами до серверної валідації та складною рольовою моделлю доступу реляційна база з обмеженнями на рівні схеми дає більше гарантій.

І якщо команда вже щільно працює з SQL, перехід на об'єктну модель потребуватиме перенавчання та переписування шару доступу до даних.

На практиці вибір виглядає так: Isar беруть там, де важливі швидкість локальних операцій, реактивний інтерфейс і простота моделі — списки, стрічки, офлайн-режим, кеш відповідей сервера.

SQL залишається сильнішим у звітності, складних зв'язках і там, де цілісність даних критична на рівні схеми. Рішення ухвалюється не за «краще/гірше», а за тим, який профіль навантаження в конкретного застосунку.

Кейс: прискорили вибірки в застосунку з базою, що зростає

Що було до змін

Застосунок — каталог з офлайн-режимом на Isar: локальна база зберігає товари, категорії та історію замовлень, синхронізація із сервером іде у фоновому режимі. На старті все працювало, але база зростала: спочатку десятки тисяч записів, потім сотні.

Списки категорій і результатів пошуку почали відкриватися з помітною затримкою, а на слабких пристроях з'являлися пропуски кадрів під час прокручування.

Корінь виявився не в обсязі даних, а в тому, як ми до них зверталися. Фільтри та сортування йшли за полями без індексів, застосунок витягував з бази весь набір об'єктів і відсіював зайве вже в пам'яті.

Паралельно синхронізація переписувала пов'язані сутності цілком, і реактивні підписки на екранах спрацьовували на кожне таке оновлення — інтерфейс перемальовувався частіше, ніж змінювалися дані.

Що змінили

Перезібрали схему: додали складені індекси під реальні сценарії — категорія плюс дата, статус плюс дата зміни, окремий індекс для пошуку за назвою.

Запити переписали так, щоб фільтрація та сортування виконувалися на боці бази, а не в пам'яті, і додали посторінкову вибірку замість читання всього набору.

Синхронізацію перевели на точкові оновлення: замість перезапису пов'язаних сутностей цілком змінюються лише ті поля, що змінилися. Реактивні підписки звузили до конкретних запитів — екран списку більше не реагує на оновлення картки товару, яку користувач не відкривав.

Метрики до і після

Показник До Після
Відкриття списку категорій 1.8–2.4 с 180–260 мс
Пошук по каталогу 3.1 с 240–310 мс
Споживання пам'яті на екрані списку 210–260 МБ 90–120 МБ
Пропуски кадрів під час прокручування регулярно поодинокі

Окремо закрили клас відмов під час синхронізації: раніше при обриві зв'язку на середині перезапису пов'язаних сутностей частина записів залишалася в проміжному стані, і користувач бачив розбіжність між локальною базою та сервером.

Точкові оновлення в межах однієї транзакції прибрали це вікно — неповних станів після збою більше не виникає.

Робота зайняла два тижні, включно з прогоном на реальних вивантаженнях бази.

Часті технічні сумніви щодо Isar

Isar у Flutter ставлять, коли застосунку потрібна локальна база з реактивними запитами та передбачуваною швидкістю на великих обсягах. Нижче — розбір сумнівів, з якими команди звертаються найчастіше.

Наскільки Isar сумісний із поточним стеком Flutter?

Isar — нативна база для Dart, працює і на мобільних платформах, і на десктопі, і у вебзбірці через окремий бекенд. Схеми описуються звичайними класами з анотаціями, генератор збирає код доступу на етапі збірки — ручний мапінг рядків і колонок не потрібен. Якщо в проєкті вже є шар репозиторіїв, Isar вбудовується за ним без переписування екранів.

Який обсяг даних витримує без деградації?

Запити йдуть за індексами, а не повним перебором, тому вибірка за складеним ключем залишається швидкою і на сотнях тисяч записів. Індекси оголошуються у схемі: унікальні, складені, з заміною регістру.

Важливо стежити за розміром індексованих полів — роздутий індекс сповільнює запис сильніше, ніж зростає сама база.

Як влаштована реактивність і чи не буде зайвих перемальовувань?

Підписка на запит віддає потік, який перезбирається при зміні заторкнутих об'єктів. Оновлення точкове: правка одного запису не тягне перерахунок усієї колекції, якщо запит обмежений фільтром. На практиці це знімає ручну синхронізацію стану між екранами.

Що з міграціями при зміні схеми?

Версія схеми зберігається в самій базі, при незбігу запускається міграція: перейменування полів, зміна типів, перебудова індексів. Дані користувача при цьому зберігаються — критично для застосунків, де локальна база це єдине сховище. Міграції проганяються на копії реальних даних до релізу.

Підтримка платформ і доступ до файлу бази

Одна кодова база закриває мобільні платформи та десктоп; відмінності стосуються шляху до файлу та прав доступу, їх закриває шар ініціалізації.

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

Якщо залишилися питання щодо конкретного сценарію — опишіть задачу, повернемося з оцінкою та планом.

Обговоримо ваше завдання щодо локального сховища

Щоб оцінка була точною, а не «за відчуттями», нам потрібні вихідні дані щодо вашого проєкту: схема даних і зв'язки між сутностями, сценарії читання та запису, вимоги до офлайн-режиму й синхронізації. Чим конкретніші вхідні дані, тим менше припущень у плані робіт і тим передбачуваніші строки.

Опишіть завдання — повернемося з оцінкою та планом робіт. У відповідь ви отримаєте:

  • розбір поточної схеми зберігання та вузьких місць: де запити виконуються повним перебором, а де бракує індексів;
  • пропозицію щодо структури колекцій і складу індексів під ваші сценарії вибірки;
  • схему реактивних підписок: які екрани на що підписані та як уникнути зайвих перебудов інтерфейсу;
  • план міграції даних між версіями схеми без втрати користувацьких записів;
  • стратегію синхронізації із сервером: розв'язання конфліктів, повторні спроби, робота при обриві зв'язку;
  • перелік перевірок на тестових наборах даних, включно з граничними випадками та великими обсягами;
  • оцінку трудомісткості за етапами та склад команди під ваш обсяг.

Якщо застосунок уже в продакшені, окремо проговоримо, як змінювати схему на живій базі: версіонування, зворотна сумісність, відкат на попередню версію застосунку. Це той клас завдань, де помилка в міграції коштує дорожче, ніж сама розробка.

Надішліть доступ до репозиторію або вивантаження моделей та опис ключових запитів — цього достатньо, щоб перейти від загальних слів до конкретного плану.

Наші компетенції:

Останні роботи

  • Розробка мобільного додатка для компанії FEEDME
    Розробка мобільного додатка для компанії FEEDME
    1009
  • Розробка мобільного додатку для компанії XOOMER
    Розробка мобільного додатку для компанії XOOMER
    902
  • Розробка мобільного додатку для компанії RHL
    Розробка мобільного додатку для компанії RHL
    1331
  • Розробка мобільного додатку для компанії ZIPPY
    Розробка мобільного додатку для компанії ZIPPY
    1179
  • Розробка мобільного додатку для компанії Affhome
    Розробка мобільного додатку для компанії Affhome
    1106
  • Розробка мобільного додатку для компанії FLAVORS
    Розробка мобільного додатку для компанії FLAVORS
    713