Всем привет. Это очередная история нашего регулярного сегмента «тестирование очевидных вещей по вторникам». И в этот раз мое внимание привлекла тема выбора базы данных для локального хранения данных во Flutter-приложении. Эта тема очень заезжена, и о ней написано множество статей, большинство из которых касается лишь практического сравнения трех альтернативных вариантов хранения данных: Hive, SQLite и SharedPreferences.

Я не буду тратить ваше время на описание каждого из них, поскольку, если вы читаете эту статью, вы, вероятно, уже знаете, что это такое. И я буду сравнивать Hive и SQLite только потому, что не могу считать SharedPreferences базой данных (можете кидать в меня лимонами, я уже налил себе текилы🤙).

Итак, как же выглядит среднестатистическая статья о выборе базы данных?

«Здравствуйте. Используйте Hive, не используйте SQLite. До свидания.

И в подтверждение этому представлена ​​вот такая интересная инфографика:

На самом деле это выглядит грустно, потому что любой, кто хоть раз видел, как устроен настоящий взрослый бэкенд, не будет сравнивать MongoDB и PostgreSQL только по производительности. Серьёзно, зачем вводить в заблуждение наивных новичков, которые хотят делать мобильные приложения?

Конечно, давайте воздержимся от выводов до конца статьи. Вы все увидите сами.

Для начала создадим файл с именем my_class.dart, в котором опишем тестовый объект для чтения/записи из базы данных. В конце концов, мы хотим протестировать реальное использование, а не только целые числа и строки, как на скриншотах выше, верно ?

import 'package:hive/hive.dart';

class MyClass {
  int id;
  String name;

  MyClass(this.id, this.name);
}

class MyClassAdapter extends TypeAdapter<MyClass> {
  @override
  final typeId = 0;

  @override
  MyClass read(BinaryReader reader) {
    final id = reader.readInt();
    final name = reader.readString();
    return MyClass(id, name);
  }

  @override
  void write(BinaryWriter writer, MyClass obj) {
    writer.writeInt(obj.id);
    writer.writeString(obj.name);
  }
}

Далее, как обычно, создадим файл _test:

import 'package:flutter/widgets.dart';
import 'package:benchmarking/benchmarking.dart';
import 'package:hive/hive.dart';
import 'package:hive_flutter/hive_flutter.dart';
import 'package:sqflite/sqflite.dart';
import 'dart:math';
import 'package:path_provider/path_provider.dart';
import 'package:sqflite_common_ffi/sqflite_ffi.dart';

import 'my_class.dart';

void main() async {
  // Initialize Hive
  WidgetsFlutterBinding.ensureInitialized();
  Hive.init('.');

  // Register adapter if necessary
  Hive.registerAdapter(MyClassAdapter());

  // Generate test data
  final testData = List.generate(1000, (index) => MyClass(index, 'test'));

  // Benchmark SQLite
  databaseFactory = databaseFactoryFfi;
  final db = await openDatabase('test.db', version: 1, onCreate: (Database db, int version) async {
    await db.execute('CREATE TABLE Test (id INTEGER PRIMARY KEY AUTOINCREMENT, name TEXT)');
  });
  syncBenchmark('SQLite Insert', () async {
    for (int i = 0; i < testData.length; i++) {
      await db.insert('Test', {'id': testData[i].id, 'name': testData[i].name});
    }
  }).report();

  syncBenchmark('SQLite Select', () async {
    await db.rawQuery('SELECT * FROM Test');
  }).report();

// Benchmark Hive
  syncBenchmark('Hive Insert', () async {
    final box = await Hive.openBox<MyClass>('benchmark');
    for (int i = 0; i < testData.length; i++) {
      await box.put(i, testData[i]);
    }
  }).report();

  syncBenchmark('Hive Select', () async {
    final box = await Hive.openBox<MyClass>('benchmark');
    box.values.toList();
  }).report();

  // Clean up
  db.close();
  Hive.deleteBoxFromDisk('benchmark');
}

В нашем эксперименте мы создали 1000 объектов класса MyClass со случайными значениями, а затем выполнили вставку и выборку данных в SQLite и Hive.

Итак, давайте посмотрим на результат:

Чтобы вам было легче видеть, я переведу результаты в формат графика:

Хорошо, у меня есть один вопрос.

Серьезно

Хотя Hive показал лучшую производительность в этом тесте, разница в производительности между Hive и SQLite не настолько значительна, чтобы писать статью о Hive в религиозном безумии.

Основным преимуществом Hive является простота использования. Hive позволяет быстро создавать и использовать объекты. Это может быть особенно полезно для приложений, которые не требуют больших объемов данных и требуют быстрой реакции на ввод данных пользователем.

С другой стороны, SQLite — более мощный инструмент для управления данными, особенно для крупномасштабных проектов с большим объемом данных. SQLite может предоставить множество опций для управления данными, таких как ограничения целостности, триггеры и т. д.

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

Вам также могут быть интересны другие мои тесты:







Технический персонал:



Или целая серия статей о работе с REST API (это настоящее дерьмо как Санта-Барбара):