|
Сергей Маркеленков,
компания РДТЕХ 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.
Каково может быть практическое применение этой экзотической возможности? Единственный случай, который, на мой взгляд, еще как-то оправдал бы создание базы данных с таким размером блока, это когда:
- подавляющее число строк в таблицах имеют примерно одинаковую длину и
- эти строки таковы, что использование блоков стандартных (кратных степени 2) размеров приводит или к появлению множества сцепленных строк, или к неэкономному расходу пространства внутри блоков
- либо используются “out of line” большие объекты (LOBы), причем подавляющее их число в размере чуть меньше какого-то “нестандартного” блока данных;
- обычно когда используется прямой ввод-вывод (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.
Как известно, из любого правила есть исключение, поэтому вполне возможно, что в каком-то конкретном случае использование “нестандартного” размера блока будет достаточно эффективным. Как обычно, чтобы это понять, самый лучший способ – протестировать возможные варианты.
|