Организация данных в памяти эвм с использованием методов вычисления адреса по значениям ключей записей
Термин «методы вычисления адреса», известный как преобразование ключа в адрес, охватывает большую группу разработанных к настоящему времени методов поиска, которые начинаются с вычисления адреса по имени. Такие методы наиболее полно используют свойства памяти с произвольным доступом.
В методах вычисления адреса используется некоторая вычислительная операция, преобразующая значение ключа записи данных в соответствующий ему адрес памяти, т. е. реализуется адресная функция
Методы вычисления адреса подразделяют на две группы:
методы, в которых адресная функция реализует взаимно однозначное соответствие адресов и ключей;
методы перемешивания, в которых адресная функция реализует только однозначное преобразование ключа в адрес; обратное преобразование обычно не имеет места.
Методы первой группы.
Методы адресации с помощью ключа, эквивалентного адресу. Метод используется в случаях, когда такое преобразование возможно. Пусть в запись при ее поступлении в систему в качестве атрибута включается адрес памяти, с которого она размещается. В дальнейшем этот атрибут используется в качестве ключа. Например, адрес записи счета будет печататься в расчетной книжке клиента сберкассы и тогда при последующих обращениях к системе поиск записи счета клиента в БД осуществляется непосредственно по ключу-адресу.
Метод адресации с использованием алгоритма преобразования ключа в адрес. Метод предполагает линейную упорядоченность записей в файле, в котором выполняется адресация, и использование записей фиксированной длины. В соответствии с размером записей и характером их упорядоченности в файле составляют уравнение адресной функции, по которому преобразуются значения ключа записи в ее адрес в файле. Например, организуется файл для хранения данных о продаже авиабилетов. Схема записи файла: (НОМЕР-РЕЙСА, ДАТА-ВЫЛЕТА, НАЛИЧИЕ - СВОБОДНЫХ - МЕСТ) . Ключом являются атрибуты НОМЕР-РЕЙСА и ДАТА-ВЫЛЕТА. Путь атрибут НОМЕР-РЕЙСА принимает значения от01до50, атрибут ДАТА - ВЫЛЕТА - от 001 до 365. Размер записи - 20 байт. В этом случае адрес записи определяется выражениями:
где -относительный и машинный адреса; НР - значение атрибута НОМЕР-РЕЙСА; ДВ - значение атрибута ДАТА-ВЫЛЕТА;- базовый адрес, начиная с которого файл располагается в памяти.
При своей простоте данный метод имеет серьезный недостаток-малое заполнение памяти, отведенной для хранения файла. В файле остаются свободные участки памяти, если ключи не преобразуются в непрерывное множество адресов. В рассматриваемом примере это будет в случае, если не все рейсы выполняются ежедневно. В этом случае по целому ряду адресов записи будут отсутствовать. Рассмотренные методы адресации просты и обеспечивают наиболее высокую скорость поиска данных. Поэтому их чаще всего применяют в диалоговых системах, где время поиска критично.
В рассмотренных методах адресация выполняется в два этапа: вначале ключ преобразуется в относительный адрес (относительно начала файла), а затем относительный адрес преобразуется в машинный. Использование относительных адресов делает организацию данных более гибкой.
Методы второй группы. Методы перемешивания известны также под названием методов хеширования, методов рассеянной памяти, иногда их называют методами рандомизации.
Основная идея хеш-адресации заключается в том, что каждый экземпляр хранимой записи размещается в памяти по адресу, вычисляемому с помощью некоторой адресной функции - хеш-функции - по значению первичного ключа записи. В случае необходимости не обязательно организовывать записи в соответствии со значениями именно первичного ключа. Формально можно выполнять организацию записей по значениям любого из полей, входящих в состав записи. Все определяется конкретным приложением.
Таким образом, чтобы первоначально запомнить экземпляр записи, необходимо вычислить адрес хранения в памяти и поместить экземпляр по этому адресу. При поиске экземпляра записи выполняются те же самые вычисления и запись считывается из памяти по полученному адресу.
Рассмотренные выше методы первой группы, использующие числовое значение первичного ключа в качестве адреса хранимой записи (либо выполняющие взаимно однозначное преобразование значения ключа в адрес), можно использовать только для ограниченного круга приложений. В общем случае эти методы неприменимы потому, что диапазон значений первичного ключа обычно много шире диапазона адресов памяти, выделенных для хранения записей.
Если в рассмотренном выше примере предположить, что номера рейсов принимают значения от 0001 до 9999, а аэропорт, для которого создается информационная система, обслуживает не более 50 рейсов, то применение метода адресации с использованием алгоритма преобразования ключа в адрес невозможно из-за колоссальных издержек памяти.
Так как практически для хранения записей о рейсах требуется не более 50х365=18250 участков памяти по 20 байт (считаем, что рейсы выполняются ежедневно), то необходимо разработать специальную функцию адресации - хеш-функцию, которая переводила бы любое значение первичного ключа в диапазоне от 00010001 до 9999365 в значения из диапазона 0-18250. Чтобы учесть возможное расширение в будущем, последний диапазон обычно увеличивают на 20%.
Этот пример также иллюстрирует и недостатки хеш-адресации. Полученная с помощью хеширования последовательность расположения в памяти экземпляров хранимых записей обычно не совпадает с последовательностью, определяемой первичным ключом. Фактически хранимый файл с хеш-адресацией обычно рассматривают как неупорядочный по значениям ключа. Другой недостаток хеш-адресации - возможность коллизий. Под коллизией понимается такая ситуация, когда для двух различных записей (с разными значениями первичного ключа) вычисляется один и тот же адрес памяти для хранения этих записей. Для обработки коллизий разработаны специальные методы, рассмотренные ниже.
Хеш-функция. Хеш-функция h имеет не более М различных значении и удовлетворяет условию: т. е. для всего множества значений ключа и однозначно определяетМ по значению к.
В реальном файле может встретиться много групп записей с почти одинаковыми значениями ключей (окучивание значений). С другой стороны, между группами близких по значению ключей в реальном файле могут существовать большие по размеру «пустоты» в множестве значений ключа записей. Требуется, чтобы выбранная хеш-функция распределяла записи реального файла равномерно в пределах выделенного участка памяти. В этом случае можно ожидать уменьшения числа коллизий.
Таким образом, при подборе хеш-функции важен не тот факт, что хеш-функция равномерно распределяет все множество К значений ключа по выделенному участку памяти. Необходимо, чтобы хеш-функция равномерно рассеивала по выделенному участку памяти те подмножества значений К ключа, которые могут встретиться в реальном файле. Эти вероятные подмножества редко можно точно охарактеризовать, поэтому хеш-функции обычно строятся на основе правил, подчиняющихся здравому смыслу.
Любая рационально подобранная хеш-функция удовлетворительно работает на большинстве значений ключа. В то же время для любой хеш-функции существуют множества значений ключа, на которых она плохо работает. Поэтому на основании экспериментальных данных подбирают такую хеш-функцию, которая не склонна отображать скученные значения ключа в скученные адреса. Хеш-функция приемлема, если она свободна от указанного недостатка в интересующей области значений ключа, ее легко вычислить и она хорошо работает на контрольных данных при решении контрольной задачи. Чтобы быстро вычислить хеш-адреса, большинство хеш-функций реализуется несколькими простейшими операциями, которые на ЭВМ можно выполнить несколькими командами над двоичным представлением значений ключей и адресов.
Рассмотрим некоторые методы построения хеш-функций.
Метод квадратов. Метод состоит в том, что значение ключа представляется целым двоичным числом и затем возводится в квадрат. Далее из центральной части полученного результата выделяются l двоичных разрядов и интерпретируются как число соответствующее адресу памяти. При необходимости выравнивания полученного адреса к границам выделенного участка памяти данное число можно промасштабировать. Масштабирование выполняется умножением числа на подобранную (соответственно границам участка) константу.
Метод квадратов - это один из первых методов для построения хеш-функции. Для многих практических случаев он работает удовлетворительно. Однако если в реальном файле существуют многочисленные группы ключей, значения которых заканчиваются несколькими нулями, то метод может оказаться неприемлемым из-за большого числа случаев коллизий. Возведение в квадрат вдвое увеличивает количество нулей и эти нули могут распространяться на среднюю часть квадрата ключа, которая интерпретируется как адрес.
Метод, основанный на делении. Метод деления прост и дает хорошие результаты для реальных файлов, что выявлено на многочисленных проверках. Хеш-функция вычисляется по формуле: h(k)=k mod M, т. е. ее значение равно остатку от деления значения ключа на число М. Выбор числа М является решающим в этом методе. Если M - четное число, то значение h(k) всегда будет четным при четном k и нечетным при нечетном k. Если М равно степени основания системы счисления, применяемой в ЭВМ, то h(k) зависит только от самых правых разрядов k и не зависит от других. Если М кратно 3, то многие значения буквенных ключей, отличающиеся друг от друга лишь порядком букв, могут дать значения функции, разность между которыми кратна 3. Подобные свойства представляют серьезную потенциальную опасность возникновения большого числа коллизий. Поэтому в качестве М рекомендуется выбирать простое число, равное или близкое к размеру участка памяти.
Метод, основанный на умножении. Метод также прост и дает хорошие результаты. Он основан на следующем свойстве: если значения k равномерно распределены в отрезке [а, b], то и значения c*k равномерно распределены в отрезке[с·а, с·b]. Отрезок [с·а, с·b] отображается на пространстве адресов. В данном методе очень важен правильный подбор значения множителя c.
Рассмотренные выше хеш-функции предполагают, что значения ключей записей и все промежуточные вычисления не превышают машинных форматов представления числовых данных для используемой ЭВМ. Есть и другие типы хеш-функции.
Методам второй группы присуще возникновение коллизий. Хеш-функции могут порождать в некоторых случаях один и тот же адрес для нескольких различных ключей. Чтобы выйти из подобной ситуации, необходимо разработать метод разрешения коллизий. Пока память не слишком заполнена, например на 50%, коллизии возникают редко и производительность метода хеширования определяется в основном временем вычисления хеш-функции.. Однако по мере заполнения памяти все чаще возникают коллизии н итоговая производительность-метода все в большей степени зависит от производительности схемы разрешения коллизий.
Существует два способа построения схемы разрешения коллизий. Первый базируется на последовательном распределении списков и называется методом открытой адресации. Второй базируется на связанном представлении списков и называется методом цепочек.
1. Метод открытой адресации. Он состоит в том, что при возникновении коллизии просматриваются один за другим участки, отведенные для организации данных памяти, до тех пор, пока не будет найден свободный участок, куда и помещается запись. При выполнении поиска записи последовательность действий аналогична. Участки памяти просматриваются до тех пор, пока не будет найдена запись с интересующим нас значением ключа, либо пока не будет достигнута свободная позиция, что в данном методе является признаком отсутствия в файле записи с указанным значением ключа.
В данном методе обычно задается правило, согласно которому каждый ключ k определяет последовательность адресов в памяти которые необходимо просматривать каждый раз при вставке или поиске записи со значением ключа, равнымk. Если при выполнении операции поиска, используя определенную значением k. последовательность адресов , обнаружится свободная позиция, то это означает отсутствие записи в файле.
Существует несколько алгоритмов формирования последовательности адресов. Например, алгоритм, получивший название «линейное опробование». Алгоритм реализует циклическую последовательность адресов:
Основной недостаток метода открытой адресации - вторичное окучивание. Первичное окучивание возникает, когда таблица содержит много ключей с одинаковыми хеш-адресами. Вторичное окучивание возникает, когда имена с различными хеш-адресами имеют почти одинаковые последовательности адресов, так как эффект вторичного окучивания связан с работой алгоритма схемы разрешения коллизий. Чтобы избежать вторичное окучивание, принимают специальные меры. Например, в алгоритме «линейное опробование» формировать последовательность адресов с приращением (а не «1»). Приращение является в свою очередь функцией отk. Посколькуявляется другой хеш-функцией, алгоритм получил название «двойное хеширование».
2. Метод цепочек. Метод достаточно прост и состоит в том, чтобы организовать М связанных линейных списков по одному на каждый возможный хеш-адрес.
После хеширования ключа, если участок памяти по вычисленному адресу свободен, выполняется размещение записи по этому адресу. Если же участок памяти по вычисленному адресу занят, то происходит обращение по указателю к следующему участку памяти (элементу списка), и так до конца списка. После этого запись помещается на свободный участок памяти и с помощью указателей подсоединяется к концу своего списка. При поиске записей действия выполняются в той же последовательности. Вначале проверяется участок памяти по вычисленному адресу. Если там находится запись с другим значением ключа, то по указателю обращаются к следующей записи, и так до тех пор, пока не будет найдена необходимая запись либо достигнут конец списка. Память, выделяемую для организации списков, называют областью переполнения, а участок памяти с хеш-адресами - основной областью.
При организации данных на внешних устройствах с прямым доступом стремятся минимизировать число обращений к устройству, поэтому записи группируют в блоки, чтобы за один раз извлекать из внешней памяти несколько записей. С этой целью все адресуемое пространство памяти, выделенное для хранения файла, разбивается на блоки. Кроме того, выделяется несколько блоков памяти в специальной области переполнения. Вначале по алгоритму запись направляется в соответствующий основной блок памяти. Если же он заполнен, то запись направляется в свободный участок одного из блоков области переполнения. Адрес этого участка запоминается в исходном участке основного блока. Записи в области переполнения можно организовать методов; цепочек.
Число записей направляемых в область переполнения, зависит от плотности заполнения основных блоков. Чем выше плотность заполнения основных блоков, тем больше вероятность того, чтя вновь поступающие записи будут направлены в область переполнения.