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

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

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

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

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

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

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

Спасибо!

Ответы [ 6 ]

2 голосов
/ 27 сентября 2008

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

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

2 голосов
/ 27 сентября 2008

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

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

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

1 голос
/ 27 сентября 2008

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

См. Mmap

Структурированные файлы очень эффективны, если приспособлены для конкретного приложения, но сложны в управлении и являются трудно используемым кодом. Лучшее решение - реализация, подобная виртуальной памяти.

  • Можно управлять до 4 гигабайт информации.
  • Пространство можно оптимизировать до реального размера данных.
  • Все данные можно просматривать как один массив и получать к ним доступ с помощью операций чтения / записи.
  • Нет необходимости структурировать для хранения, а просто использовать и хранить.
  • Можно кэшировать. Многоразового использования.
1 голос
/ 27 сентября 2008

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

Вот краткий список реализаций, которые я знаю о C # /. NET:

1 голос
/ 27 сентября 2008

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

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

0 голосов
/ 27 сентября 2008

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

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

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

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

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

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

Персона (PersonID, Любые Атрибуты Лица как Имя / И т.д.)
Группа (GroupID, Имя группы, PersonID?)
PersonGroup? (PersonID, GroupID)
PictureGroup? (GroupID, PictureID)

...