Оценка размера записи

ЧАстые Вопросы и Ответы

Модераторы: kdv, CyberMax

Ответить
Andrew Sagulin
Сообщения: 53
Зарегистрирован: 11 мар 2005, 15:44

Оценка размера записи

Сообщение Andrew Sagulin » 20 янв 2006, 10:56

К сожалению я нигде не нашёл формулу расчёта длины записи для FB. Я понимаю: из-за того, что FB пакует каждую запись, точно посчитать её размер невозможно, но хотелось бы иметь формулу хотя бы для худшего случая.
Вот моё предположение:
Размер записи=24+суммарный размер полей.
Размер полей указан в документации, однако ничего не сказано про стоимость хранения varchar (есть ли там поле длины и сколько оно занимат: байт или два?).
Также в документации не указана стоимость поддержки значений NULL (1 бит на поле, 1 байт?).

Ну и мелкие претензии не по теме, но рядом с ней:
- странно, что date, time и timestamp занимают одинаковое количество байт (восемь), хотя последний тип должен быть больше, так как включает в себя два первых.
- не хватает типов tinyint (1 байт) и mediumint (3 байта), а также беззнаковых типов. Для небольших таблиц это не имеет большого значения, но когда в таблице сотни миллионов записей - каждый байт на счету. Хотя, наверное, это претензии скорее к стандарту SQL (где подобных типов не предусмотрено), чем конкретно к FB.

hvlad
Разработчик Firebird
Сообщения: 1244
Зарегистрирован: 21 мар 2005, 10:48

Сообщение hvlad » 20 янв 2006, 11:24

Запись в неупакованном виде имеет фиксированную длину, независимо от содержимого. Т.е. varchar(N), например, займет N+2 байта в распакованном виде.

На диске запись упакована. Алгоритм - простейший RLE: сначала байт-индикатор - положительное значение показывает длину последующей неупакованной цепочки байт, отрицательное значение показывает кол-во повторений следующего байта. Таким образом NULL в varchar(255) кодируется 8-ю байтами [2, 0, -127, 0, -127, 0, 1, 0] (не проверял, но суть видно ;) )

На диске присутствует заголовок записи - 13 (или 19 для фрагментированной записи) байт, битовая маска нуллов и затем упакованная запись.

- странно, что date, time и timestamp занимают одинаковое количество байт (восемь), хотя последний тип должен быть больше, так как включает в себя два первых.
Откуда дровишки ? первые два типа занимают 4 байта, последний - 8.
С индексами спутал ?
- не хватает типов tinyint (1 байт) и mediumint (3 байта), а также беззнаковых типов. Для небольших таблиц это не имеет большого значения, но когда в таблице сотни миллионов записей - каждый байт на счету.
На диске оно всё равно упакуется, это раз, работать будет медленно, это два.

kdv
Forum Admin
Сообщения: 6595
Зарегистрирован: 25 окт 2004, 18:07

Сообщение kdv » 20 янв 2006, 11:26

Я понимаю: из-за того, что FB пакует каждую запись, точно посчитать её размер невозможно, но хотелось бы иметь формулу хотя бы для худшего случая.
нет смысла. Минимум это примерно 18 байт (заголовок + delete stub), максимум - это размер всех фиксированных столбцов плюс размер данных char/varchar.
IBAnalyst показывает средний размер записей и версий, которые выводит статистика. Если IBA берет статистику через services api, то он при наводе мышью на размер записи покажет и максимально возможный размер, исходя из структуры таблицы.

То есть, подсчет размера записи по сравнению с мировой революцией - фигня.
странно, что date, time и timestamp занимают одинаковое количество байт (восемь),
почему это? date и time - 4 байта.
не хватает типов tinyint (1 байт) и mediumint (3 байта)
нафиг они не нужны. на нынешних 32-разрядных системах любые операции с числами размерностью меньше 4 байт все равно приводятся к 4-м байтам, поэтому скорость их обработки хуже, чем натурально 4-байтовых. Это можно увидеть даже сравнив smallint и int.
Кроме того, числа все равно упаковываются, поэтому мельчить с 1 или 3-байтовыми типами смысла нет.
В MySQL этих типов напихали непонятно зачем, может, чтобы козырять большей широтой поддерживаемых типов данных?
но когда в таблице сотни миллионов записей - каждый байт на счету
это тоже можно считать несущественным. Даже до нынешнего лимита в FB 1.5 в 36 гигабайт на таблицу (2 столбца integer, ~600 миллионов записей) дошли считанные единицы.
Причем, для решения этой проблемы пришлось увеличить разрядность идентификатора записи с 32 бит до 64 (реально до 40).

Andrew Sagulin
Сообщения: 53
Зарегистрирован: 11 мар 2005, 15:44

Сообщение Andrew Sagulin » 20 янв 2006, 12:39

Спасибо, hvlad, за подробное объяснение.

Про "дровишки" :)

В IB6 langref.pdf написано буквально следующее:
DATE 64 bits
TIME 64 bits
TIMESTAMP 64 bits

Сейчас посмотрел в IB6 Release Notes: да, действительно, DATE и TIME занимают 32 бита. Прямо "здесь играть, здесь не играть, а здесь я рыбу заворачивал". :?
Кстати, очень-очень не хватает единой документации, и периодически приходится листать как минимум 4 документа (IB6 LangRef, IB6 RelNotes, FB 1 и FB1.5 RelNotes).

Про "На диске оно всё равно упакуется"

Одни и те же данные. Таблицы отличаются только тем, что в одной из таблиц 3 поля Integer заменены на SmallInt. Вот статистика:

Код: Выделить всё

CONNT (138)
    Primary pointer page: 1284847, Index root page: 1284875
    Average record length: 54.57, total records: 13784461
    Average version length: 0.00, total versions: 0, max versions: 0
    Data pages: 61798, data page slots: 61798, average fill: 98%
    Fill distribution:
	 0 - 19% = 0
	20 - 39% = 0
	40 - 59% = 0
	60 - 79% = 0
	80 - 99% = 61798

CONNT2 (139)
    Primary pointer page: 1364875, Index root page: 1364876
    Average record length: 59.84, total records: 13784461
    Average version length: 0.00, total versions: 0, max versions: 0
    Data pages: 65721, data page slots: 65721, average fill: 99%
    Fill distribution:
	 0 - 19% = 0
	20 - 39% = 1
	40 - 59% = 0
	60 - 79% = 0
	80 - 99% = 65720
Разница чуть больше, чем 5 байт на одну запись.

Про "работать будет медленно".

Зато таблица меньше станет, а значит с диска считываться будет быстрей. :)

kdv
Forum Admin
Сообщения: 6595
Зарегистрирован: 25 окт 2004, 18:07

Сообщение kdv » 20 янв 2006, 13:43

Сейчас посмотрел в IB6 Release Notes: да, действительно, DATE и TIME занимают 32 бита. Прямо "здесь играть, здесь не играть, а здесь я рыбу заворачивал
так это пре-релиз доки. там и синие метки часто встречаются. Релиз доки шел только с платной версией 6.1, соответственно выкладывать его я не имею права.
Кстати, очень-очень не хватает единой документации, и периодически приходится листать как минимум 4 документа (IB6 LangRef, IB6 RelNotes, FB 1 и FB1.5 RelNotes
купи книгу Х. Борри. А так - права на доку по IB принадлежат Borland, и "склеивать" ее с релизнотами FB никто не имеет права.
Зато таблица меньше станет, а значит с диска считываться будет быстрей.
разница в 6 процентов. Таблица имеет размер 65к страниц, то есть это при размере страницы - 500 мег. При интенсивной работе она никогда не будет целиком в кэше, поэтому эти 6% разницы в размере уйдут на большую разницу в I/O вообще, плюс затраты процессора на конвертацию, которые на больших преобразованиях тоже выливаются в проценты ухудшения, а не в доли процента.

Ты бы еще с Yaffil поэкспериментировал, там есть возможность задать порог сжатия версий. Если его снизить относительно умолчания, то скорость обновления данных возрастает чуть ли не в 2-3 раза, зато на неупакованных версиях начинает пухнуть БД.
То есть, сжатие жрет проц и потребляет время, но экономит диск, а несжатие - наоборот. И на конкретной задаче еще вопрос - что будет эффективнее.

Ответить