Процедура dbms_space.free_space, Інші СУБД, Бази даних, статті

Для чого призначена ця процедура, що зберігається? Вона видає обсяг вільного простору для змін, вірно? Але вона не повідомляє, скільки вільного простору залишилося в кожному блоці. Інформацію про вільний просторі можна отримати з подання dba_free_space. Не могли б ви показати, для чого ми могли б використовувати цю процедуру?


В цьому пакеті є ще одна процедура, unused_space. Якщо вона повідомляє, що є 35 блоків, чи означає це, що в 35 блоках ніколи не було даних?


Схоже, що вона не повідомляє про вільні блоках за відміткою максимального рівня заповнення (high water mark – HWM), чи не так?


Як ми могли б використовувати цю інформацію? Не могли б ви дати декілька прикладів використання цих процедур при управлінні простором.


Відповідь Тома Кайта


Далі представлений приклад, що показує, як використовувати пакет dbms_space і як інтерпретувати отримані результати. По суті, за допомогою цих 2 процедур пакета ми зможемо отримати наступну інформацію:

Free Blocks …… Кількість блоків в списку вільних (freelist) Total Blocks ….. Загальна кількість блоків, виділених таблиці Total Bytes …… Загальна кількість байтів, виділених таблиці Unused Blocks …. Скільки блоків ніколи не містили дані Unused Bytes ….. Те ж, але в байтах

При цьому ви не зможете дізнатися, у скількох блоках є вільний простір для змін. Ми можемо визначити, скільки блоків є кандидатами для вставки (вони знаходяться в списку вільних блоків) і всі блоки в списку вільних точно містять простір для змін, але в таблиці є ще блоки, в яких достатньо простору для змін, але вони не входять в список вільних блоків. Інформацію про них ми ніяк не отримаємо.


Пропонована процедура не скаже вам, скільки простору вільно в кожному блоці (і ніхто не скаже, оскільки в таблиці зазвичай – тисячі або сотні тисяч блоків, і будь поблочної аналіз вільного простору практично неефективний. Можна отримати середній обсяг вільного простору, але не по кожному блоку окремо).


Цей звіт видає інформацію про блоки за відміткою максимального рівня заповнення. Unused Blocks– Це якраз блоки “вище” позначки максимального рівня заповнення.


Велику частину інформації, що видається пакетом dbms_space, Можна отримати, аналізуючи таблицю і виконуючи запити до уявлень user_tables і user_segments. Цей пакет забезпечує більш детальний аналіз списків вільних блоків, оскільки кожен список можна аналізувати окремо.


Нижче представлена ​​процедура, за допомогою якої можна спростити використання пакета dbms_space. Після неї я створюю таблицю і показую, як використовується виділене їй простір. В коментарях я пояснюю отримані результати.

ops$tkyte@8i> create or replace
2 procedure show_space
3 ( p_segname in varchar2,
4 p_owner in varchar2 default user,
5 p_type in varchar2 default “TABLE” )
6 as
7 l_free_blks number;
8
9 l_total_blocks number;
10 l_total_bytes number;
11 l_unused_blocks number;
12 l_unused_bytes number;
13 l_LastUsedExtFileId number;
14 l_LastUsedExtBlockId number;
15 l_LAST_USED_BLOCK number;
16 procedure p( p_label in varchar2, p_num in number )
17 is
18 begin
19 dbms_output.put_line( rpad(p_label,40,”.”) //
20 p_num );
21 end;
22 begin
23 dbms_space.free_blocks
24 ( segment_owner => p_owner,
25 segment_name => p_segname,
26 segment_type => p_type,
27 freelist_group_id => 0,
28 free_blks => l_free_blks );
29
30 dbms_space.unused_space
31 ( segment_owner => p_owner,
32 segment_name => p_segname,
33 segment_type => p_type,
34 total_blocks => l_total_blocks,
35 total_bytes => l_total_bytes,
36 unused_blocks => l_unused_blocks,
37 unused_bytes => l_unused_bytes,
38 LAST_USED_EXTENT_FILE_ID => l_LastUsedExtFileId,
39 LAST_USED_EXTENT_BLOCK_ID => l_LastUsedExtBlockId,
40 LAST_USED_BLOCK => l_LAST_USED_BLOCK );
41
42 p( “Free Blocks”, l_free_blks );
43 p( “Total Blocks”, l_total_blocks );
44 p( “Total Bytes”, l_total_bytes );
45 p( “Unused Blocks”, l_unused_blocks );
46 p( “Unused Bytes”, l_unused_bytes );
47 p( “Last Used Ext FileId”, l_LastUsedExtFileId );
48 p( “Last Used Ext BlockId”, l_LastUsedExtBlockId );
49 p( “Last Used Block”, l_LAST_USED_BLOCK );
50 end;
51 /
Procedure created.
ops$tkyte@8i> create table t ( x int, y char(2000) default “*” )
2 storage ( initial 40k next 40k minextents 5 )
3 tablespace system;
Table created.

Я створив таблицю з декількома екстента, щоб результати були цікавіше. Я також додав стовпець типу char(2000), Щоб мінімальна довжина рядка становила 2000 байтів (поля типу char завжди мають максимальний розмір). В результаті, рядки у мене виходять “великі”.

ops$tkyte@8i> insert into t (x) values ( 1 );
1 row created.

Я створив один рядок, щоб використовувати трохи простору в таблиці.

ops$tkyte@8i> analyze table t compute statistics;
Table analyzed.
ops$tkyte@8i> compute sum of blocks on report
ops$tkyte@8i> break on report
ops$tkyte@8i> select extent_id, bytes, blocks
2 from user_extents
3 where segment_name = “T”
4 and segment_type = “TABLE”
5 /
EXTENT_ID BYTES BLOCKS
———- ———- ———-
2 40960 5
3 81920 10
4 57344 7
0 40960 5
1 40960 5
———-
sum 32

Це показує, що в п’яти екстента цій таблиці виділено 32 блоки (що й слід було очікувати)

ops$tkyte@8i> clear breaks
ops$tkyte@8i> select blocks, empty_blocks,
2 avg_space, num_freelist_blocks
3 from user_tables
4 where table_name = “T”
5 /
BLOCKS EMPTY_BLOCKS AVG_SPACE NUM_FREELIST_BLOCKS
———- ———— ———- ——————-
1 30 6091 1

Оскільки я проаналізував таблицю, у мене є доступ до наведеної вище інформації. Ви побачите, що вона в точності відповідає отриманим нижче результатів. Усього таблиці виділено 32 блоки (як показано нижче і підтверджується запитом до user_extents вище). Є 30 EMPTY_BLOCKS (Вище) /UNUSED_BLOCKS (Нижче). Це блоки вище HWM. Залишається 2 неврахованих блоку – один блок містить дані, а інший – карту екстентів для таблиці (перший блок кожної таблиці використовується системою для своїх цілей).

ops$tkyte@8i> exec show_space( “T” )
Free Blocks………………………..1
Total Blocks……………………….32
Total Bytes………………………..262144
Unused Blocks………………………30
Unused Bytes……………………….245760
Last Used Ext FileId………………..1
Last Used Ext BlockId……………….64816
Last Used Block…………………….2
PL/SQL procedure successfully completed.
ops$tkyte@8i> insert into t (x)
2 select rownum
3 from all_users
4 where rownum < 50
5 /
49 rows created.
ops$tkyte@8i> commit;
Commit complete.

Отже, тепер у нас є 50 рядків по 2 Кбайта кожна. Я використовую блоки розміром 8 Кбайт, тому припускаю, що в кожному блоці буде по 3 рядки. Це означає близько 18 блоків даних плюс 1 для системної інформації = близько 19 “використовуються” блоків в результаті. Нижче я отримую наступну інформацію:


ops$tkyte@8i> exec show_space( “T” )
Free Blocks………………………..3
Total Blocks……………………….32
Total Bytes………………………..262144
Unused Blocks………………………12
Unused Bytes……………………….98304
Last Used Ext FileId………………..1
Last Used Ext BlockId……………….64681
Last Used Block…………………….5
PL/SQL procedure successfully completed.
ops$tkyte@8i> delete from t;
50 rows deleted.
ops$tkyte@8i> commit;
Commit complete.

Тепер ми можемо побачити, як використовується простір після видалення.

ops$tkyte@8i> exec show_space( “T” )
Free Blocks………………………..19
Total Blocks……………………….32
Total Bytes………………………..262144
Unused Blocks………………………12
Unused Bytes……………………….98304
Last Used Ext FileId………………..1
Last Used Ext BlockId……………….64681
Last Used Block…………………….5
PL/SQL procedure successfully completed.

Представлений результат показує, що при видаленні всі блоки поміщаються в список вільних. У нас вийшло 19 блоків у списку вільних + 12 невикористовуваних + 1 системний = 32 блоки. Все враховано. Зверніть увагу, що позиція HWM залишилася тією ж – у нас не 31 невикористовуваний блок, а 12, як і раніше. Значення HWM для таблиці ніколи не зменшується, якщо тільки ми не виконаємо …

ops$tkyte@8i> truncate table t;
Table truncated.
ops$tkyte@8i> exec show_space( “T” )
Free Blocks………………………..0
Total Blocks……………………….32
Total Bytes………………………..262144
Unused Blocks………………………31
Unused Bytes……………………….253952
Last Used Ext FileId………………..1
Last Used Ext BlockId……………….64816
Last Used Block…………………….1
PL/SQL procedure successfully completed.

її очищення. В результаті, всі виділені блоки виявляються до HWM. Тепер у нас є 31 невикористовуваних блоку + 1 системний = 32 блоки. Жоден з блоків не входить в список вільних, тому що ні в одному з них немає ніяких даних.


ORA-14107: partition specification is required for a partitioned object

SQL> CREATE TABLE T (X VARCHAR2(20));
Table created.
SQL> EXEC SHOW_SPACE(“T”);
PL/SQL procedure successfully completed.
SQL> set serveroutput on
SQL> EXEC SHOW_SPACE(“T”);
Free Blocks………………………..0
Total Blocks……………………….10
Total Bytes………………………..81920
Unused Blocks………………………9
Unused Bytes……………………….73728
Last Used Ext FileId………………..5
Last Used Ext BlockId……………….126659
Last Used Block…………………….1
PL/SQL procedure successfully completed.

T_P – секціонірованная таблиця.

SQL> EXEC SHOW_SPACE(“T_P”);
BEGIN SHOW_SPACE(“T_P”); END;
*
ERROR at line 1:
ORA-14107: partition specification is required for a partitioned object
ORA-06512: at “SYS.DBMS_SPACE”, line 55
ORA-06512: at “myschema.SHOW_SPACE”, line 22
ORA-06512: at line 1

Чому я отримую цю помилку при спробі використання процедури show_space для секціонірованние (partitioned) таблиці?


Відповідь Тома Кайта:


Так, прийшов час оновити цю утиліту! У мене вже є нова версія, яка додатково:



  1. враховує секціонування;
  2. дозволяє отримувати результати в SQL операторах, повертаючи результуюче безліч, а не просто друкуючи їх. Роздрукувати за допомогою dbms_output.put_line ви легко зможете самі …

Почнемо з типів:

create or replace type show_space_type
as object
( owner varchar2(30),
segment_name varchar2(30),
partition_name varchar2(30),
segment_type varchar2(30),
free_blocks number,
total_blocks number,
unused_blocks number,
last_used_ext_fileid number,
last_used_ext_blockid number,
last_used_block number
)
/
create or replace type show_space_table_type
as table of show_space_type
/

А потім сама функція:

create or replace
function show_space_for
( p_segname in varchar2,
p_owner in varchar2 default user,
p_type in varchar2 default “TABLE”,
p_partition in varchar2 default NULL )
return show_space_table_type
authid CURRENT_USER
as – Pragma autonomous_transaction; – нижче з’ясується, що це зайве – прим. В.К.
type rc is ref cursor;
l_cursor rc;
l_free_blks number;
l_total_blocks number;
l_total_bytes number;
l_unused_blocks number;
l_unused_bytes number;
l_LastUsedExtFileId number;
l_LastUsedExtBlockId number;
l_last_used_block number;
l_sql long;
l_conj varchar2(7) default ” where “;
l_data show_space_table_type := show_space_table_type();
l_owner varchar2(30);
l_segment_name varchar2(30);
l_segment_type varchar2(30);
l_partition_name varchar2(30);
procedure add_predicate( p_name in varchar2, p_value in varchar2 )
as
begin
if ( instr( p_value, “%” ) > 0 )
then
l_sql := l_sql // l_conj // p_name //
” like “”” // upper(p_value) // “”””;
l_conj := ” and “;
elsif ( p_value is not null )
then
l_sql := l_sql // l_conj // p_name //
” = “”” // upper(p_value) // “”””;
l_conj := ” and “;
end if;
end;
begin
l_sql := “select owner, segment_name, segment_type, partition_name
from dba_segments “;
add_predicate( “segment_name”, p_segname );
add_predicate( “owner”, p_owner );
add_predicate( “segment_type”, p_type );
add_predicate( “partition”, p_partition );
execute immediate “alter session set cursor_sharing=force”;
open l_cursor for l_sql;
execute immediate “alter session set cursor_sharing=exact”;
loop
fetch l_cursor into l_owner, l_segment_name, l_segment_type, l_partition_name;
exit when l_cursor%notfound;
begin
dbms_space.free_blocks
( segment_owner => l_owner,
segment_name => l_segment_name,
segment_type => l_segment_type,
partition_name => l_partition_name,
freelist_group_id => 0,
free_blks => l_free_blks );
dbms_space.unused_space
( segment_owner => l_owner,
segment_name => l_segment_name,
segment_type => l_segment_type,
partition_name => l_partition_name,
total_blocks => l_total_blocks,
total_bytes => l_total_bytes,
unused_blocks => l_unused_blocks,
unused_bytes => l_unused_bytes,
LAST_USED_EXTENT_FILE_ID => l_LastUsedExtFileId,
LAST_USED_EXTENT_BLOCK_ID => l_LastUsedExtBlockId,
LAST_USED_BLOCK => l_LAST_USED_BLOCK );
l_data.extend;
l_data(l_data.count) :=
show_space_type( l_owner, l_segment_name, l_partition_name,
l_segment_type, l_free_blks, l_total_blocks, l_unused_blocks,
l_lastUsedExtFileId, l_LastUsedExtBlockId, l_last_used_block );
exception
when others then null;
end;
end loop;
close l_cursor;
return l_data;
end;
/

Тепер ми можемо виконати:

ops$tkyte@ORA817DEV.US.ORACLE.COM> select SEGMENT_NAME, PARTITION_NAME
SEGMENT_TYPE, FREE_BLOCKS,TOTAL_BLOCKS,UNUSED_BLOCKS
2 from table( cast( show_space_for( “HASHED”,user,”%” ) as show_space_table_type ) )
3 /
SEGMENT_NA SEGMENT_TYPE FREE_BLOCKS TOTAL_BLOCKS UNUSED_BLOCKS
———- —————– ———– ———— ————-
HASHED PART_2 1 64 62
HASHED PART_3 1 64 62
HASHED PART_4 1 64 62
HASHED PART_1 1 64 62

А для версії 9i можна змінити функцію на потокову (pipelined):

ops$tkyte@ORA9I.WORLD> create or replace
2 function show_space_for
3 ( p_segname in varchar2,
4 p_owner in varchar2 default user,
5 p_type in varchar2 default “TABLE”,
6 p_partition in varchar2 default NULL )
7 return show_space_table_type
8 authid CURRENT_USER
9 PIPELINED
10 as 11 – pragma autonomous_transaction; – нижче з’ясується, що це зайве – прим. В.К.
12 type rc is ref cursor;
13 l_cursor rc;
14
15 l_free_blks number;
16 l_total_blocks number;
17 l_total_bytes number;
18 l_unused_blocks number;
19 l_unused_bytes number;
20 l_LastUsedExtFileId number;
21 l_LastUsedExtBlockId number;
22 l_last_used_block number;
23 l_sql long;
24 l_conj varchar2(7) default ” where “;
25 l_owner varchar2(30);
26 l_segment_name varchar2(30);
27 l_segment_type varchar2(30);
28 l_partition_name varchar2(30);
29
30 procedure add_predicate( p_name in varchar2, p_value in varchar2 )
31 as
32 begin
33 if ( instr( p_value, “%” ) > 0 )
34 then
35 l_sql := l_sql // l_conj // p_name // ” like “”” // upper(p_value) // “”””;
36 l_conj := ” and “;
37 elsif ( p_value is not null )
38 then
39 l_sql := l_sql // l_conj // p_name // ” = “”” // upper(p_value) // “”””;
40 l_conj := ” and “;
41 end if;
42 end;
43 begin
44 l_sql := “select owner, segment_name, segment_type, partition_name
45 from dba_segments “;
46
47 add_predicate( “segment_name”, p_segname );
48 add_predicate( “owner”, p_owner );
49 add_predicate( “segment_type”, p_type );
50 add_predicate( “partition”, p_partition );
51
52 execute immediate “alter session set cursor_sharing=force”;
53 open l_cursor for l_sql;
54 execute immediate “alter session set cursor_sharing=exact”;
55
56 loop
57 fetch l_cursor into l_owner, l_segment_name, l_segment_type, l_partition_name;
58 dbms_output.put_line( l_segment_name // “,” // l_segment_type );
59 exit when l_cursor%notfound;
60 begin
61 dbms_space.free_blocks
62 ( segment_owner => l_owner,
63 segment_name => l_segment_name,
64 segment_type => l_segment_type,
65 partition_name => l_partition_name,
66 freelist_group_id => 0,
67 free_blks => l_free_blks );
68
69 dbms_space.unused_space
70 ( segment_owner => l_owner,
71 segment_name => l_segment_name,
72 segment_type => l_segment_type,
73 partition_name => l_partition_name,
74 total_blocks => l_total_blocks,
75 total_bytes => l_total_bytes,
76 unused_blocks => l_unused_blocks,
77 unused_bytes => l_unused_bytes,
78 LAST_USED_EXTENT_FILE_ID => l_LastUsedExtFileId,
79 LAST_USED_EXTENT_BLOCK_ID => l_LastUsedExtBlockId,
80 LAST_USED_BLOCK => l_LAST_USED_BLOCK );
81
82 pipe row ( show_space_type( l_owner, l_segment_name, l_partition_name,
83 l_segment_type, l_free_blks, l_total_blocks, l_unused_blocks,
84 l_lastUsedExtFileId, l_LastUsedExtBlockId, l_last_used_block ) );
85 exception
86 when others then null;
87 end;
88 end loop;
89 close l_cursor;
90
91 return;
92 end;
93 /
Function created.
ops$tkyte@ORA9I.WORLD> set arraysize 1
ops$tkyte@ORA9I.WORLD> select SEGMENT_NAME, SEGMENT_TYPE,
FREE_BLOCKS,TOTAL_BLOCKS,UNUSED_BLOCKS
2 from table( show_space_for( “%”,user,”%” ) )
3 /
SEGMENT_NAME SEGMENT_TYPE FREE_BLOCKS TOTAL_BLOCKS UNUSED_BLOCKS
————— —————– ———– ———— ————-
KEEP_SCN TABLE 1 64 62
EMPLOYEES TABLE 0 64 63
STINKY TABLE 0 64 63
OBJECT_TABLE TABLE 1 64 62
RUN_STATS TABLE 2 64 53
EMP TABLE 0 64 62
PROJ TABLE 0 64 62
X TABLE 1 64 62
WORDS TABLE 0 64 63
DOCS TABLE 0 64 63
KEYWORDS TABLE 0 64 63
DEPT TABLE 2 64 61
C TABLE 1 64 62
DSINVLINES TABLE 1 64 62
NUM_STR TABLE 1 64 23
T TABLE 4 64 28
T1 TABLE 0 64 63
T2 TABLE 0 64 63
BOM TABLE 1 64 62
PARTS TABLE 1 64 62
SYS_C001371 INDEX 0 64 62
SYS_C001372 INDEX 0 64 62
SYS_C001574 INDEX 0 64 62
SYS_C001694 INDEX 0 64 62
SYS_C001695 INDEX 0 64 62
BOM_PK INDEX 0 64 62
PARTS_PK INDEX 0 64 62
27 rows selected.

Тут було багато коментарів і питань, які я для скорочення обсягу випуску перекладати не став – прим. В.К.


Коментар Тома Кайта з приводу “системних” блоків у файлах даних


Так, перший блок файлу в табличному просторів, керованому За словником (DMT), використовується системою.


Так само, як і перші 64 Кбайта в ЛОКАЛЬНО керованих табличних просторах (LMT).


Нижче представлено те, про що ви запитували – що ви отримуєте і скільки простору доступно для використання (я настійно рекомендую використовувати LMT – уникайте DMT):

ops$tkyte@ORA817DEV.US.ORACLE.COM> Create tablespace TS1 datafile “/tmp/ts1.dbf” size 24k reuse;
Tablespace created.
ops$tkyte@ORA817DEV.US.ORACLE.COM> host ls -l /tmp/ts1.dbf
-rw-r—– 1 ora817 32768 Dec 26 13:33 /tmp/ts1.dbf
ops$tkyte@ORA817DEV.US.ORACLE.COM> @free 1

MaxPoss Max
Tablespace Name KBytes Used Free Used Largest Kbytes Used
—————- ——- ———- ——— —— ——- ——– ——

TS1 24 8 16 33.3 16 0 .0
——- ———- ———
sum 3,818,848 1,605,144 2,213,704
13 rows selected.


Бачите: 24 Кбайта розмір – 8 використано, 16 вільно …

ops$tkyte@ORA817DEV.US.ORACLE.COM> alter tablespace ts1 add datafile “/tmp/ts2.dbf” size 24k reuse;
Tablespace altered.
ops$tkyte@ORA817DEV.US.ORACLE.COM> host ls -l /tmp/ts2.dbf
-rw-r—– 1 ora817 32768 Dec 26 13:33 /tmp/ts2.dbf
ops$tkyte@ORA817DEV.US.ORACLE.COM> @free 1
MaxPoss Max
Tablespace Name KBytes Used Free Used Largest Kbytes Used
—————- ——- ——— ——— —— ——– ——– ——

TS1 48 16 32 33.3 16 0 .0
——- ——— ———
sum 3,818,872 1,605,152 2,213,720
13 rows selected.

Тепер маємо 48 Кбайт (24 * 2), 16 Кбайт використано (по одному блоку в файлі)


Розміри екстентів в байтах


Спасибі за хороше пояснення, Том. Але у мене є одне питання:


ops$tkyte@8i> select extent_id, bytes, blocks
2 from user_extents
3 where segment_name = “T”
4 and segment_type = “TABLE”
5 /
EXTENT_ID BYTES BLOCKS
———- ———- ———-
2 40960 5
3 81920 10
4 57344 7
0 40960 5
1 40960 5
———-
sum 32

Ось це ми отримали після створення таблиці T з першим і наступним екстентів розміром 40 Кбайт. Так звідки узяв третю екстент – 81920 байт і четвертий, 57344? І чому їм виділено, відповідно, 10 і 7 блоків?


Відповідь Тома Кайта:


Причина в тому, що я створив таблицю в табличному просторі, керованому за словником, і ми виділяємо простір розміром + – 5 блоків (щоб уникнути фрагментації вільного простору).


Почитайте

http://download-west.oracle.com/docs/cd/A87860_01/doc/server.817/a76965/c02block.htm#2846

там описаний алгоритм.


Що таке AUTO SEGMENT SPACE MANAGEMENT?


Яким має бути значення freelist_group_id при кожному зверненні до dbms_space.free_blocks? Ви за замовчуванням використовуєте значення 1, так чи треба задавати 1 для таблиць у всіх випадках?


Я тільки що виконав dbms_space.free_blocks для сегмента в ЛОКАЛЬНО керованому табличному просторі з AUTO SEGMENT SPACE MANAGEMENT, і отримав таке повідомлення про помилку:

10618, 00000, “Operation not allowed on this segment”
// *Cause: This DBMS_SPACE operation is not permitted on segments in
// tablespaces with AUTO SEGMENT SPACE MANAGEMENT
// *Action: Recheck the segment name and type and re-issue the statement

Як знайти вільні блоки в цьому випадку?


Відповідь Тома Кайта:


Я просто думав, що список вільних блоків буде один. Якщо їх кілька, утиліта просто “недостатньо розумна”.


Для ASSM є процедура dbms_space.space_usage.


Ваша процедура show_space і секціонірованние таблиці


Я намагаюся використовувати вашу процедуру show_space, Але, схоже, вона не працює для секціонованих таблиць.


Я думаю, в курсорі

for x in ( select tablespace_name
from dba_tablespaces
where tablespace_name = ( select tablespace_name
from dba_segments
where segment_type = p_type
and segment_name = p_segname
and SEGMENT_SPACE_MANAGEMENT <> “AUTO”
)

в підзапит треба додати distinct


Відповідь Тома Кайта:


Ну, так додайте. Я змінюю цю процедуру у міру потреби.


Вільні блоки і прозводительности


Як впливає велике значення HWM, кількість вільних або невикористовуваних блоків на продуктивність при роботі з таблицею (INSERT / UPDATE / SELECT). У мене в практиці був випадок, коли пакет працював 9 хвилин на одному екземплярі (EDEV) І 2:00 на іншому (EPROD). Результат виконання вашої процедури та запиту до ALL_TABLES для обох примірників представлений нижче.


EDEV
Free Blocks 4
Total Blocks 1984
Total Bytes 16252928
Unused Blocks 1
Unused Bytes 8192
Last Used Ext FileId 112
Last Used Ext BlockId 5193
Last Used Block 15
EPROD
Free Blocks 20
Total Blocks 2352
Total Bytes 19267584
Unused Blocks 11
Unused Bytes 90112
Last Used Ext FileId 346
Last Used Ext BlockId 3065
Last Used Block 5
BLOCKS EMPTY_BLOCKS AVG_SPACE NUM_FREELIST_BLOCKS
2340 6 4462 2103
select blocks, empty_blocks,
avg_space, num_freelist_blocks
from user_tables
where table_name = “BACKLOG_ITEM”
BLOCKS EMPTY_BLOCKS AVG_SPACE NUM_FREELIST_BLOCKS
3956 11 4570 2004

Якщо я можу використовувати оператор TRUNCATE, Але в пакетному завданні виконується безліч операторів DELETE і INSERT, Як мені запобігти великі значення позначки максимального рівня заповнення? Чи немає якоїсь утиліти або сценарію для зменшення значення HWM для таблиці.


Відповідь Тома Кайта:


1) Обидві ці таблиці занадто маленькі. Якби у мене було “пакетне завдання”, яке 9 хвилин обробляє 20 мегабайтів даних, мене б одне це вже стурбувало. Це, ймовірно, на 8 з половиною хвилин довше, ніж повинно бути.


Використовуйте TKPROF і SQL_TRACE для пошуку найбільш істотною проблеми.


2) У вас дуже, дуже маленька таблиця. Я думаю, ви шукайте не в тому напрямку. Швидше за все, використовується поганий алгоритм. Треба знайти проблему і усунути її. Не “щось виправити” і подивитися, допомогло чи ні.


Коментар читача від 13 червня 2003


Спасибі за відповідь. Я абсолютно згоден, що продуктивність пакетного завдання, яке я згадував, може бути підвищена шляхом зміни алгоритму. Вибачте, якщо представлений приклад відвернув від “реальної” суті мого запитання.


Мене цікавить, як я можу використовувати результати, видаються вашої утилітою, при супроводі бази даних. Наприклад, чи є кореляція між кількістю вільних блоків і продуктивністю?


У моєму прикладі, чи можу я пов’язувати відмінність у часі виконання пакетного завдання на двох примірниках з кількістю зведених блоків? (Повторюся, що я згоден з тим, що продуктивність може бути підвищена.)


Ще один приклад: у мене є таблиця з приблизно 6 мільйонами рядків. Середня довжина рядка складає 1250 байтів. Ми виконуємо з цією таблицею безліч операторів “Delete / Insert / Update”. Ми недавно перестворити цю таблицю (використовуючи експорт, CREATE Table та імпорт). Ми помітили суттєву зміну продуктивності операторів SELECTS. Через деякий час їх продуктивність знову стала “нормальною”. Можу Чи я пов’язувати це з кількістю вільних блоків і чи не вважаєте ви, що потрібно постійно шукати такі блоки і “вичищати” їх, а якщо так, то як це зробити?.


Примітка: на цей раз я намагаюся знайти основну причину змін продуктивності. По ходу читання цього обговорення мені здалося, що я, можливо, знайшов “одну” з причин, і я хочу отримати ваше підтвердження. Я також хочу зазначити, що бази даних не сильно відрізняються з точки зору розміру, параметрів і т.п. Код теж не змінився.


Відповідь Тома Кайта:


Може бути, але в вашому прикладі розміри дуже вже невеликі. Мені здавалося абсолютно ясним, що, на мою думку, невелика кількість блоків у списку вільних не могло істотно ні на що вплинути …


Ні, нічого і ні з чим ви тут пов’язувати не можете. Для обгрунтованих висновків просто недостатньо даних.


Ви не сказали, як змінилася продуктивність, якого роду дії ви виконували з цією таблицею, взагалі нічого. Знову абсолютно недостатньо даних для будь-яких висновків про що б то не було (крім гіпотетичних міркувань, які я не дуже люблю). Тепер, якщо у вас є конкретні показники (отримані за допомогою tkprof або statspack) – Конкретні числові дані, які свідчать про кількість consistent gets, Плани запитів, вхідні дані і т.п. для всіх випадків, то, звичайно, можна буде зробити певні висновки …


(Але, на продуктивність запитів кількість блоків у списку вільних впливу не робить. Я можу встановити параметри pctfree/pctused так, що кожен блок буде в списку вільних. Я можу встановити параметри pctfree/pctused так, що ЖОДНОГО блоку в списку вільних не буде. Я можу організувати обидві ці таблиці так, що всі блоки у них будуть, фактично, “однакові”. При цьому продуктивність запитів до них буде однаковою. Вона ніяк не пов’язана з кількістю блоків у списку вільних (однак, ви можете робити певні висновки на основі цього показника, якщо розумієте, як встановлені параметри pctfree/pctused і як таблиці використовуються). Все пов’язано з тим, скільки блоків сервер Oracle повинен обробити, щоб виконати ваші запити.


Вам необхідний аналіз за допомогою TKPROF. Треба проаналізувати за допомогою TKPROF виконання цього “пакетного завдання” на dev і на prod. Треба порівняти результати. Це дозволить пройти 90% шляху до вихідної причини проблеми.


У чому тут може бути проблема?


Том,

я не можу використовувати процедуру show_space. Допоможи мені, будь ласка.

SQL> create user a identified by a;
User created.
SQL> grant create session, create procedure,
2 create table to a;
Grant succeeded.
SQL> alter user a quota unlimited on users;
User altered.
SQL> connect a/a
Connected.
SQL> @D:shareoracleasktomshow_space.sql
51 /
Procedure created.
SQL> create table t ( x int ) tablespace users;
Table created.
SQL> exec show_space( “T” )
BEGIN show_space( “T” ); END;
*
ERROR at line 1:
ORA-10618: Operation not allowed on this segment
ORA-06512: at “SYS.DBMS_SPACE”, line 74
ORA-06512: at “A.SHOW_SPACE”, line 22
ORA-06512: at line 1
SQL> desc t
Name Null? Type
————————————- ——– ——–
X NUMBER(38)
SQL> insert into t values(100);
1 row created.
SQL> desc dbms_space
PROCEDURE FREE_BLOCKS
Argument Name Type In/Out Default?
—————————— ———————– —— ——–
SEGMENT_OWNER VARCHAR2 IN
SEGMENT_NAME VARCHAR2 IN
SEGMENT_TYPE VARCHAR2 IN
FREELIST_GROUP_ID NUMBER IN
FREE_BLKS NUMBER OUT
SCAN_LIMIT NUMBER IN DEFAULT
PARTITION_NAME VARCHAR2 IN DEFAULT
PROCEDURE SPACE_USAGE
Argument Name Type In/Out Default?
—————————— ———————– —— ——–
SEGMENT_OWNER VARCHAR2 IN
SEGMENT_NAME VARCHAR2 IN
SEGMENT_TYPE VARCHAR2 IN
UNFORMATTED_BLOCKS NUMBER OUT
UNFORMATTED_BYTES NUMBER OUT
FS1_BLOCKS NUMBER OUT
FS1_BYTES NUMBER OUT
FS2_BLOCKS NUMBER OUT
FS2_BYTES NUMBER OUT
FS3_BLOCKS NUMBER OUT
FS3_BYTES NUMBER OUT
FS4_BLOCKS NUMBER OUT
FS4_BYTES NUMBER OUT
FULL_BLOCKS NUMBER OUT
FULL_BYTES NUMBER OUT
PARTITION_NAME VARCHAR2 IN DEFAULT
PROCEDURE UNUSED_SPACE
Argument Name Type In/Out Default?
—————————— ———————– —— ——–
SEGMENT_OWNER VARCHAR2 IN
SEGMENT_NAME VARCHAR2 IN
SEGMENT_TYPE VARCHAR2 IN
TOTAL_BLOCKS NUMBER OUT
TOTAL_BYTES NUMBER OUT
UNUSED_BLOCKS NUMBER OUT
UNUSED_BYTES NUMBER OUT
LAST_USED_EXTENT_FILE_ID NUMBER OUT
LAST_USED_EXTENT_BLOCK_ID NUMBER OUT
LAST_USED_BLOCK NUMBER OUT
PARTITION_NAME VARCHAR2 IN DEFAULT

Відповідь Тома Кайта:

create or replace procedure show_space
( p_segname in varchar2,
p_owner in varchar2 default user,
p_type in varchar2 default “TABLE”,
p_partition in varchar2 default NULL ) – Ця процедура використовує authid current user, щоб вона могла запитувати – Подання DBA_ *, використовуючи привілеї РОЛІ і щоб її можна було – Встановлювати в одному примірнику в базі даних, а не окремо для – Кожного користувача, якому вона необхідна
authid current_user
as
l_free_blks number;
l_total_blocks number;
l_total_bytes number;
l_unused_blocks number;
l_unused_bytes number;
l_LastUsedExtFileId number;
l_LastUsedExtBlockId number;
l_LAST_USED_BLOCK number;
l_segment_space_mgmt varchar2(255);
l_unformatted_blocks number;
l_unformatted_bytes number;
l_fs1_blocks number; l_fs1_bytes number;
l_fs2_blocks number; l_fs2_bytes number;
l_fs3_blocks number; l_fs3_bytes number;
l_fs4_blocks number; l_fs4_bytes number;
l_full_blocks number; l_full_bytes number;
– Вкладена процедура для видачі значень в красивому форматі – З простою міткою
procedure p( p_label in varchar2, p_num in number )
is
begin
dbms_output.put_line( rpad(p_label,40,”.”) //
to_char(p_num,”999,999,999,999″) );
end;
begin – Цей запит виконується динамічно, щоб можна було створити дану процедуру – Користувачем, які мають доступ до уявлень DBA_SEGMENTS / TABLESPACES – Через роль, як це зазвичай буває. – ПРИМІТКА: під час виконання, викликає ПОВИНЕН мати доступ до цих – Двом уявленням! – Цей запит визначає, чи є даний об’єкт об’єктом ASSM чи ні
begin
execute immediate
“select ts.segment_space_management
from dba_segments seg, dba_tablespaces ts
where seg.segment_name = :p_segname
and (:p_partition is null or
seg.partition_name = :p_partition)
and seg.owner = :p_owner
and seg.tablespace_name = ts.tablespace_name”
into l_segment_space_mgmt
using p_segname, p_partition, p_partition, p_owner;
exception
when too_many_rows then
dbms_output.put_line (“Це секціонірованная таблиця, використовуйте p_partition =>”);
return;
end;
– Якщо об’єкт розташований в табличному просторі ASSM, ми повинні використовувати – Цей виклик для отримання інформації про простір, інакше ми використовуємо – Виклик FREE_BLOCKS для сегментів, керованих користувачем
if l_segment_space_mgmt = “AUTO”
then
dbms_space.space_usage
( p_owner, p_segname, p_type, l_unformatted_blocks,
l_unformatted_bytes, l_fs1_blocks, l_fs1_bytes,
l_fs2_blocks, l_fs2_bytes, l_fs3_blocks, l_fs3_bytes,
l_fs4_blocks, l_fs4_bytes, l_full_blocks, l_full_bytes, p_partition);
p( “Unformatted Blocks “, l_unformatted_blocks );
p( “FS1 Blocks (0-25) “, l_fs1_blocks );
p( “FS2 Blocks (25-50) “, l_fs2_blocks );
p( “FS3 Blocks (50-75) “, l_fs3_blocks );
p( “FS4 Blocks (75-100)”, l_fs4_blocks );
p( “Full Blocks “, l_full_blocks );
else
dbms_space.free_blocks(
segment_owner => p_owner,
segment_name => p_segname,
segment_type => p_type,
freelist_group_id => 0,
free_blks => l_free_blks);
p( “Free Blocks”, l_free_blks );
end if;
– А потім ми викликаємо процедуру unused_space для отримання іншої – Інформації
dbms_space.unused_space
( segment_owner => p_owner,
segment_name => p_segname,
segment_type => p_type,
partition_name => p_partition,
total_blocks => l_total_blocks,
total_bytes => l_total_bytes,
unused_blocks => l_unused_blocks,
unused_bytes => l_unused_bytes,
LAST_USED_EXTENT_FILE_ID => l_LastUsedExtFileId,
LAST_USED_EXTENT_BLOCK_ID => l_LastUsedExtBlockId,
LAST_USED_BLOCK => l_LAST_USED_BLOCK );
p( “Total Blocks”, l_total_blocks );
p( “Total Bytes”, l_total_bytes );
p( “Total MBytes”, trunc(l_total_bytes/1024/1024) );
p( “Unused Blocks”, l_unused_blocks );
p( “Unused Bytes”, l_unused_bytes );
p( “Last Used Ext FileId”, l_LastUsedExtFileId );
p( “Last Used Ext BlockId”, l_LastUsedExtBlockId );
p( “Last Used Block”, l_LAST_USED_BLOCK );
end;
/

Спробуйте використовувати цю версію; схоже ви працюєте в 9i з використанням ASSM, застосовуючи стару версію з 8i – механізм assm не використовує списків вільних блоків.


Необхідний доступ до уявлень dba_ *


Це трохи напружує! Я звик використовувати цю чудову утиліту (show_space) В базах багатьох клієнтів (8i), для дослідження проблем з простором. По суті, її можна було використовувати в будь-якій схемі! Тепер, в 9i, мені потрібно просити привілеї доступу до цих уявлень. Не можна Чи це якось обійти?


Відповідь Тома Кайта:


Замість запит до уявлень dba_* ви можете самі передавати цю інформацію (в табличному просторі якого типу знаходиться об’єкт).


Використовуйте версію, аналогічну “8i”, але параметризуються її, щоб використовувався відповідний виклик.


Інші розміри екстентів


Спасибі за чудовий обговорення. Проте, в самому першому відповіді я так і не зрозумів, чому подання DBA_EXTENTS показує екстенти різних розмірів (тобто екстенти розміром 5, 5, 5, 10, 7, що дає в сумі 32 блоки). В ╨ те прикладі, ме не указЕвалі PCTINCREASE. Тому мені здається, що все екстенти повинні бути однакового розміру, і в одному екстента вільного місця повинно бути менше, ніж в інших через одну вставки. Проте, запит дає нам інший результат. Не могли б ви пояснити, як в DBA_EXTENTS виявилися екстенти зазначених розмірів.


Відповідь Тома Кайта:


Ви читали відповідь, яку я давав, з посиланням на документацію?


Коли ви просите 40 Кбайт з табличного простору, керованого за словником, і знаходиться вільний екстент, розмір якого відрізняється від запитаного не більше, ніж на 5 блоків (наприклад: 40k = 5 * 8k блоків – будь-який вільний екстент розміром 5, 6, 7, 8, 9 або 10 блоків буде використаний). Це робиться, щоб уникнути ситуації, коли при наявності вільного екстента розміром, скажімо, 7 блоків і запиті 5 блоків, ми беремо 5 і залишаємо 2 “абсолютно непотрібних” блоку.


Якщо б у вільному екстента було 11 блоків, вам би виділили ваші 5, а 6 залишилося б для наступного запиту.


Інакше залишалося б безліч вільних екстентів по 1/2/3 блоку, які ні для чого не можна було б використовувати.


Питання


1. Чому у вашому коді є обробник “EXCEPTION WHEN OTHERS THEN NULL“? Ви ж виступаєте різко проти приховування виняткових ситуацій, чи не так?


2. Я розумію, що конструкція AUTHID CURRENT_USER дозволяє встановлювати утиліту в базі даних в одному примірнику, і кожен викликає користувач не отримує додаткових привілеїв через використання прав творця.


Але як конструкція AUTHID CURRENT_USER забезпечує те, щоб процедура “могла запитувати подання DBA_ *, використовуючи привілеї РОЛІ”?


3. “- Цей запит виконується динамічно, щоб можна було створити дану процедуру користувачем, які мають доступ до уявлень DBA_SEGMENTS / TABLESPACES через роль, як це зазвичай буває.”


Натомість чому просто не використовувати подання ALL_*, Щоб EXECUTE IMMEDIATE взагалі не знадобився? Кожен користувач, що викликає цю процедуру, автоматично бачить те, що йому повинно бути доступно, тобто подання ALL_* вирішують всі проблеми за нас?


4. Які переваги дає нам використання PIPELINED у версії 9iR2 цієї утиліти?


5. Навіщо потрібна PRAGMA AUTONOMOUS_TRANSACTION?


Відповідь Тома Кайта:


1) Тому що так я отримую простий звіт; замість збою на півдорозі при виявленні об’єкта, для якого не можна отримати звіт, я просто пропускаю його.


2)

    l_sql := “select owner, segment_name, segment_type, partition_name
from dba_segments “;
add_predicate( “segment_name”, p_segname );
add_predicate( “owner”, p_owner );
add_predicate( “segment_type”, p_type );
add_predicate( “partition”, p_partition );
execute immediate “alter session set cursor_sharing=force”;
open l_cursor for l_sql;
execute immediate “alter session set cursor_sharing=exact”;

Я використав динамічний sql – Тому творці процедури доступ до DBA_* не потрібен, він потрібен тільки ВИЗИВЮЩЕМУ. І він при цьому зможе використовувати привілеї ролі, оскільки ролі враховуються при виконанні підпрограми з правами викликає.


3) Оскільки утиліта створювалася для DBA_. Подання DBA_ не містять фільтрів.


4) Для більшої ефективності – пошукайте pipelined в багатьох прикладах.


5) Не потрібна. Не знаю, про що я думав, коли залишив її в коді.


Помилка ORA-00943


Як уникнути помилки ORA-00943 при підрахунку вільних блоків за допомогою DBMS_SPACE.FREE_SPACE для кластерів, що належать іншому користувачеві, наприклад:

SQL> show user
USER is “TEST123”
SQL> var x number;
SQL>
SQL> exec dbms_space.free_blocks (“TEST”,”TEST_CLUSTER”,”CLUSTER”,0,:x);
BEGIN dbms_space.free_blocks (“TEST”,”TEST_CLUSTER”,”CLUSTER”,0,:x); END;
*
ERROR at line 1:
ORA-00943: cluster does not exist
ORA-06512: at “SYS.DBMS_SPACE”, line 74
ORA-06512: at line 1
SQL>
SQL> conn test/test@dev
Connected.
SQL> exec dbms_space.free_blocks (“TEST”,”TEST_CLUSTER”,”CLUSTER”,0,:x);
PL/SQL procedure successfully completed.
SQL> print x
X
———-
3
SQL> disc
Disconnected from Oracle9i Enterprise Edition Release 9.2.0.1.0 – Production
With the Partitioning, OLAP and Oracle Data Mining options
JServer Release 9.2.0.1.0 – Production

Питання 1. Чи є якась привілей, необхідна для вирішення цього завдання користувачем, що відрізняється від власника кластера?


Я намагався вЕполніть GRANT ALTER ANY CLUSTER TO TEST123, Але ╨ то не допомогло.


Відповідь Тома Кайта:

ops$tkyte@ORA9IR2> create user a identified by a default tablespace manual quota
unlimited on manual;

User created.

ops$tkyte@ORA9IR2> create user b identified by b;

User created.

ops$tkyte@ORA9IR2> grant create session, create cluster to a;

Grant succeeded.

ops$tkyte@ORA9IR2> grant create session to b;

Grant succeeded.

ops$tkyte@ORA9IR2> @connect a/a
ops$tkyte@ORA9IR2> set termout off
a@ORA9IR2> set termout on
a@ORA9IR2> create cluster test_cluster (x number) size 1024;

Cluster created.

a@ORA9IR2> @connect b/b
a@ORA9IR2> set termout off
b@ORA9IR2> set termout on
b@ORA9IR2> var x number;
b@ORA9IR2> exec dbms_space.free_blocks (“A”,”TEST_CLUSTER”,”CLUSTER”,0,:x)
BEGIN dbms_space.free_blocks (“A”,”TEST_CLUSTER”,”CLUSTER”,0,:x); END;

*
ERROR at line 1:
ORA-00943: cluster does not exist
ORA-06512: at “SYS.DBMS_SPACE”, line 74
ORA-06512: at line 1

b@ORA9IR2> @connect /
b@ORA9IR2> set termout off
ops$tkyte@ORA9IR2> set termout on
ops$tkyte@ORA9IR2> grant analyze any to b;

Grant succeeded.

ops$tkyte@ORA9IR2> @connect b/b
ops$tkyte@ORA9IR2> set termout off
b@ORA9IR2> set termout on
b@ORA9IR2> exec dbms_space.free_blocks (“A”,”TEST_CLUSTER”,”CLUSTER”,0,:x)

PL/SQL procedure successfully completed.


Кластери SYS дають ту ж помилку навіть за наявності привілеї “ANALYZE ANY”


Спасибі за відповідь.


Але навіть для щойно створеного кластеру у схемі SYS видається помилка:

SQL> show user
USER is “SYS”
SQL> l
1 create cluster test_cluster (dept number(2))
2 size 1024
3* index
SQL>
SQL> /
Cluster created.
SQL> create index test_cluster_index on cluster test_cluster;
Index created.
SQL> create table x
2 cluster test_cluster(deptno)
3 as select * from scott.dept;
Table created.
SQL> create table y
2 cluster test_cluster(deptno)
3 as select * from scott.emp;
Table created.
SQL> exec dbms_space.free_blocks(“SYS”,”TEST_CLUSTER”,”CLUSTER”, 0, :x);
PL/SQL procedure successfully completed.
SQL> print x
X
———-
1
SQL> grant analyze any to test;
Grant succeeded.
SQL> conn test/test
Connected.
SQL> show user
USER is “TEST”
SQL> var x number
SQL> exec dbms_space.free_blocks(“SYS”,”TEST_CLUSTER”,”CLUSTER”, 0, :x);
BEGIN dbms_space.free_blocks(“SYS”,”TEST_CLUSTER”,”CLUSTER”, 0, :x); END;
*
ERROR at line 1:
ORA-00943: cluster does not exist
ORA-06512: at “SYS.DBMS_SPACE”, line 74
ORA-06512: at line 1
SQL> disc
Disconnected from Oracle9i Enterprise Edition Release 9.2.0.1.0 – Production
With the Partitioning, OLAP and Oracle Data Mining options
JServer Release 9.2.0.1.0 – Production

Відповідь Тома Кайта:


Це результат вашої установки O7_DICTIONARY_ACCESSIBILITY, Пов’язаний із забезпеченням захисту – щоб захистити SYS від всього іншого.


Вам треба або виконувати цю утиліту як SYSDBA для аналізу схеми SYS (Переважно), або встановити O7_DICTIONARY_ACCESSIBILITY=true (Не рекомендується).


А що це за FS1 … FS4?


Я знайшов (і створив) утиліту Show_Space для LTM, але не можу знайти описи призначення нових рядків: Що таке “FS1(2,3,4) Blocks“? Що це за”Unformatted Blocks“?


Відповідь Тома Кайта:

     p( “Unformatted Blocks “, l_unformatted_blocks );
p( “FS1 Blocks (0-25) “, l_fs1_blocks );
p( “FS2 Blocks (25-50) “, l_fs2_blocks );
p( “FS3 Blocks (50-75) “, l_fs3_blocks );
p( “FS4 Blocks (75-100)”, l_fs4_blocks );
p( “Full Blocks “, l_full_blocks );
FS1 означає 0-25% вільного простору в блоці FS2 означає 25-50% вільного простору в блоці FS3 означає 50-75% вільного простору в блоці FS4 означає 75-100% вільного простору в блоці

Неформатований блоки (unformatted blocks) – це блоки, доступні для негайного використання (до реальної оцінки максимального рівня заповнення), але ще не містять ніяких даних. Коли таблиця каже: “Я заповнилася”, ми переносимо в таблицю групу блоків через HWM, і вони будуть неформатований, поки ви їх не використовуєте.


Ще одне питання


Я бачив ваш відповідь на це питання раніше, але я все одно не розумію: Як виходить, що Total Blocks не дорівнює Unformatted Blocks + FS1 Blocks + FS2 Blocks + FS3 Blocks + FS4 Blocks + Full Blocks + System Block (В даному прикладі, у мене залишається ще 660 блоків).

SQL> call show_space(“TCOM_PERFORMANCE_DATA”);
Unformatted Blocks ………………… 784
FS1 Blocks (0-25) ………………… 1
FS2 Blocks (25-50) ………………… 0
FS3 Blocks (50-75) ………………… 0
FS4 Blocks (75-100)………………… 225
Full Blocks ………………… 172,410
Total Blocks………………………. 174,080
Total Bytes……………………….. 1,426,063,360
Total MBytes………………………. 1,360
Unused Blocks……………………… 0
Unused Bytes………………………. 0
Last Used Ext FileId……………….. 5
Last Used Ext BlockId………………. 317,576
Last Used Block……………………. 2,048

Відповідь Тома Кайта:


Є блоки, які сервер Oracle використовує для управління вашими блоками.


У мене з DBMS_SPACE проблема

SQL*Plus: Release 8.1.7.0.0 – Production on Tue Oct 19 15:30:14 2004
(c) Copyright 2000 Oracle Corporation. All rights reserved.
Enter password:
Connected to:
Oracle8i Enterprise Edition Release 8.1.7.3.0 – Production
With the Partitioning option
JServer Release 8.1.7.3.0 – Production
SQL> select name from v$database;
NAME
———
EK_PLSHD
SQL> show user
USER is “SYSTEM”
SQL> column object_name format a30
SQL> column object_type format a30
SQL> set lines 120
SQL> select object_name, object_type, status, created, last_ddl_time
2 from dba_objects
3 where object_name = “DBMS_SPACE”
4 /
OBJECT_NAME OBJECT_TYPE STATUS CREATED
LAST_DDL_
—————————— —————————— ——- ———
———
DBMS_SPACE PACKAGE VALID 03-JUN-04
19-OCT-04
DBMS_SPACE PACKAGE BODY VALID 03-JUN-04
19-OCT-04
DBMS_SPACE SYNONYM VALID 03-JUN-04
19-OCT-04
SQL> desc dbms_space
PROCEDURE FREE_BLOCKS
Argument Name Type In/Out Default?
—————————— ———————– —— ——–
SEGMENT_OWNER VARCHAR2 IN
SEGMENT_NAME VARCHAR2 IN
SEGMENT_TYPE VARCHAR2 IN
FREELIST_GROUP_ID NUMBER IN
FREE_BLKS NUMBER OUT
SCAN_LIMIT NUMBER IN DEFAULT
PARTITION_NAME VARCHAR2 IN DEFAULT
PROCEDURE UNUSED_SPACE
Argument Name Type In/Out Default?
—————————— ———————– —— ——–
SEGMENT_OWNER VARCHAR2 IN
SEGMENT_NAME VARCHAR2 IN
SEGMENT_TYPE VARCHAR2 IN
TOTAL_BLOCKS NUMBER OUT
TOTAL_BYTES NUMBER OUT
UNUSED_BLOCKS NUMBER OUT
UNUSED_BYTES NUMBER OUT
LAST_USED_EXTENT_FILE_ID NUMBER OUT
LAST_USED_EXTENT_BLOCK_ID NUMBER OUT
LAST_USED_BLOCK NUMBER OUT
PARTITION_NAME VARCHAR2 IN DEFAULT
SQL> desc show_space
PROCEDURE show_space
Argument Name Type In/Out Default?
—————————— ———————– —— ——–
P_SEGNAME VARCHAR2 IN
P_OWNER VARCHAR2 IN DEFAULT
P_TYPE VARCHAR2 IN DEFAULT
SQL> select * from dba_tab_privs where table_name = “DBMS_SPACE”;
GRANTEE OWNER TABLE_NAME
—————————— ——————————
——————————
GRANTOR PRIVILEGE GRA
—————————— —————————————- —
PUBLIC SYS DBMS_SPACE
SYS EXECUTE NO
SQL> select * from dba_tab_privs where table_name = “SHOW_SPACE”;
GRANTEE OWNER TABLE_NAME
—————————— ——————————
——————————
GRANTOR PRIVILEGE GRA
—————————— —————————————- —
PUBLIC SYSTEM SHOW_SPACE
SYSTEM EXECUTE NO
SQL> exec show_space(“ETK_TEXT” , “DIC” );
BEGIN show_space(“ETK_TEXT” , “DIC” ); END;
*
ERROR at line 1:
ORA-00942: table or view does not exist
ORA-06512: at “SYS.DBMS_SPACE”, line 55
ORA-06512: at “SYSTEM.SHOW_SPACE”, line 20
ORA-06512: at line 1
SQL> exit
Disconnected from Oracle8i Enterprise Edition Release 8.1.7.3.0 – Production
With the Partitioning option
JServer Release 8.1.7.3.0 – Production

Схоже, що не вистачає якихось привілеїв на базову таблицю або подання, але я не знаю, яких; перестворення пакета за допомогою сценаріїв dbmsutil.sql і prvtutil.plb не допомагає: я отримую ту ж помилку.


Буду вдячний за будь-які підказки.


Відповідь Тома Кайта:


http://download-west.oracle.com/docs/cd/B10501_01/appdev.920/a96612/d_space.htm#1001674

див. розділ “Requirements“.


Проблеми пов’язані не з привілеями на пакет dbms_space, А з привілеями на сам об’єкт.


Будь ласка, не використовуйте SYS, SYSTEM або будь-яку іншу стандартну обліковий запис Oracle – використовуйте для всіх задач свої власні облікові записи.


Використовувати або не використовувати …


Завдяки вашим поясненням, я раз і назавжди перейшов до використання локально керованих табличних просторів. Але я все одно не розумію:


1) Коли використовувати, а коли не використовувати uniform extents або autoallocate.


2) Коли я використовую autoallocate, Розміри виділених мені екстентів визначає система. Це дивно, оскільки схоже на передбачення системою майбутнього. Чи ні?


3) Autoallocate виділяє екстенти різних розмірів. Це схоже на ситуацію з табличними просторами, керованими за словником. Привіт, фрагментація!


Відповідь Тома Кайта:


1) Мені подобається autoallocate – Це опція для “недалеких”.


Якщо ви точно знаєте, якого розміру буде об’єкт, ви можете використовувати uniform і підібрати правильний розмір екстентів.


Або, якщо ви хочете контролювати зростання ТОЧНО і знати, наскільки великим буде об’єкт спочатку і наскільки швидко він буде рости, можна використовувати uniform (Наприклад: об’єкт буде починатися з розміру 500 Мбайт, ми припускаємо, що він буде збільшуватися на 50 Мбайт в місяць. Можна використовувати однакові екстенти розміром 50 Мбайт і додавати по екстента на місяць, і ви зможете передбачити, коли додасться новий екстент).


2) Не зовсім так: система говорить, що в міру зростання об’єкта екстенти будуть ставати більше.


3) Ні, не зовсім – вони прекрасно поєднуються один з одним, оскільки використовується всього кілька різних розмірів.

Схожі статті:


Сподобалася стаття? Ви можете залишити відгук або підписатися на RSS , щоб автоматично отримувати інформацію про нові статтях.

Коментарів поки що немає.

Ваш отзыв

Поділ на параграфи відбувається автоматично, адреса електронної пошти ніколи не буде опублікований, допустимий HTML: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>

*

*