Почему BLOB-поле - недополе, и как его сделать полем

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

  1. скачивание (с сервера, в т.ч. с СУБД);
  2. получение (от клиента, который отправляет его по собственной инициативе).

Перечислим, какие задачи они порождают, и предложим, как их решить.


Скачивание

Соединения иногда разрываются. Кроме того, может понадобится перезагрузить компьютер-получатель или выключить ноутбук-получатель. Таким образом, в поле нужно хранить:

  • внешний адрес BLOB'а для продолжения скачивания;
  • уже скачанную часть BLOB - и даже части, если СУБД может разделять удалённый BLOB на несколько частей (подобно обычным программам для скачивания, например "ReGet") и скачивать каждую часть через отдельное TCP-соединение;
  • смещения начала и конца каждой части для продолжения скачивания и сборки в единый BLOB.

И нам нужны операторы:

  • возвращающий BLOB;
  • возвращающий процент завершённости скачивания;
  • возвращающий адрес BLOB'а на удалённом сервере (вместо NULL'а, чтобы уведомить запрашивающего BLOB, что скачивание ещё не закончено, и уведомить, где можно получить BLOB до завершения скачивания или в случае, если СУБД будет разрушена);
  • запускающий скачивание в фоновом режиме (т.е. разрешающий выполнение следующих SQL-операторов в процессе скачивания) и сообщающий, запущено скачивание или нет


Получение

Мы не можем продолжить получение после разрыва TCP-соединения, после перезагрузки или выключения питания - мы можем только надеяться, что соединение не будет разорвано, компьютер не повиснет и что источник бесперебойного питания дотянет до конца передачи. Но если кто-нибудь попросит СУБД выдать этот BLOB в процессе получения, что СУБД должна ответить ему ? Отвечая NULL, она сообщит, что ничего не знает о BLOB'е, что является ложью, т.к. получение BLOB'а - это только вопрос времени.

Таким образом, мы видим, что поле должно хранить:

  • уже полученную часть BLOB;
  • значение "ACCEPTING", подобное NULL, но не равное ему.

Пусть третья база данных копирует BLOB-поле в себя в тот момент, когда наша база данных его ещё получает. Может ли третья база данных содержать значение "ACCEPTING"? Очевидно нет, т.к. это выглядело бы так, будто третья база данных сама получает BLOB. Таким образом, третья база данных дезинформировала бы своих пользователей и внушила бы им ложные надежды. Итак, нам нужно ещё одно значение, подобное NULL, например:

  • значение "NOTGOT"

в которое превращается "ACCEPTING". NOTGOT превращается в NOTGOT при копировании.


Оба случая

Следует заметить, что BLOB - это часто картинка, которая должна быть продемонстрирована в клиенте (например, в браузере). И было бы очень неудобно, если бы адрес содержал имя BLOB-поля (чтобы отличить его от других BLOB-полей), имя поля первичного ключа (чтобы указать запись) и имя таблицы1. И как записать такой адрес? Это будет совершенно не похоже на URL, кроме того, клиент совершенно не обязан знать SQL. Таким образом, мы видим, что:

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

должен быть помещён в BLOB-поле сразу, как только BLOB будет скачан или получен полностью. Помещение должно выполняться СУБД автоматически, без участия программиста2;

Вообще же BLOB - это файл, и как всякий файл, он имеет тип - jpg, mpg, и т.д. Файлы одних форматов содержат указание типа в самом начале файла, файлы других форматов - не содержат, и в этом случае тип должен храниться в BLOB-поле и копироваться из поля в поле при копировании BLOB'а3.

  • тип файла.


Резюме

Давайте подытожим: BLOB-поле должно быть способно содержать один из следующих наборов значений:

  • значение NULL

или

  • значение ACCEPTING
  • тип файла
  • одну часть (начало) BLOB'а

или

  • значение NOTGOT

или

  • идентификатор, уникальный во всей базе данных
  • тип файла
  • целый BLOB

или

  • URL4
  • тип файла
  • несколько частей BLOB'а
  • смещения начала и конца каждой части BLOB'а.

Операторы, упомянутые выше, будут выглядеть так:

  • "SELECT fieldname ..." - для извлечения BLOB'а
  • "SELECT ID(fieldname) ..." - для извлечения идентификатора BLOB
  • "... WHERE fieldname=542" - для указания записи по идентификатору BLOB, равному 542
  • "SELECT PERCENT(fieldname) ..." - для извлечения процента завершённости скачивания
  • "SELECT TYPE(fieldname) ..." - для типа BLOB'а5
  • "SELECT DOWNLOAD(fieldname) ..." - для запуска скачивания в фоновом режиме и для информирования, запущено скачивание или нет (т.е. возвращает Y/N)
  • "SELECT STOP(fieldname) FROM * WHERE fieldname=542" - для остановки скачивания BLOB'а с идентификатором, равным 542


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

Дмитрий ТЮРИН,
главный специалист департамента ЦАБС "АСБ Беларусбанк"

  1. Предполагаем, что имя схемы объединено вместе с именем таблицы в один токин
  2. Было бы очень глупо, если бы программист должен был создавать последовательность для BLOB'ов и по триггеру для каждого BLOB-поля в базе данных
  3. Хорошо, если бы СУБД понимала большое количество форматов и исправляла бы тип файла в BLOB-поле на значение из содержимого файла
  4. Вида "site.com/~dbowner/dbname/identifier" или "111.222.333.444/~dbowner/dbname /identifier"
  5. Знать тип BLOB'а нужно, только чтобы отобрать BLOB'ы для конвертирования из одного формата в другой. При пересылке BLOB'а его тип отдельно запрашивать не надо, т.к. он обязан автоматически извлекаться вместе с BLOB'ом, например (проприетарный формат передачи данных конкретной СУБД для удобства его визуализации записан в XML-виде, подробности этой записи и вариант её возможного транспортного использования представлены на слайдах #141-143 презентации sql50.euro.ru/sql5.17.0.pdf)
    <tablename fieldname1= fieldname="3652435"/>
    <?file value="3652435" type="mpg" size="3">Y29</?file>
    BLOB'ы передаются не в xml-атрибуте, а после всех xml-элементов. Иначе бы они блокировали реакцию получателя на быстро передаваемые неBLOB атрибуты.
Версия для печатиВерсия для печати

Номер: 

07 за 2009 год

Рубрика: 

Software
Заметили ошибку? Выделите ее мышкой и нажмите Ctrl+Enter!

Комментарии

Страницы

Аватар пользователя mr
>>>>>

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

<<<<<

я думаю надо помочь крупнейшему банку страны в понимании вопроса.

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

Аватар пользователя Колесников А.
Автор поднял интересную проблему и написал очень интересную статью. Прочитал три раза.
Аватар пользователя Ваши имя, фамилия
Я в шоке.
Аватар пользователя mike
Сорри за тупой вопрос: автору это нужно для того, чтобы работать с чужой БД?
Аватар пользователя WindWalker
Очень понравилось значение негот. Так держать, аффтар!

PS. Интересно, а беларусбанке есть вменяемые специалисты в написании ПО или это эффект главного специалиста ?

Аватар пользователя al
А главный редактор как такое вообще пропустил? там статьи вообще читают перед публикацией? ))))
Аватар пользователя asd
Какой банк, такой и главный специалист.
Аватар пользователя Developer
IMHO, в качестве базы данных для хранения файлов пока что более целесообразно использовать файловую систему, а не SQL DB.

Cтатья, знаете, как-то уж очень пугает. Скажите, Беларусбанк вообще собирается переходить на открытый стандард Unix (FreeBSD, Linux) ? Что у вас там вообще творится ? Мы сейчас ведёмся на пиар технологий, чтоб в конечном итоге превратиться в дойную корову Билла Гейтса? Или всё же ищем менее распиаренные, но зато наиболее эффективные и к тому же ещё бесплатные и открытые решения?

В общем, можете для начала установить lighttpd - сверхбыстрый сервер, производительность отдачи статики значительно выше чем Apache. Кстати, на нём работает Youtube.

Советую писать на С++ с помощью wxWidgets, Qt (эти мощные кроссплатформенные библиотеки абсолютно бесплатны для разработчиков закрытого коммерческого ПО, и там есть уже готовые database layers). Вместо PHP можно ещё пробовать использовать FastCGI - не пугайтесь, там всё просто, учится это дело вообще за 2 дня, только предупреждаю, такие системы мало кто пиарит, это не выгодно ни монстрам типа Microsoft, ни 1С, ни Sun, и ни тем кто кормится за счёт этих монстров.

Аватар пользователя Developer
Если кто-то не знал: Qt c марта этого года переходит на лицензию LGPL. Эта лицензия позволяет закрывать исходный код при динамической линковке.
Аватар пользователя Колесников А.
...перечитал стать еще пару раз:))) общее мнение поддерживаю....

Страницы