Oracle Magazine - Русское издание (Май Июнь 2007)

Сергей Маркеленков,
компания РДТЕХ
http://www.rdtex.ru,
markelenkov@rdtex.ru

Размер блока базы данных
Oracle: малоизвестные факты.
Часть 1

Источник: статья предоставлена автором.

Все, чья работа тесно связана с СУБД Oracle, знают, насколько она сложна. Это отражается и в обилии возможностей, в большом числе всяческих параметров, опций, огромном объеме документации, постоянном выпуске новых версий и т.д. Разумеется, при таком большом объеме информации что-то со временем забывается, на какой-то факт при чтении документации можно вовсе не обратить внимания, а какой-то покажется малозначительным. Ну и, разумеется, многие достаточно интересные факты просто не отражены в документации. Как, наверное, и любая другая сложная система, Oracle со временем оброс мифами, редко имеющими под собой почву.

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

Все мы знаем из документации, что размер блока данных в Oracle может быть от 2k до 32k. Тот размер блока, с которым было создано табличное пространство SYSTEM, называется стандартным размером блока. Известно, что, начиная с версии 9i, можно сконфигурировать буферные кэши для табличных пространств с нестандартным размером блока. Для этого предназначены параметры инициализации db_nk_cache_size, где n может принимать значения 2,4,8,16,32. В общем, у подавляющего большинства работающих с Oracle сложилось четкое представление о том, что размер блока данных в Oracle лежит в диапазоне 2k-32k и кратен степени двойки.

 

Давайте попробуем задать размер блока не кратный степени двойки и посмотрим, что получится. Проводить эксперименты я буду на Oracle EE 9.2.0.8 под Windows. Создадим файл с параметрами инициализации следующего содержания:

db_name=O92
db_block_size=8500
1P class=bodycopy >compatible=9.2.0.0
control_files='D:\Test\Control01.ctl'
background_dump_dest=D:\Test\bdump
user_dump_dest=D:\Test\udump

Теперь пробуем запустить экземпляр:

D:\Test> sqlplus "/as sysdba"

SQL*Plus: Release 9.2.0.8.0 - Production on Wed May 23 13:04:14 2007

Copyright (c) 1982, 2002, Oracle Corporation.  All rights reserved.

Connected to an idle instance.

SQL> startup nomount pfile="D:\Test\initorcl.ora";
ORA-00374: parameter db_block_size = 8500 invalid ; 
must be a multiple of 512 in the range [2048..16384]
SQL>

 

Как и следовало ожидать, я получил сообщение об ошибке. Однако, сообщение достаточно информативно. Кстати, если посмотреть файл $ORACLE_HOME/rdbms/mesg/oraus.msg, то в комментариях в начале файла можно увидеть следующую строку:

/ smukkama 07/20/00 - change 374 - db_block_size must be multiple of 512

То есть, таким текст сообщения стал с 2000 года. Изменим параметр инициализации db_block_size на 8704 (8192+512) и попытаемся запустить экземпляр:

SQL> startup nomount pfile="D:\Test\initorcl.ora";
ORACLE instance started.

Total System Global Area   97590688 bytes
Fixed Size                   454048 bytes
Variable Size              46137344 bytes
Database Buffers           50331648 bytes
Redo Buffers                 667648 bytes
SQL>
   

Теперь попробуем создать базу данных с таким не кратным степени 2 размером блока:

SQL> CREATE DATABASE O92
  2  MAXINSTANCES 1 MAXLOGHISTORY 1 MAXLOGFILES 16
  3  MAXLOGMEMBERS 5 MAXDATAFILES 256
  4  DATAFILE 'D:\Test\System01.dbf' SIZE 128M EXTENT MANAGEMENT LOCAL
  5  DEFAULT TEMPORARY TABLESPACE TEMP TEMPFILE 'D:\Test\Temp01.dbf' SIZE 32M
  6  CHARACTER SET WE8ISO8859P1 NATIONAL CHARACTER SET AL16UTF16
  7  LOGFILE
  8  GROUP 1 ('D:\Test\Redo01.log') SIZE 16M,
  9  GROUP 2 ('D:\Test\Redo02.log') SIZE 16M;

Database created.

SQL> show parameter db_block_size

NAME                                 TYPE        VALUE
------------------------------------ ----------- ------------------------------
db_block_size                        integer     8704
SQL>

Все получилось. Однако такой некратный степени 2 размер блока допустим только для стандартного блока (т.е. для параметра инициализации db_block_size). Создать отдельное табличное пространство с некратным степени 2 размером блока не получится, т.к. невозможно создать буферный подкэш с некратным степени 2 размером блока. Для параметров db_nk_cache_size n может принимать только значения 2,4,8,16 и 32.

Каково может быть практическое применение этой экзотической возможности? Единственный случай, который, на мой взгляд, еще как-то оправдал бы создание базы данных с таким размером блока, это когда:

  1. подавляющее число строк в таблицах имеют примерно одинаковую длину и
  • эти строки таковы, что использование блоков стандартных (кратных степени 2) размеров приводит или к появлению множества сцепленных строк, или к неэкономному расходу пространства внутри блоков
  • либо используются “out of line” большие объекты (LOBы), причем подавляющее их число в размере чуть меньше какого-то “нестандартного” блока данных;
  1. обычно когда используется прямой ввод-вывод (direct_io) между буферным кэшем и дисками. Иначе накладные расходы из-за несоответствия размеров блока ОС и блока Oracle могут превзойти выгоду от экономии пространства.

Например, у вас 80-90% всех строк в таблицах имеют длину 2125 +|- 5 байт. В этом случае в блок размером 4k поместится только одна строка, в блок 8k – 3 строки, в блок 16k – 7 строк. Если же создать базу данных с размером блока 8704 байта, то в такой блок поместится 4 таких строки. Налицо существенная экономия как дискового пространства, так и оперативной памяти под буферный кэш.

Нечто похожее наблюдается и в случае столбцов типа LOB – любой такой столбец, который создан с опцией DISABLE STORAGE IN ROW или длина которого больше 3964 байт, всегда хранится в отдельном LOB-сегменте и занимает как минимум один блок. Например, 80-90% всех данных в базе составляют большие объекты, представляющие собой jpeg-файлы размером 10000 байт. В этом случае они будут занимать или 3 блока по 4k, или 2 блока по 8k, или 1 блок размером 16k. Во всех случаях это менее эффективно, чем хранить такие файлы в табличном пространстве с размером блока 20*512=10240 байт.

Но все это относится к разряду экзотики, поэтому на практике практически не применяется. Возможно поэтому, начиная с версии 10.2, Oracle уже не позволяет создавать базу данных с таким размером блока:

SQL> startup nomount pfile="D:\Test\initorcl.ora";
ORACLE instance started.

Total System Global Area  113246208 bytes
Fixed Size                  1289196 bytes
Variable Size              58721300 bytes
Database Buffers           50331648 bytes
Redo Buffers                2904064 bytes
SQL> CREATE DATABASE O102
  2  MAXINSTANCES 1 MAXLOGHISTORY 1 MAXLOGFILES 16
  3  MAXLOGMEMBERS 5 MAXDATAFILES 256
  4  DATAFILE 'D:\Test\System01.dbf' SIZE 128M
  5  DEFAULT TEMPORARY TABLESPACE TEMP TEMPFILE 'D:\Test\Temp01.dbf' SIZE 32M
  6  SYSAUX DATAFILE 'D:\Test\Sysaux01.dbf' SIZE 32M
  7  CHARACTER SET WE8ISO8859P1 NATIONAL CHARACTER SET AL16UTF16
  8  LOGFILE
  9  GROUP 1 ('D:\Test\Redo01.log') SIZE 16M,
 10  GROUP 2 ('D:\Test\Redo02.log') SIZE 16M;
CREATE DATABASE O102
*
ERROR at line 1:
ORA-25157: Specified block size 8704 is not valid

SQL>

Однако, если у вас уже есть созданная ранее база данных с не кратным степени 2 размером блока, то в этом случае миграция на версию 10.2 допускается, и вы сможете иметь такой размер блока и в версии Oracle 10.2.

Как известно, из любого правила есть исключение, поэтому вполне возможно, что в каком-то конкретном случае использование “нестандартного” размера блока будет достаточно эффективным. Как обычно, чтобы это понять, самый лучший способ – протестировать возможные варианты.

E-mail this page