У меня есть идея, как решить эту проблему, но я хотел знать, есть ли что-то более простое и расширяемое для моей проблемы.
Программа, над которой я работаю, имеет две основные формы данных: изображения и информацию, связанную с этими изображениями. Информация, связанная с изображениями, ранее хранилась в чрезвычайно простой базе данных JET (четыре таблицы), которая оказалась как медленной, так и неполной в сохраненных полях. Мы переходим к новой реализации хранения данных. Учитывая простоту задействованных структур данных, я подумал, что базы данных слишком много.
Каждое изображение будет иметь собственную информацию (параметры захвата), будет частью группы изображений, которые взаимосвязаны (например, сняты в течение одного тридцатиминутного периода), а затем частью более крупной группы (сняты одним и тем же человеком. ). Прямо сейчас я храню людей в словаре с уникальным идентификатором. Затем у каждого человека есть Список различных групп изображений, а у каждой группы изображений есть Список изображений. Все эти классы сериализуемы, а я просто сериализую и десериализую словарь. Довольно простой материал. Изображения хранятся отдельно, поэтому размер словаря не становится астрономическим.
Проблема в следующем: что происходит, когда мне нужно добавить новые информационные поля? Есть ли простой способ настроить эти структуры данных для учета потенциальных будущих изменений? Раньше в C я с этим справлялся, создавая сериализуемую структуру с большим количеством пустых байтов (по крайней мере, k) для будущей расширяемости, причем один из байтов в структуре указывал версию. Затем, когда программа прочитает структуру, она будет знать, какую десериализацию использовать на основе массивного оператора switch (а старые версии могут читать новые данные, потому что посторонние данные просто попадают в поля, которые игнорируются).
Есть ли такая схема в C#? Например, если у меня есть класс, представляющий собой группу объектов String и Int, а затем я добавляю в структуру еще один объект String, как я могу десериализовать объект с диска, а затем добавить к нему строку? Должен ли я смириться с наличием нескольких версий классов данных и фабрики, которая принимает поток десериализации и обрабатывает десериализацию на основе некоторой информации о версии, хранящейся в базовом классе? Или такой класс, как Dictionary, идеально подходит для хранения такой информации, поскольку он автоматически десериализует все поля на диске, и если в них добавлены новые поля, я могу просто перехватить исключения и заменить эти значения пустыми строками и Ints?
Если я буду использовать словарный подход, есть ли снижение скорости, связанное с чтением / записью файла, а также временем поиска параметров? Я полагаю, что если в классе есть только поля, то извлечение поля происходит мгновенно, но в словаре есть небольшие накладные расходы, связанные с этим классом.
Спасибо!





Sqlite - это то, что вам нужно. Это быстрая встраиваемая однофайловая база данных, привязанная к большинству языков.
Что касается расширяемости, вы можете хранить свои модели с атрибутами по умолчанию, а затем иметь отдельную таблицу для расширений атрибутов для будущих изменений.
Через год или два, если код все еще используется, вы будете счастливы, что 1) другим разработчикам не придется изучать настраиваемую структуру кода для поддержки кода, 2) вы можете экспортировать, просматривать, изменять данные со стандартными инструментами базы данных (есть драйвер ODBC для файлов sqlite и различные инструменты запросов) и 3) вы сможете масштабироваться до базы данных с минимальными изменениями кода.
Есть схема базы данных, название которой я не могу вспомнить, которая может справиться с подобными ситуациями. У вас в основном две таблицы. В одной таблице хранится имя переменной, а в другой - значение переменной. Если вы хотите сгруппировать переменные, добавьте третью таблицу, которая будет иметь отношение «один ко многим» с таблицей имен переменных. Эта установка имеет то преимущество, что позволяет вам продолжать добавлять различные переменные без необходимости постоянно менять схему базы данных. Я сэкономил много раз, когда имел дело с отделами, которые часто меняют свое мнение (например, по маркетингу).
Единственным недостатком является то, что таблица значений переменных должна будет хранить фактическое значение в виде строкового столбца (на самом деле varchar или nvarchar). Затем вам придется столкнуться с трудностями при преобразовании значений обратно в их собственные представления. В настоящее время я поддерживаю что-то подобное. В таблице переменных сейчас около 800 миллионов строк. Это все еще довольно быстро, так как я все еще могу получить определенные вариации значений менее чем за одну секунду.
Это называется моделью EAV (сущность / атрибут / значение). Он популярен в таких областях, как фармацевтическое тестирование, где у них нет четкого представления о возможных столбцах.
Интересно. Итак, у меня была бы пара таблиц (вероятно, в sqlite, которую я собираю), а затем я бы поддерживал кучу классов, в которые встраиваются данные, а затем использовал бы словарь как внутрипрограммную память, верно?
В данный момент мой мозг перегорел, поэтому я не уверен, что могу посоветовать за или против базы данных, но если вы ищете сериализацию, не зависящую от версии, вы были бы дураком, если бы хотя бы не проверили Буферы протокола.
Вот краткий список известных мне реализаций C# /. NET:
К сожалению, это C#, поэтому буферы протоколов недоступны для этого языка (пока!)
Конечно, есть, ммр! Я обновил ответ, включив в него ссылки на известные мне реализации.
Спасибо, проверю. Мне нравится, что есть так много разных ответов, которые нужно попробовать ... если бы у меня было время понять их все
Для того, что мне нужно, буферы протоколов оказались правильным решением - мы используем версию Марка Грейвелла.
Я не программист на 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.
Почему это лучше, чем сериализация / десериализация словаря на диск? Похоже, что в будущем у меня все еще будут проблемы с расширяемостью.
Поэтому используйте 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) (вы можете быть удивлены увеличением производительности) и исправлением всего, чего не хватает в нынешнем дизайне базы данных. Затем, если производительность по-прежнему остается проблемой, начните исследовать эти другие технологии.
Итак, отдельная таблица для каждой из других таблиц? Могу ли я затем загрузить их в объекты класса, чтобы сохранить как объекты, так и таблицы данных? Как мне обновить таблицы? Я не понимаю многих деталей с этими реализациями базы данных ...