Эта страница переведена машинным переводом. Читайте английский оригинал. English

Библиотека IBSurgeon

Различия между полями VARCHAR и INTEGER в ключах

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

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

Одиночное поле ключа сначала преобразуется в один из трех канонических типов: строка с collation, double precision и (к сожалению) 64-битное целое. Даты становятся числами с плавающей точкой double precision.

Строки, имеющие collation, отличный от их байтового значения, преобразуются в формат collation. Это своего рода черное искусство, которое расширяет размер строки, но в результате строка находит свое правильное место при сортировке с другими строками той же collation. ‘A’, ‘a’, ‘â’, ‘á’, ‘Ă’, ‘ã’, ‘ä’, ‘å’, ‘ă’, ‘ą’, ‘Ā’ - все появляются на своих назначенных местах. (Извините за то, что это сделало с вашим почтовым клиентом… в моем это одиннадцать вариантов ‘A’.) Завершающие пробелы не включаются в ключ.

Число double precision искажается, чтобы оно тоже сортировалось побайтово - примерно инвертируется знак, затем экспонента, затем мантисса, с отбрасыванием завершающих нулей.

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

Составные ключи в основном аналогичны. Каждая часть преобразуется в свой тип ключа индекса и дополняется до кратного 4 байтам. После каждых четырех байт Firebird добавляет байт с позицией текущего поля ключа. Таким образом, индекс на LastName, FirstName, ZodiacSign будет выглядеть как 1Harr1ison2Ann 3Gemi3ni. Это позволяет избежать неловкости путаницы между Damnation и Dam nation.

Почему я сказал “(к сожалению)” выше? Потому что наличие единого формата для чисел позволяет Firebird изменять размер чисел без пересоздания индексов на них. Но когда Borland добавил обратно 64-битные целые - InterBase имел 64-битные целые с самого начала на VAX - какой-то умник понял, что double precision имеет 56 бит точности, а 64-битные целые - 64 бита. С другой стороны, индексы Firebird спроектированы так, чтобы выдерживать некоторую неточность… или оставшиеся 8 бит можно было бы добавить в конец… неважно. Поэтому вам приходится перестраивать индексы при переходе с Numeric/Decimal 9 на Numeric/Decimal 12. Печально.

“Префиксное сжатие?” При хранении ключа, отличного от первого на странице или первого после перехода на странице, Firebird смотрит на предыдущий ключ и обрезает ту часть начала следующего ключа, которая дублирует его предшественника, и добавляет длину обрезанной части в начало. Таким образом, строки “AAAA”, “AAAB”, “AAAC”, “AABC” становятся

“AAAA”, “3B”, “3C” и “2BC”. Существует проблема с некоторыми форматами GUID, которые ставят изменяемую часть числа первой, за которой следует фиксированная часть. Это сводит на нет префиксное сжатие и раздувает размер индексов.

“Переход?” - Префиксное сжатие значительно уменьшает размер индексов, снижая ввод-вывод, но требует чтения всей страницы для расшифровки ключа. Это нормально для страниц 1K, но при больших размерах страниц вычисления были неприемлемы. Поэтому каждая страница индекса теперь имеет свой собственный индекс, указывающий на смещения несжатых записей. Этот индекс называется вектором переходов.

Ann Harrision