2010-02-09 4 views
8

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

  • Это приложение .NET.
  • мне нужно хранить до 200000 объектов (между 3KB-500 КБ)
  • мне нужно хранить около 10 из них в секунду от множественных потоков
  • Я использую binaryserialization перед хранением
  • мне нужно получить доступ их позже целое число, уникальный идентификатор

Каков наилучший способ для этого?

  • Я не могу держать их в памяти, как я буду получать OutOfMemory исключения
  • Когда я храню их на диске в виде отдельных файлов, что возможные проблемы с производительностью? Это значительно снизит общую производительность?
  • Должен ли я реализовать какое-то кэширование, например, объединить 100 объектов и записать его один раз в виде одного файла. Затем проанализируйте их позже. Или что-то подобное?
  • Следует использовать базу данных? (время доступа не важно, поиска не будет, и я получаю доступ только пару раз по известному уникальному идентификатору). Теоретически мне не нужна база данных, я не хочу ее усложнять.

UPDATE:

  • Я предполагаю, что база данных будет медленнее, чем файловая система, докажите меня неправильно, если вы что-то об этом. Вот почему я тоже склоняюсь к файловой системе. Но я действительно беспокоюсь о том, чтобы записать 200 КБ * 10 в секунду на жесткий диск (это может быть любой жесткий диск, я не контролирую аппаратное обеспечение, это настольный инструмент, который будет развернут в разных системах).
  • Если я использую файловую систему, которую я буду хранить файлы в отдельных папках, чтобы избежать проблем, связанных с файловой системой (, так что вы можете игнорировать это ограничение)
+0

ли уникальный идентификатор, предоставленный нам, или мы должны создать его? Если мы должны создать его, это нужно, чтобы выжить перезапуски системы? –

+0

уникального идентификатор уже позаботился о при условии, –

+0

Обратите внимание на обман, но смотрите: http://stackoverflow.com/questions/2230032/which-is-a-better-method-for- storage-images-folder-or-sql-server-as-binary –

ответ

3

Если вы хотите избежать использования базы данных, вы можете сохранить их как файлы на диске (чтобы все было просто).Но вам нужно знать соображения файловой системы при сохранении большого количества файлов в одном каталоге.

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

Хорошим решением является ограничение вашего каталога на небольшое число узлов (скажем n = 1000) и создание дерева файлов в каталоге.

Таким образом, вместо того, чтобы хранить файлы как:

/реж/file1/реж/file2/реж/file3 .../реж/fileN

хранить их как:

/реж/Г1/s2/file1/dir/r1/s2/file2 .../dir/rM/sN/fileP

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

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

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

В качестве альтернативы, если это не разрезает его, вы можете использовать встроенную базу данных, такую ​​как SQLlite или Firebird.

HTH.

+0

Я не контролирую аппаратное обеспечение, так что это может быть что угодно: от жесткого жесткого диска с FAT32 (вряд ли, но возможно) до RAID. ОС всегда Windows, хотя это .NET в Windows, без моно. –

+0

@dr. evil: Я думаю, что в случае «дрянного жесткого диска», неспособного хранить 2 МБ/с, любое решение, включая DMBS, потерпит неудачу, просто потому, что любая СУБД добавляет свои собственные накладные расходы при хранении данных. –

+0

Это ужасная идея; Я пробовал что-то вроде этого, и это непрактично даже в современных файловых системах, таких как ext4. Большинство FS будут подавляться, если вы добавите больше 8k файлов в 8k dirs. В моей настройке каждый файл хэширован и помещен в структуру dir, например img/a412/8cdf/e9k4/rest_of_hash.png, и она в основном убила меня, потому что у меня (а) закончились inodes, (b) убил все тралы файлов из-за тысяч каталоги и (c) использовать тонны дополнительного дискового пространства, потому что каждый каталог составляет 4096 тыс., даже если мои изображения составляют 2 тыс. Хранилище файловой системы для таких вещей - это BAD IDEA для широкомасштабных решений. – Nthalk

2

Я был бы соблазн использовать базу данных, в C++ либо sqlite, либо coucheDB.
Они будут работать в .Net, но я не знаю, есть ли более эффективная альтернатива .Net.

Даже на файловых системах, которые могут обрабатывать 200000 файлов в директории, требующимся для того, чтобы когда-нибудь открыть каталог

Edit - БД, вероятно, будет быстрее!
Файловая система не предназначена для огромного количества небольших объектов, БД.
Он будет реализовывать всевозможные умные операции кэширования/транзакции, о которых вы никогда не думали.

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

+0

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

1

вы можете проверить mongoDb, он поддерживает файлы хранилища.

+0

Есть ли преимущество в производительности MongoDB? Я предполагаю, что это будет медленнее, если это то, что является преимуществом по сравнению с файловой системой (при условии, что я буду группировать файлы 1000 на каждую папку в файловой системе). –

0

Единственный способ узнать наверняка будет узнать больше о вашем сценарии использования.

Например, в дальнейшем использование файлов потребует их в кластерах по 100 файлов за раз? Возможно, если это так, было бы разумно объединить их.

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

Вот что я хотел бы сделать:

  1. сделать класс, который имеет дело с хранения и поиска (так что вы можете позже на смену этому классу, и не каждая точка в вашем приложении, которое использует его)
  2. Хранить файлы на диске как есть, не комбинировать их
  3. Распространять их по подкаталогам, сохраняя 1000 или менее файлов в каждом каталоге (доступ к каталогам добавляет служебные данные, если у вас много файлов в одном каталоге)
+0

сценарий использования понятен, как объясняется в вопросе, позже использование не имеет никакого значения, Я получаю доступ к нему только 0-10 раз и должен получить доступ по ID. Не важно, как долго это происходит, как только это будет менее 15-30 секунд. –

0

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

Если вам нужно много писать и читать редко (например, файлы журналов), вы должны создать a.zip-файл или тому подобное (выберите уровень сжатия, который не слишком замедляет работу, в рейтинге 1-9, как правило, для меня работает 5 или около того). Это дает вам несколько преимуществ: вы не так сильно ударяете файловую систему, ваше место для хранения уменьшается, и вы можете естественно группировать файлы в блоках по 100 или 1000 или что-то еще.

Если вам нужно написать много и читать много, вы можете определить свой собственный формат плоского файла (если у вас нет доступа к коммунальным услугам для чтения и записи .tar файлов и т.п., или схитрить и поместить двоичные данные в 8-битном оттенке серого TIFF). Определите записи для каждого заголовка - возможно, 1024 байта, каждый из которых содержит смещение в файле, имя файла и все остальное, что вам нужно для хранения, - и затем записывайте данные в куски. Когда вам нужно прочитать фрагмент, сначала прочитайте заголовок (возможно, 100k), а затем перейдите к нужному смещению и прочитайте нужную сумму. Преимущество заголовков фиксированного размера заключается в том, что вы можете сначала записать в них пустые данные, а затем просто добавить новые файлы в конец файла, а затем вернуться и перезаписать соответствующую запись.

Наконец, вы могли бы изучить что-то вроде HDF5; Я не знаю, что такое поддержка .NET, но это хороший способ хранения общих данных.

0

Возможно, вы захотите использовать Microsoft Application Caching Application Block. Вы можете настроить его для использования IsolStorage в качестве хранилища резервных копий, поэтому элементы в кеше будут сериализованы на диск. Производительность может быть проблемой - я думаю, что из коробки она блокируется при записи, поэтому вам может потребоваться настроить ее вместо асинхронной записи.

0

в вашем случае memchached может охватывать некоторые проблемы с производительностью.

2

Я рекомендую создать класс, который имеет одну очередь с потоком для сброса изображений (gzipped) в конец файла, а затем сохранение смещений файлов/метаинформации в небольшую базу данных, такую ​​как sqlite. Это позволяет хранить все ваши файлы быстро, плотно, из нескольких потоков и считывать их обратно, эффективно и без необходимости иметь дело с любыми причудами файловой системы (кроме максимального размера файла), что может быть связано с наличием дополнительных метаданных.

File: 
file.1.gzipack 

Table: 
compressed_files { 
    id, 
    storage_file_id, 
    storage_offset, 
    storage_compressed_length, 
    mime_type, 
    original_file_name 
} 
Смежные вопросы