Проблема
Зачем использовать вообще одно из этих решений?
Существуют модели, у которых необходимо выделить разновидности и сделать это именно с помощью типов, а не категорий... Разберёмся...
Тип - разновидность модели, не всегда, но влияющая на состав её параметров
Категория - одна из характеристик модели, указывающая на принадлежность к разновидности, не влияющая на состав её параметров
Решение
Решить данную проблему можно 2 основными способами:
-
Использовать enums (перечисления)
-
Использовать таблицы
Использование enums более пригодно при наличии небольшого кол-ва типов (до 5 на каждый enum)
К преимуществу использования таблиц можно отнести возможность реализовать многоуровневость типов, не плодя дополнительные сущности и типы.
Не придётся создавать таблицу под каждый тип, у которого есть подтипы, что желательно делать при использовании enums.
Практическая ситуация
Есть база данных, в которой необходимо выделить разновидности "счетов" для приложения по учёту домашней бухгалтерии.
Счета бывают :
-
Дебетовые
-
Кредитные:
-
Ипотека
-
Автокредит
-
Потребительский кредит
-
Рассрочка
-
Долг
-
-
Депозитные:
-
Объекты (материальные):
-
Недвижимость
-
Транспорт
-
Ценная вещь
-
-
Вклады (не материальные):
-
Депозит (банковский вклад)
-
Депозит (копилка)
-
Инвестиции
-
Долг
-
-
Я разработал два варианта диаграмм и структур данных для решения конкретной ситуации:
Тестирование: Enums VS Tables
Данные для тестирования:
18000 записей = 10000 счетов + 1500 кредитных + 3500 объектов + 3000 вкладов
Использовал СУБД PostgreSQL, так как она мне нравится больше остальных.
Тестирование проводил 10 раз, чтобы получить более усреднённые данные.
Для соединения .NET приложения с базой данных использовались: ORM (Entity Framework) и ADO.NET (Npgsql).
На картинках измерение в миллисекундах!
Генерация данных
Первое - (неважное) генерация данных с помощью .NET Faker
Тут оказалось, что быстрее генерируется схема с таблицами, хотя с точки зрения моделей действия для генерация не отличаются.
Добавление данных
Второе испытание - добавление всех 18000 записей в базу данных.
Для Entity Framework просто добавление записей.
А вот для ADO.NET (Npgsql) добавление сделаем несколькими способами:
-
Все записи добавляются 1 запросом
-
Пакеты по <= 1000 запросов
-
Пакеты по <= 800 запросов
-
Пакеты по <= 500 запросов
Очевидно, что самое долгое - это добавление всех записей 1 запросом... в среднем около 19-20сек.
Интересное:
Сравниваем добавление через Entity Framework и пакетную отправку (исследование внутри исследования)Оказалось, что скорости Entity Framework по добавлению +- сопоставляются с отправкой пакетами по <= 1000 запросов.
Поэтому пакеты меньшего размера будут давать прирост производительности.Максимального прироста смог добиться, отправляя пакеты по <= 500 запросов, тем самым обогнав Entity Framework на 0,5-0,7сек или же на 33-38%!
... Возвращаемся к исследованию Enums VS Tables:
Единственное измерение, где подход таблиц смог "победить" enums - это добавление всех записей 1 запросом... и то в районе погрешности - всего на 1,6%... не густо...
Во всех остальных замерах на лицо превосходство enums подхода.
В среднем он быстрее на 13%:
-
Добавление через Entity Framework - 19%
-
Добавление 1 запросом - -1.6%
-
Добавление пакетами по <= 1000 запросов - 11%
-
Добавление пакетами по <= 800 запросов - 9%
-
Добавление пакетами по <= 500 запросов - 14%
Разница между tables и enums при добавлении данных (% от tables подхода) |
|
Добавление через Entity Framework |
19% |
Добавление 1 запросом |
- 1,6% (в зоне погрешности) |
Добавление пакетами по <= 1000 запросов |
11% |
Добавление пакетами по <= 800 запросов |
9% |
Добавление пакетами по <= 500 запросов |
14% |
Получение одной записи
Алгоритм получения записи следующий:
-
Получаем запись счета по Id
-
Определяем - какой тип счета у записи
-
Лезем в соответствующую таблицу и достаём оттуда запись по Id
Тут ситуация неоднозначная:
Если использовать Entity Framework, то enums быстрее табличного подхода на 3%.
Если же использовать Npgsql, то табличный подход быстрее enums на 5%.
Эти значения в рамках погрешности, так что буду считать, что разницы при получении 1 записи между подходами нету!
Вывод?
В добавлении записей выигрывает enums подход (подход перечислений) в среднем на 13%.
Но у enums есть ограничения, которые не позволяют их использовать во всех ситуациях, когда нужно ввести типы моделей:
-
Они неизменяемы (да, добавить новое значение можно... но удалить ненужное уже трудно)
-
Лучше хранить не более 5-7 значений в одном enum, чтобы они не превратились в номенклатуру
-
Требует уверенных знаний SQL
Выбирать enum подход (подход перечислений) стоит, если:
-
Не нужна структура подтипов
-
Не планируется изменение списка значений
-
Количество типов не превышает 5-7 на одно перечисление
Автор: anavov4ik