Добавил:
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Базы и банки данных / Базы и банки данных (5 сем).doc
Скачиваний:
76
Добавлен:
01.05.2014
Размер:
705.54 Кб
Скачать

Хеширование

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

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

  • Для сохранения записи в СУБД сначала вычисляется хеш-адрес новой записи, а затем диспетчер файлов помещает эту запись по вычисленному адресу.

  • Для извлечения нужной записи по заданному значению хеш-поля в СУБД сначала вычисляется хеш-адрес, а затем диспетчеру файлов посылается адрес для извлечения записи по вычисленному адресу.

Простейшим примером хеш-функции может служить остаток от деления на подобранное простое число значения, содержащегося в хеш-поле.

Хеширование отличается от индексирования тем, что в файле может быть любое количество индексов, но только одна структура хеширования.

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

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

Задание

Пусть значениями хеш-поля являются числа 100, 200, 300, 400, 500. Используя для вычисления хеш-адреса остаток от деления на 13, получить хеш-адреса и показать схематично размещение записей при таком хешировании.

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

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

Итак, пусть в качестве функции хеширования h используется остаток от деления на 13. Например, применение этой функции к целочисленным значениям в поле первичного ключа дает:h(39)= 0;h(62)= 10;h(5)=5. Данная функция хеширования позволяет получить значения в диапазоне от 0 до 12, идентифицируя тем самым 13 блоков. Пусть в каждый блок можно поместить 8 записей. Тогда, если файл содержит 72 записи, пространство, выделенное для его хранения, будет на две трети заполнено данными.

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

Чтобы включить в файл новую запись, нужно с помощью линейного поиска в блоке, номер которого определяется значением h, найти запись с истинным значением поля НЕТЗАПИСИ. После этого на место найденной записи надо поместить новую. В том случае, если при попытке поместить новую запись в файл обнаруживается, что в найденном блоке нет записи с НЕТЗАПИСИ=TRUE, говорят, что блок переполнен. Несколько позже будет описана реакция на переполнение.

Для удаления записи из файла надо, используя метод линейного поиска, попытаться обнаружить ее в блоке, номер которого равен h(значение первичного ключа). Если запись будет найдена, то нужно установить НЕТЗАПИСИ =TRUE; еслинет, то очевидно, что блок переполнен и необходимо продолжить поиск. Отметим, что перед тем как заполнить файл записями, необходимо установить НЕТЗАПИСИ =TRUEдля всех записей всех блоков.

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

Переполнение

Для борьбы с переполнением могут быть использованы три метода: связанных в цепь блоков; связанных в цепь записей и прогрессирующего переполнения.

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

Основной недостаток метода блоков, связанных в цепь, заключается в том, что блоки переполнения часто оказываются заполненными только несколькими записями, а оставшаяся в них память тратится впустую. Для устранения этого недостатка можно использовать один блок переполнения для всех записей, не обращая внимания на то, в какой блок они попали. Когда и этот блок переполняется, используется еще один блок и т.д. Записи, имеющие одинаковые значения функции хеширования и попавшие в блоки переполнения, объединяются в связанный список. Тот блок, который изначально предназначен для хранения записей с одинаковыми значениями функции хеширования и попавшие в блоки переполнения, объединяются в связанный список. Тот блок, который изначально предназначен для хранения записей с одинаковыми значениями функции хеширования, в случае переполнения должен содержать указатель на начало связанного списка записей, находящихся в блоках переполнения. Для поиска записи в файле с такой организацией. Необходимо сначала произвести линейный поиск в блоке, номер которого определяется значением функции хеширования для этой записи; если искомая запись не обнаружена, необходимо, воспользовавшись указателем, находящемся в блоке, просмотреть связанный список записей в блоках переполнения.

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

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

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

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

Функции хеширования

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

Выбор функции хеширования осуществляется в некотором смысле произвольно. Для выбора "хорошей" функции хеширования необходимо знать, вопервых, примерное число записей в файле и, вовторых, сколько записей можно помещать в блок. Эта информация будет использоваться для подсчета числа блоков в файле, на основании которого можно определить диапазон изменения значений функции хеширования. Если для файла будет отведено слишком мало блоков, то эффективность доступа будет уменьшаться по мере переполнения этих блоков. Если, наоборот, для размещения файла будет предусмотрено много блоков, то переполнение блоков будет происходить редко и, следовательно доступ будет осуществляться быстро. Значительная часть памяти в этом случае останется не занятой данными. Будем стремиться к золотой середине, т.е. считать, что примерно две трети блоков должны быть заняты данными.

Функция хеширования должна быть выбрана таким образом, чтобы максимально удовлетворять следующим условиям:

  • Каждое ее значение должно быть целым из интервала 0..число блоков в файле 1

  • Она должна быть удобной для вычисления, т.е. определение значения функции хеширования должно происходить быстро

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

Если h(<значение первичного ключа>) полностью удовлетворяет последнему условию, то говорят, чтоhперемешивает значения ключа. Перемешивание позволяет добиться того, чтобы все блоки содержали примерно одинаковое число записей. Если условие перемешивания не выполняется, то часть блоков может переполняться, в то время как другие блоки будут содержать лишь небольшое число записей, и в результате эффективность доступа может оказаться ниже, чем при использовании перемешивания.

Заметим, что любому ключу (не только числовому) можно сопоставить численное значение. Например, буквы можно интерпретировать как целые числа в диапазоне 0…33, т.е. А = 0, Б = 1 и т.д. Тогда числовое значение БВ53 будет равно (1*33*33 + 2*33)*100 +53.

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

Непригодность файлов с хеш-адресацией к групповой обработке

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

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

Типичным примером, в котором коэффициент активности близок к единице, является вычисление зарплаты при обработке платежных ведомостей: каждая (или почти каждая) запись в файле обрабатывается.

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

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

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