Лучший способ хранить / извлекать миллионы файлов, когда их метаданные находятся в базе данных SQL - PullRequest
8 голосов
/ 11 августа 2009

У меня есть процесс, который первоначально генерирует 3-4 миллиона файлов PDF, и продолжается со скоростью 80K / день. Они будут довольно маленькими (50 КБ) каждый, но меня беспокоит то, как управлять общей массой файлов, которые я генерирую, для удобства поиска. Некоторые детали:

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

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

  1. С одной папкой все в порядке? Файлы никогда не будут перечислены - они будут получены только с помощью System.IO.File с именем файла, которое я уже определил.
  2. Если я создаю папку, могу ли я наблюдать за новыми файлами с System.IO.DirectoryWatcher, даже с таким количеством файлов, или он начнет медленно работать с таким количеством файлов?
  3. Должны ли они храниться в виде больших двоичных объектов в базе данных SQL Server? Поскольку мне нужно получить их по справочному значению, возможно, это имеет больше смысла.

Спасибо за ваши мысли!

Ответы [ 12 ]

5 голосов
/ 11 августа 2009

Чтобы ответить на ваши вопросы:

  1. Я бы не стал хранить их в одной папке. Так как шансы в какой-то момент у вас захочет посмотреть реальные файлы на диске, а не как-то иначе.
    Вместо этого, почему бы не хранить их в отдельных каталогах, разбитых на партии по 1000? Возможно использование идентификатора в качестве ключа.
  2. Это множество файлов, вероятно, затопит DirectorWatcher, поэтому некоторые будут потеряны. Я использовал это в прошлом, и после определенного момента (несколько сотен) я обнаружил, что он начинает пропускать файлы. Возможно, используйте другой каталог для входящих файлов, а затем обрабатывайте это очень часто. Это может затем запустить процесс для обновления оригинала.
  3. Я не буду хранить документы в базе данных, но определенно сохраню метаданные в базе данных.
3 голосов
/ 11 августа 2009

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

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

sf394fgr90rtfofrpo98tx.pdf

Затем разбейте это на блоки из двух символов, и вы получите это:

sf/39/4f/gr/90/rt/fo/fr/po/98/tx.pdf

Как видите, оно дает вам глубокое дерево каталогов, по которому вы можете легко перемещаться.

При хорошей хэш-функции она будет распределена очень равномерно, и вы никогда не получите более 1296 записей на каталог. Если вы когда-нибудь столкнулись (что должно быть крайне редко), просто добавьте число в конец: tx.pdf, tx_1.pdf, tx_2.pdf. Опять же, столкновения с такими большими хэшами должны быть крайне редкими, так что возникающие из-за этого сгустки не являются проблемой.

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

3 голосов
/ 11 августа 2009

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

Файлы устаревают и удаляются? Если это так, сортировка и файл будет удаляемым куском. Если нет, могу ли я быть вашим поставщиком оборудования?

Есть аргументы с обеих сторон о хранении файлов в базе данных.

  • С одной стороны, вы получаете повышенную безопасность, потому что более неудобно извлекать файлы из БД; с другой стороны, вы получаете потенциально более низкую производительность, потому что более неудобно извлекать файлы из БД.
  • В БД вам не нужно беспокоиться о том, сколько файлов в папке, секторе, кластере NAS и т. Д. - это проблема БД, и, вероятно, у них есть хорошая реализация для этого. С другой стороны, будет сложнее управлять / просматривать данные, так как это было бы миллиардами капель в одной таблице, и, ну, черт. (Вы можете разделить таблицу на основе вышеупомянутой бизнес-логики, что сделает процесс удаления или архивирования бесконечно проще. Это или, может быть, разделенные представления, так как разделение таблицы имеет ограничение в 1000 разделов.)
  • SQL Server 2008 имеет тип данных FileStream; Я не знаю много об этом, возможно, стоит разобраться.

Последнее, о чем нужно беспокоиться, это сохранение данных "выровненными". Если БД хранит информацию о файле вместе с путем / именем к файлу, и файл перемещается, вы можете полностью скрыться.

2 голосов
/ 11 августа 2009

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

Просто имейте в виду, что если вы используете идентификаторы заказов, вы можете получить http://en.wikipedia.org/wiki/Benford%27s_law

1 голос
/ 24 августа 2011

При использовании базы данных для хранения ваших файлов, особенно с небольшими файлами, накладные расходы должны быть небольшими. но вы также можете делать такие вещи, как:

DELETE FROM BLOBTABLE WHERE NAME LIKE '<whatever>'

или когда у вас есть срок действия или вы хотите обновить файл, вы удаляете его:

DELETE FROM BLOBTABLE WHERE CREATIONDATE < ...
etc...
1 голос
/ 11 августа 2009

Почему бы не подумать о сохранении всех этих файлов после преобразования в PDF в БД (blob) Отсюда и преимущества:

  1. Полагаю, вам не придется иметь дело с операциями ввода-вывода операционной системы и оставить все до БД.
  2. Нет необходимости хэшировать
  3. Простота резервного копирования и обслуживания
1 голос
/ 11 августа 2009

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

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

Если файловая система индексирует каталоги (например, btree или просто сортирует их внутри, что в данном контексте фактически одно и то же), то размеры каталогов менее важны, хотя некоторые инструменты могут жаловаться (загрузка Окно Windows Explorer с файлами 4M, кто знает, что будет).

Итак, я изучу вашу запланированную операционную систему и параметры файловой системы, протестирую ее и выясню, какая из них лучше всего подходит для вас.

1 голос
/ 11 августа 2009

Определите логический порядок подкаталогов и сохраните их в блоках, содержащих не более 512 файлов в папке.

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

0 голосов
/ 11 августа 2009

Я думаю, как и многие другие говорили, вы должны делать подпапки, но таким образом, чтобы вы могли найти данные с помощью кода. Например, если работает datetime, используйте это. Из прочтения того, что вы сказали, может показаться, что в отчетах есть какая-то форма иерархической структуры (ежедневный, еженедельный, ежедневный отчет X, ежечасный отчет Y и т. Д.), И я посмотрю на структуру того, когда и почему отчеты создаются и создаются мои каталоги таким образом.

0 голосов
/ 11 августа 2009

Моя файловая база данных содержит более 4 миллионов папок, в каждой папке много файлов.

Просто бросил все папки в одну директорию. NTFS может справиться с этим без каких-либо проблем, а передовые инструменты, такие как robocopy, могут помочь, когда вам нужно переместить его.

Просто убедитесь, что вы можете индексировать файлы без сканирования. Я сделал это, бросив свой индекс в базу данных mysql.

Таким образом, чтобы получить файл, я ищу в базе данных mysql некоторые метаданные и получаю индекс. Затем я использую этот индекс для непосредственного чтения файла. До сих пор хорошо для меня. Но обратите внимание, что вы будете превращать все в произвольный доступ и, следовательно, в случайное чтение / запись. Это плохая производительность для HDD, но, к счастью, SSD очень поможет.

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

...