Дилема (FS block, DB block, BLOB)

shkoda
Дата: 28.09.2004 11:23:38
Вопрос больше теоретический, но все же интересно :)
Исходные данные:
- Блоб при хранении выравнивается по ширине блока базы, логично иметь меньший размер блока для большого количества (10-ки миллионов) блобов размером 1..16К
- рекомендуется делать ширину блока ФС кратную ширине блока ФС
- не все ОС позволяют размер блока ФС меньше 8К (солярка например)

Варианты:
- установить блок БД 8к, тогда будем терять место просто гигабайтами, на 10млн блобов потеряем ~40-80ГБ
- сделать блок 2К, но возможно будет медленнее все это дело работать, на сколько медленнее история умалчивает :)
- делать RAW устройства, соответственно гемор с управлением всем этим хозяйством

Чем пожертвовать? Или есть еще варианты?
Вячеслав Любомудров
Дата: 28.09.2004 12:09:25
shkoda
Вопрос больше теоретический, но все же интересно :)
Исходные данные:
- Блоб при хранении выравнивается по ширине блока базы, логично иметь меньший размер блока для большого количества (10-ки миллионов) блобов размером 1..16К
- рекомендуется делать ширину блока ФС кратную ширине блока ФС
- не все ОС позволяют размер блока ФС меньше 8К (солярка например)

Варианты:
- установить блок БД 8к, тогда будем терять место просто гигабайтами, на 10млн блобов потеряем ~40-80ГБ
- сделать блок 2К, но возможно будет медленнее все это дело работать, на сколько медленнее история умалчивает :)
- делать RAW устройства, соответственно гемор с управлением всем этим хозяйством

Чем пожертвовать? Или есть еще варианты?
На самом деле если хранить блоб в строке, а не отдельно (enable storage in row) - все не так страшно ;-)

Конечно случаи индивидуальны, но вот простой пример:
Большая таблица с блобом (два поля фиксированной длины по ~12 байт и блоб), побита на партиции по дате.

Одна из партиции содержит 5710623 записей, занимает 66112(блоков), 1083179008 (байт), средняя длина цлоба (avg(length)) ~98.5 байт при разбросе min-max=1-2217, а на строку расходуется 189.6, убрав длину остальных полей и всевозможные служебные накладные расходы получим 30-50 потерянных байт на запись - много, конечно, но никак не по границе блока.

Размер блока 16К, основной размер БД - 8К. Кстати, если бы сохранялось не в строке - минимальный размер, занятый даже 1-байтным блобом составлял бы размер стандартного блока БД (не размера блока этого таблспейса)
Так что достаточно терпимо
shkoda
Дата: 28.09.2004 14:06:02
Т.е. предложение наоборот сделать на таблице с блобами большой блок и включить enable storage in row?
В моем случае ситуации усложняется следущими факторами:
1. Блоб полей в таблице 4
2. enable storage in row приводит к фулсканам таблицы, в результате чего приходиться выключать CBO.
3. Вопрос с кэшированием. Когда disable storage in row то блоки блобов можно не кэшировать, а вот когда блобы хранятся в строке, то от этого никуда не денешься. У меня промежуток времени между записью и чтением большой, блоб один раз пишется, потом читается и в архив. Т.е. опытным путем установлено что disable storage in row приводит к существенному уменьшению нагрузки на дисковую
4. В код приложения вмешаться нельзя.
Вячеслав Любомудров
Дата: 29.09.2004 02:15:01
Я же говорил - случаи у всех индивидуальные
Для своих данных я пробовал блок в 2K, 8K и 16K - выигрыш по месту (и, соответственно по скорости, хоть и в меньшей степени) оказалось в разах примерно 2.0, 1.3, 1.0

По поводу disable storage in row - тогда минимальный чанк для любого блоба - один стандартный блок БД - в моем случае 8K - для среднего размера блоба в 200-300 байт это пожалуй слишком расточительно

Что касается средних размеров то они весьма неравномерны и составляют в одних партициях 200 байт, в других - 2K. А так туда умудрились запихать и более 10K (это текстовое описание-то) - в общем то из-за упрощения интерфейса и было принято решение хранить в цлоб, а не в varchar2

А чтоб не бояться full scan'ов - мы лобы вынесли в отдельную табличку (спицифика такова, что это обычные текстовые описания), и достаем их только при необходимости по первичному ключу. Понятно, что в большинстве операций они нафиг ненужны и поэтому блоки для их хранения сканировать не нужно. Кстати вынос в отдельную таблицу НА ПОРЯДОК(!) поднял скорость выполнения многих операций (что впрочем, естественно)
Markelenkov
Дата: 29.09.2004 19:57:02
Вячеслав Любомудров
Кстати, если бы сохранялось не в строке - минимальный размер, занятый даже 1-байтным блобом составлял бы размер стандартного блока БД (не размера блока этого таблспейса)
Так что достаточно терпимо

То есть, ты хочешь сказать, что если, например, db_block_size=4k, а LOB с параметром DISABLE STORAGE IN ROW лежит в TS с blocksize=16k, то он будет в таком блоке занимать только 4k?

Чего-то я не понял этой фразы, что ты имел ввиду, Вячеслав?
Вячеслав Любомудров
Дата: 30.09.2004 03:05:19
Markelenkov
Вячеслав Любомудров
Кстати, если бы сохранялось не в строке - минимальный размер, занятый даже 1-байтным блобом составлял бы размер стандартного блока БД (не размера блока этого таблспейса)
Так что достаточно терпимо

То есть, ты хочешь сказать, что если, например, db_block_size=4k, а LOB с параметром DISABLE STORAGE IN ROW лежит в TS с blocksize=16k, то он будет в таком блоке занимать только 4k?

Чего-то я не понял этой фразы, что ты имел ввиду, Вячеслав?
Нет, не совсем верно выразился
(Насколько я понял документацию), при db_block_size=8k, а LOB с параметром DISABLE STORAGE IN ROW лежит в TS с blocksize=2k, то он будет занимать в таком TS 4 блока (т.е. 8k)
Markelenkov
Дата: 30.09.2004 18:24:29
Вячеслав Любомудров
При db_block_size=8k, а LOB с параметром DISABLE STORAGE IN ROW лежит в TS с blocksize=2k, то он будет занимать в таком TS 4 блока (т.е. 8k)

Вячеслав, ты ошибаешься. В подобном случае LOB будет занимать один блок того TS, в котором он расположен, т.е. 2k.

Следует отметить, что документация об этом умалчивает, хотя при появлении фичи с multiplay block size об этом стоило бы четко упомянуть.
Вячеслав Любомудров
Дата: 01.10.2004 03:05:00
Да, спасибо за подсказку
Я исходил из
Oracle9 i SQL Reference CREATE TABLE
...
CHUNK integer: Specify the number of bytes to be allocated for LOB
manipulation. If integer is not a multiple of the database block size, then
Oracle rounds up (in bytes) to the next multiple. For example, if the database
block size
is 2048 and integer is 2050, then Oracle allocates 4096 bytes (2
blocks). The maximum value is 32768 (32K), which is the largest Oracle block
size allowed. The default CHUNK size is one Oracle database block.
...
и проверить неудосужился
На самом деле размер чанка (минимальный кусок лоба) должен быть кратен размеру блока таблспейса с лоб-сегментом. И по-умолчанию ставится равным одному блоку того самого таблспейса
tst> create table tlob(x number, l clob) tablespace users
  2  lob(l) store as tlob_lobs(tablespace lb_ts
  3  disable storage in row)
  4  /

Table created.

tst> select table_name, segment_name, chunk from user_lobs where table_name='TLOB';

TABLE_NAME                     SEGMENT_NAME                                  CHUNK
------------------------------ ------------------------------ --------------------
TLOB                           TLOB_LOBS                                      2048

tst> select tablespace_name, block_size from dba_tablespaces
  2  where tablespace_name in ('USERS', 'LB_TS');

TABLESPACE_NAME                          BLOCK_SIZE
------------------------------ --------------------
LB_TS                                          2048
USERS                                          8192
Как говорится доверяй, но все возможные неоднозначности проверяй ;-)
Скорее всего это осталось в доке от 8, где был только один размер блока :-(