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

StackOverflow https://stackoverflow.com/questions/1257415

Вопрос

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

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

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

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

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

Это было полезно?

Решение

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

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

Существуют аргументы с обеих сторон сохранения файлов в базе данных.

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

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

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

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

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

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

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

sf394fgr90rtfofrpo98tx.pdf

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

DELETE FROM BLOBTABLE WHERE NAME LIKE '<whatever>'

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

DELETE FROM BLOBTABLE WHERE CREATIONDATE < ...
etc...

Вопрос:

Почему эти документы необходимо создавать и хранить в формате PDF?

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

1) Это полностью противоречит тому, что я обычно проповедую, но вы можете захотеть сохранить их в базе данных SQL, поскольку это действительно небольшие файлы.SQL Server также позволил бы вам быстро и легко находить нужные вам файлы без какого-либо сумасшедшего разгрома диска, обычно связанного с перечислением такого большого каталога. Кроме того, хранение файлов в SQL (хотя я обычно против) значительно упростило бы процесс резервного копирования / восстановления.

2) Храните их все в каталогах и либо индексируйте их с помощью службы индексирования Windows (дрожит) или создайте свой собственный индекс в SQL Server, который содержал бы имя файла и полный путь.Я бы предложил хранить их в отдельных каталогах, всего по несколько десятков тысяч файлов в каждом.Возможно, вы могли бы использовать год заказа в качестве названия папки?

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

Надеюсь, это поможет!

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

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

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

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

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

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

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top