Разделители и обозначения единиц

В базах данных результаты измерений хранятся в двоичном формате, но при вводе и выводе этих данных человек ожидает увидеть их в виде читаемых символов и разделителей. Перед числовыми данными, после них и даже посреди может стоять явное или неявное обозначение единицы измерения.
Если я напишу $25,15, вы поймете, что в качестве единицы измерения использован доллар — на это указывает символ, стоящий перед числом. В записи “160 кг” сокращенное обозначение единицы — килограмма — стоит после числа. Строка “12 марта 1989 г.” очевидно представляет собою дату — на это указывают название месяца, пробелы и сокращенное обозначение года. Однако вы без труда распознаете дату и в строке “12.03.1989”.
В базах данных разделители, как правило, не хранятся. Исключение составляют нестандартные типы данных MONEY и CURRENCY, имеющиеся во многих реализациях SQL Разделители и единицы нужны лишь для отображения данных, поэтому их хранение в самой БД представляет собой напрасный расход ресурсов. Можно, конечно, разместить обозначения единиц в отдельном столбце по соседству со столбцом с числовыми данными, но такая таблица будет выглядеть неуклюже. Если все числа выражены в одних и тех же единицах, специальный столбец для них не нужен. Если числа выражены в разных единицах, перед проведением вычислений вам все равно придется привести их к единой шкале. Почему бы не соблюсти единство с самого начала? По миру ходит немало страшных историй о том, как в международных компаниях с отделениями в США и Европе перепутывались английская и международная системы мер, что приводило к различным печальным последствиям.
В идеале администратор должен обеспечить внутреннее единство единиц измерения во всей базе данных. Если без использования различных единиц не обойтись, их можно показывать пользователю посредством представления, в котором будут спрятаны все необходимые преобразования. При этом офис в США увидит данные в английских единицах, а офис в Европе — в единицах СИ, и никто не узнает, что перед выводом данные как-то преобразуются.

Рекомендации по использованию шкал в базах данных

В этом разделе приведены общие рекомендации по использованию шкал в БД. Не стоит воспринимать их как жесткие правила — у всех у них есть исключения.
1. Как правило, чем шире круг возможных преобразований шкалы, тем ограниченнее возможности ее статистической обработки.По измерениям в шкале отношений можно вычислить практически любую статистику. К измерениям в шкале наименований статистика почти не применима.
2. С помощью конструкций СНЕСК() в объявлении таблицы обеспечьте включение в БД только допустимых значений.Если ваш SQL-продукт допускает создание доменов из стандарта SQL-92, используйте эту возможность для создания шкал. У шкал наименований имеется список допустимых значений; у других шкал можно проверять диапазон. С помощью конструкции DEFAULT обязательно задавайте значениепо умолчанию — начальную точку шкалы, NULL или другое.
3. В десятичных дробях задавайте на одну цифру после запятой больше, чем требуется для представления данных.В большинстве реализаций SQL ошибки округления уменьшаются при увеличении количества цифр после запятой. К сожалению, точность представления чисел и правила округления меняются от реализации к реализации, поэтому один и тот же запрос на разных продуктах может давать немного различающиеся результаты. С другой стороны, в отличие от многих старых систем SQL более милосерден: он позволяет администратору изменять параметры числового столбца (точность и диапазон) безпотери существующих данных и запросов. Для отображения большегоколичества цифр могут понадобиться изменения в хост-программе.
При работе с валютами вам, возможно, придется поближе познакомиться с законами и бухгалтерскими правилами. В Евросоюзе имеются собственные правила по расчетам в евро, в США — по расчетам в долларах.
4. По возможности храните в БД данные в основных единицах. Это не всегда возможно, поскольку зачастую в результатах измерения фигурируют только производные единицы. Взгляните на манометр насоса, которым вы накачиваете шины: он проградуирован в Паскалях (ньютонах на квадратный метр), и вы не сможете разделить его показания на ньютоны и квадратные метры. Никогда не храните в одной и той же таблице и основные единицы, и вычисляемые по ним производные единицы. Это не только напрасный расход памяти, но и источник возможных ошибок: если вы, обновив столбец с основными единицами, забудете пересчитать столбец с производными единицами. Кстати, на большинстве компьютеров пересчет производных единиц идет гораздо быстрее, чем их считывание с диска.
5. Придерживайтесь одних и тех же обозначений и единиц. В частности, не смешивайте формат даты ISO и ANSI, не выражайте длину то в метрах, то в сантиметрах. В идеале, во всех приложениях данные должны выражаться в одних и тех же единицах.





ГЛАВА 5.
Схемы кодировки данных

Никто не записывает данные сразу в БД. Сначала их соответствующим способом кодируют и лишь затем помещают в столбец. Слова принадлежат к определенному языку и составляются из букв; данные измерений записываются числами. Правда, к буквам и числам мы настолько привыкли, что уже не рассматриваем их в качестве кодов. Часто мы также не задумываемся о том, что одну и ту же сущность или свойство можно идентифицировать (и, следовательно, закодировать) различными способами. Как обозначить пациента больницы — именем или номером медицинского страхового полиса? Это может зависеть от того, для кого предназначается база данных — для врача или для страховой компании. Как идентифицировать песню — по названию, по позиции в альбоме или обоими способами? Или стоит включить в БД мелодию — в виде нот или в виде файла мультимедиа? Никто не обучает программистов составлению схем кодировки, поэтому зачастую они составляются “на лету”. Причем во многих случаях самодельной схеме отдается предпочтение даже при наличии общепринятого стандарта кодирования. Начинающие программисты считают, что о разработке схемы кодировки они вообще заботиться не должны — это дело компьютера, пусть он и разбирается. С появлением SQL такое отношение только укрепилось благодаря иллюзии, что любые ошибки проекта можно позже исправить с помощью оператора ALTER.
Да, компьютер способен решить множество проблем, но программы для ввода и проверки данных очень сложны и трудны в обслуживании. Запросы к базам данных с замысловатыми схемами кодировки сложны в разработке и ресурсоемки в исполнении. При этом рано или поздно разбираться с кодированием все равно придется человеку. Неудачные схемы кодировки обязательно приводят к неверному вводу и выводу и в конце концов становятся причиной появления некорректной модели данных.

Плохие схемы кодировки

В качестве примера рассмотрим систему учета автомобилей в одном южном штате. Она начиналась, как система с перфокартами, написанная на Коболе. Большинство читателей, вероятно, слишком молоды, чтобы помнить перфокарты. Напоминаю: перфокарта — это лист жесткой бумаги, на котором двоичному представлению символов соответствует набор пробитых и непробитых позиций. Возможные позиции для отверстий выстроены в 80 вертикальных колонок, каждая из которых используется для кодирования одного символа — отсюда фиксированная длина строки. Перфокарты пробивались на специальном устройстве с клавиатурой наподобие клавиатуры пишущей машинки: по мере того как оператор набирал текст, устройство автоматически меняло перфокарты.
В исходной системе учета автомобилей на каждой карточке выделялась одна колонка для одноразрядного кода типа автомобиля: частный, с наемным шофером, такси, грузовик, маршрутный автобус и т.п. Шло время, и в систему добавлялись новые типы — для ветеранов различных войн, для университетских выпускников, в общем, для любой группы лоббистов, которая обладала достаточной политической властью, чтобы пробить себе право на специальный номерной знак.
Скоро количество типов превысило 10, и одноразрядной системы для них хватать перестало. Место для добавления еще одного разряда на перфокартах было, но в Коболе используются поля фиксированной длины, и потому изменение разметки карты было невозможно без корректировки программ и настройки перфорирующих устройств.
Поначалу проблема была решена следующим образом: оператор вместо цифры вводил знак препинания, расположенный на одной с цифрой клавише. Сначала в схему попал один знак препинания, за ним другой, и вскоре в системе кодов были все символы, соответствующие верхнему ряду клавиш на клавиатуре.
К несчастью, размещение знаков препинания на клавиатуре менялось от устройства к устройству, поэтому перед обновлением базы данных для каждого набора перфокарт приходилось разрабатывать специальную программу для преобразования раскладки к оригинальным кодам модели IBM 026. Такая практика продолжалась даже тогда, когда все эти устройства переместились в свой механический рай.
Просто контролировать попадание кода в заданный числовой диапазон было нельзя. Приходилось использовать простую программу, которая проверяла совпадение вводимого кода с более чем 20 допустимыми значениями. Звучит как будто не очень внушительно, но учтите — за один только квартал система должна была обработать более трех миллионов записей.
При этом нужно было еще помнить, на какой именно машине создана данная запись. Естественно, количество ошибок было очень велико. Если бы код с самого начала сделали двухразрядным (от 00 до 99), никаких проблем не возникло бы. Если бы я создавал эту систему сегодня, я бы просто завел для номера столбец типа INTEGER и мог бы себе позволить столько номеров, сколько понадобится.
О втором примере сообщило в 1987 г. издание Information Systems Week. Собственно, вся история была заключена в первом предложении: “По-видимому, хаос и огромное число ошибок в работе новой системы управления соцобеспечением Нью-Йорка связаны с чрезмерным увеличением количества кодов, необходимых для ввода данных, и с вытекающей из этого сложностью обучения операторов”. В остальной части статьи рассказывалось о попытке объединить в новой системе несколько старых. В результате слияния количество ошибок возросло с 2 более чем до 20%, поскольку толком слить имевшиеся схемы кодировки так и не удалось.
Как при встрече распознать плохую схему кодировки? Один из характерных признаков — отсутствие возможности расширения. Поговорите с кем-нибудь, кому приходилось переконфигурировать систему с записями фиксированной длины при переходе от старых к новым почтовым индексам. Физически в SQL такой проблемы нет, но она может проявиться на логическом уровне.
Другое свойство плохих схем — неоднозначные коды. Наверное, самый забавный случай связан с попыткой ввести в итальянскую телефонную систему “службу точного времени”. Для нее был подобран трехзначный телефонный номер, совпавший с междугородным кодом Милана, в результате чего никто не мог дозвониться в Милан, не узнав попутно, который час.
Такие вещи происходят чаще, чем кажется, причем наиболее типичная форма ошибки — слишком вольная трактовка кода, соответствующего случаю “Другое”. Очень разные случаи кодируются как идентичные, и в результате выполнения запроса пользователь получает некорректную информацию.
В плохой схеме кодировки нет кодов для отсутствующих, неизвестных, неприменимых или неклассифицируемых значений. В классической истории рассказывается о человеке, который ради шутки зарегистрировал для своей машины номерной знак “NONE” и вскоре получил по почте тысячи штрафных квитанций. В дорожной полиции не было специального кода для случаев, когда на квитанции не указан номер машины, и потому в поле для номера они писали просто “none” (нет). Как только в БД появился номерной знак этого несчастного, СУБД зарегистрировала совпадение и отправила на его адрес все неоплаченные квитанции, в которых отсутствовал номер автомобиля.
Вы, вероятно, скажете, что в SQL эту проблему легко решить с помощью значения NULL? Увы, к сожалению, во многих функциях SQL оно игнорируется. SQL-запрос:

SELECT tag_nbr, SUM(fme)

FROM tickets

GROUP BY tag_nbr;

предназначенный для выдачи суммы штрафов для каждого автомобиля, сгруппирует все записи, не содержащие номера, и выдаст полную сумму для этой группы, словно эти записи относятся к одной машине. Но вам, скорее всего, хотелось бы видеть информацию по каждому такому случаю в отдельности, потому что вряд ли во всей Калифорнии отыщется всего один автомобиль без номера.
Имеются также небольшие, но существенные различия между пропущенными, неизвестными, неприменимыми, неклассифицируемыми и ошибочными значениями. Например, в международной классификации заболеваний код 999 999 применяется для неклассифицируемой болезни, то есть, болезни, наличие которой у пациента сомнений не вызывает, но диагностировать которую не удается. Это безрадостное состояние, конечно, отличается от отсутствующего кода заболевания (пациент только что пришел в больницу, может быть, даже и не болен), неприменимого кода (осложнения беременности для мужчины), неизвестного кода (болен, ожидает результаты анализов) или ошибочного кода (в графе для температуры пациента значится 100°С).

Типы схем кодировки

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

Перечисляющая кодировка

Перечисляющая кодировка состоит в упорядочении значений атрибута и последующем присвоении каждому значению числа или буквы. Числа обычно предпочтительнее букв, поскольку при добавлении новых значений их можно увеличивать безгранично. Перечисляющие схемы хороши для коротких списков, по по мере увеличения длины их эффективность падает.
Запомнить длинный список кодов сложно, да и упорядоченность с добавлением новых значений, скорее всего, будет нарушена. Упорядочивать значения лучше всего на основе их естественного чередования, если такое имеется. Это может быть хронологический порядок (1 случилось раньше, чем 2) или порядок выполнения (1 необходимо сделать раньше, чем 2). Иногда используют такой порядок: сначала часто встречающиеся значения, потом — реже встречающиеся значения. Наиболее частым случаям можно присвоить коды покороче. Уместны списки, упорядоченные по физическим характеристикам (масса, цвет и пр.).
Высказавшись в пользу естественного упорядочения, я должен признать, что гораздо чаще в реальной жизни встречается алфавитный порядок, поскольку его легче реализовать на компьютере. В стандарте ANSI X3.31, например, имена округов США сначала выстроены по алфавиту (отдельно в каждом штате), а затем пронумерованы.

Кодировка единиц измерения

Эта кодировка обозначает единицы измерения — фунты, метры, вольты, литры. Как правило, единица измерения не записывается в столбец, а просто подразумевается, но может присутствовать в нем и в явном виде. Последнее часто происходит с “денежными” столбцами, в которые подставляется символ доллара, фунта, йены и пр.
Подробнее о шкалах и измерениях — в главе 4.

Кодировка аббревиатурами

Сокращения нужны, чтобы сэкономить пространство, занимаемое значением атрибута, но вместе с тем сохранить его понятность. Аббревиатура может быть как переменной, так и постоянной длины, но компьютерщикам, конечно, ближе второй вариант. В качестве примера взгляните на двух-буквенные обозначения штатов (СА — Калифорния, AL — Алабама), которые пришли на смену сокращениям переменной длины (соответственно, Calif, и Ala.).
Добротная система аббревиатур очень удобна, но по мере роста количества кодируемых значений повышается вероятность путаницы. Трехбуквенные коды больших аэропортов еще можно запомнить: LAX — Лос-Анжелес, SFO — Сан-Франциско, SVO — Шереметьево, но разобраться с кодами небольших аэропортов гораздо сложнее.
Еще один пример — стандартные коды стран ISO-3166, которые могут быть двухбуквенными, трехбуквенными или числовыми. Их поддерживает сетевой координационный центр RIPE.

Алгоритмические коды

Алгоритмическая кодировка заключается в создании кода из значения по определенному алгоритму. Алгоритм должен быть обратимым, чтобы из кода можно было восстановить исходное значение. Хотя это и не обязательно, код обычно бывает короче (по крайней мере, его размер ограничен сверху) и упорядоченнее исходных значений. Наиболее типичным видом алгоритмического кодирования является шифрование — очень важный процесс, заслуживающий отдельного рассмотрения.
В астрономии используется алгоритмическое кодирование дней — так называемая юлианская дата, которая представляет собой количество дней, прошедших с определенного дня (1 января 4713 г. до н. э.) в далеком прошлом. Юлианский день фактически есть преобразование даты в целое число. Для более приземленных целей удобна упрощенная юлианская дата — количество дней, прошедших с начала года. Она, очевидно, заключена в пределах от 1 до Зб5 или 366. Применение алгоритма требует компьютерного времени как на вводе, так и на выводе данных, но кодирование, как правило, окупает эти затраты, так как позволяет легко осуществлять поиск и расчеты, которые были бы невозможны с исходными данными.
Другой пример — хэш-функции, которые преобразуют одни численные значения в другие, предназначенные для хранения. Вариантом алгоритмической кодировки можно также считать округление чисел перед помещением в БД.
Разница между аббревиатурой и алгоритмом не особенно четкая. Сокращение можно считать особым случаем алгоритма, описывающим удаление или замену букв. Чтобы все-таки разделить их, обращайте внимание на следующие признаки
1. То, что легко понимается человеком, является аббревиатурой.
2. Результат алгоритмического кодирования легкому пониманию не поддается.
3. Алгоритмическое кодирование может возвращать один и тот же код для нескольких значений. Аббревиатура всегда однозначна.

Наши рекомендации