Лучший (бесплатный) способ хранения данных? Как насчет обновлений файловой системы?

У меня есть идея, как решить эту проблему, но я хотел знать, есть ли что-то более простое и расширяемое для моей проблемы.

Программа, над которой я работаю, имеет две основные формы данных: изображения и информацию, связанную с этими изображениями. Информация, связанная с изображениями, ранее хранилась в чрезвычайно простой базе данных JET (четыре таблицы), которая оказалась как медленной, так и неполной в сохраненных полях. Мы переходим к новой реализации хранения данных. Учитывая простоту задействованных структур данных, я подумал, что базы данных слишком много.

Каждое изображение будет иметь собственную информацию (параметры захвата), будет частью группы изображений, которые взаимосвязаны (например, сняты в течение одного тридцатиминутного периода), а затем частью более крупной группы (сняты одним и тем же человеком. ). Прямо сейчас я храню людей в словаре с уникальным идентификатором. Затем у каждого человека есть Список различных групп изображений, а у каждой группы изображений есть Список изображений. Все эти классы сериализуемы, а я просто сериализую и десериализую словарь. Довольно простой материал. Изображения хранятся отдельно, поэтому размер словаря не становится астрономическим.

Проблема в следующем: что происходит, когда мне нужно добавить новые информационные поля? Есть ли простой способ настроить эти структуры данных для учета потенциальных будущих изменений? Раньше в C я с этим справлялся, создавая сериализуемую структуру с большим количеством пустых байтов (по крайней мере, k) для будущей расширяемости, причем один из байтов в структуре указывал версию. Затем, когда программа прочитает структуру, она будет знать, какую десериализацию использовать на основе массивного оператора switch (а старые версии могут читать новые данные, потому что посторонние данные просто попадают в поля, которые игнорируются).

Есть ли такая схема в C#? Например, если у меня есть класс, представляющий собой группу объектов String и Int, а затем я добавляю в структуру еще один объект String, как я могу десериализовать объект с диска, а затем добавить к нему строку? Должен ли я смириться с наличием нескольких версий классов данных и фабрики, которая принимает поток десериализации и обрабатывает десериализацию на основе некоторой информации о версии, хранящейся в базовом классе? Или такой класс, как Dictionary, идеально подходит для хранения такой информации, поскольку он автоматически десериализует все поля на диске, и если в них добавлены новые поля, я могу просто перехватить исключения и заменить эти значения пустыми строками и Ints?

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

Спасибо!

Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
4
0
1 275
6
Перейти к ответу Данный вопрос помечен как решенный

Ответы 6

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

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

Через год или два, если код все еще используется, вы будете счастливы, что 1) другим разработчикам не придется изучать настраиваемую структуру кода для поддержки кода, 2) вы можете экспортировать, просматривать, изменять данные со стандартными инструментами базы данных (есть драйвер ODBC для файлов sqlite и различные инструменты запросов) и 3) вы сможете масштабироваться до базы данных с минимальными изменениями кода.

Итак, отдельная таблица для каждой из других таблиц? Могу ли я затем загрузить их в объекты класса, чтобы сохранить как объекты, так и таблицы данных? Как мне обновить таблицы? Я не понимаю многих деталей с этими реализациями базы данных ...

mmr 27.09.2008 01:53

Есть схема базы данных, название которой я не могу вспомнить, которая может справиться с подобными ситуациями. У вас в основном две таблицы. В одной таблице хранится имя переменной, а в другой - значение переменной. Если вы хотите сгруппировать переменные, добавьте третью таблицу, которая будет иметь отношение «один ко многим» с таблицей имен переменных. Эта установка имеет то преимущество, что позволяет вам продолжать добавлять различные переменные без необходимости постоянно менять схему базы данных. Я сэкономил много раз, когда имел дело с отделами, которые часто меняют свое мнение (например, по маркетингу).

Единственным недостатком является то, что таблица значений переменных должна будет хранить фактическое значение в виде строкового столбца (на самом деле varchar или nvarchar). Затем вам придется столкнуться с трудностями при преобразовании значений обратно в их собственные представления. В настоящее время я поддерживаю что-то подобное. В таблице переменных сейчас около 800 миллионов строк. Это все еще довольно быстро, так как я все еще могу получить определенные вариации значений менее чем за одну секунду.

Это называется моделью EAV (сущность / атрибут / значение). Он популярен в таких областях, как фармацевтическое тестирование, где у них нет четкого представления о возможных столбцах.

Turnkey 27.09.2008 02:22

Интересно. Итак, у меня была бы пара таблиц (вероятно, в sqlite, которую я собираю), а затем я бы поддерживал кучу классов, в которые встраиваются данные, а затем использовал бы словарь как внутрипрограммную память, верно?

mmr 27.09.2008 02:22
Ответ принят как подходящий

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

Вот краткий список известных мне реализаций C# /. NET:

К сожалению, это C#, поэтому буферы протоколов недоступны для этого языка (пока!)

mmr 27.09.2008 02:16

Конечно, есть, ммр! Я обновил ответ, включив в него ссылки на известные мне реализации.

Alex Lyman 27.09.2008 02:52

Спасибо, проверю. Мне нравится, что есть так много разных ответов, которые нужно попробовать ... если бы у меня было время понять их все

mmr 27.09.2008 06:30

Для того, что мне нужно, буферы протоколов оказались правильным решением - мы используем версию Марка Грейвелла.

mmr 03.04.2009 02:04

Я не программист на C#, но мне нравится вызов mmap (), и я увидел, что есть проект, делающий такое для C#.

См. Mmap

Structured files are very performing if tailored for a specific application but are difficult to manage and an hardly reusable code resource. A better solution is a virtual memory-like implementation.

  • Up to 4 gigabyte of information can be managed.
  • Space can be optimized to real data size.
  • All the data can be viewed as a single array and accessed with read/write operations.
  • No needing to structure to store but just use and store.
  • Can be cached. Is highly reusable.

Почему это лучше, чем сериализация / десериализация словаря на диск? Похоже, что в будущем у меня все еще будут проблемы с расширяемостью.

mmr 27.09.2008 02:21

Поэтому используйте sqllite по следующим причинам:
1. Вам не нужно каждый раз читать / записывать всю базу данных с диска
2. Намного проще добавить, даже если вы не оставляете достаточно заполнителей в начале
3. Легче искать на основе всего, что вы хотите
4. проще изменять данные способами, выходящими за рамки приложения, которое было разработано

Проблемы со словарным подходом 1. Если вы не создали умный словарь, вам нужно каждый раз читать / записывать всю базу данных (если вы тщательно не спроектируете структуру данных, будет очень сложно поддерживать обратную совместимость)
----- а) если вы не оставили достаточно заполнителей до свидания
2. Похоже, что вам придется выполнить линейный поиск по всем фотографиям, чтобы выполнить поиск по одному из атрибутов захвата
3. Может ли изображение быть в нескольких группах? Может ли фотография находиться под более чем одним человеком? Могут ли два человека быть в одной группе? Со словарями эти вещи могут стать непосильными ....

Для таблицы базы данных, если вы получаете новый атрибут, вы можете просто сказать «Изменить изображение таблицы» Добавить тип данных атрибута. Затем, пока вы не создадите правило, согласно которому атрибут должен иметь значение, вы все равно можете загружать и сохранять более старые версии. В то же время более новые версии могут использовать новые атрибуты.

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

Вероятно, ваш стол должен быть
Изображение (PictureID, GroupID?, Путь к файлу, параметр захвата 1, параметр захвата 2 и т. д.)

Если вы хотите большей гибкости, вы можете сделать таблицу CaptureParameter (PictureID, ParameterName, ParameterValue) ... Я бы посоветовал этого не делать, потому что это намного менее эффективно, чем просто поместить их в одну таблицу (не говоря уже о запросах для получения / поиска параметров захвата, которые были бы более сложными).

Человек (PersonID, любые атрибуты человека, такие как имя и т. д.)
Группа (GroupID, Group Name, PersonID?)
PersonGroup? (PersonID, GroupID)
. PictureGroup? (GroupID, PictureID)

Небольшое предупреждение, SQLLite, Protocol Buffers, mmap и др ... все очень хорошо, но вы должны создать прототип и протестировать каждую реализацию и убедиться, что вы не столкнетесь с теми же проблемами производительности или разными узкими местами.

Простота может заключаться в увеличении размера до SQL (Express) (вы можете быть удивлены увеличением производительности) и исправлением всего, чего не хватает в нынешнем дизайне базы данных. Затем, если производительность по-прежнему остается проблемой, начните исследовать эти другие технологии.

Другие вопросы по теме