Том Кайт: про прискорення

Наш експерт визначає операційну систему, "прискорює" роботу додатків, пояснює особливості роботи з NLS-параметрами та написання чисел по буквах.

Питання. Я якось бачив на вашому сайті, як хтось показував, як визначити операційну систему, в якій працює утиліта SQL * Plus, а проте тепер я не можу знайти цю інформацію. У мене є SQL-скрипт, який я використовую для створення інших SQL-скриптів. Я хочу розширити цей скрипт так, щоб при його виклику на UNIX-платформі, на якій працює утиліта SQL * Plus, він створював би як SQL-скрипт, так і скрипт командної оболонки (shell script).

Відповідь. Я думаю, ви на сайті Ask Tom бачили, як визначити операційну систему, в якій працює сервер бази даних. Це можна зробити за допомогою функції DBMS_UTILITY.PORT_STRING:

SQL> begin
2 dbms_output.put_line(
3 dbms_utility.port_string );
4 end;
5 /

Linuxi386/Linux-2.0.34-8.1.0

Це говорить вам не про те, в якій операційній системі працює ваш клієнт SQL * Plus, а про те, в якій операційній системі працює сам сервер бази даних (вони можуть відрізнятися). Однак вам можуть допомогти два стовпці подання V $ SESSION – PROGRAM і PROCESS. Стовпець PROGRAM в загальному показує ім'я програми клієнта, яка з'єднана з сервером бази даних (але це ім'я може легко вводити в оману, якщо файли копіюються з іншими іменами), а стовпець PROCESS показує ідентифікатор процесу клієнта, сполученого з сервером бази даних – ідентифікатор процесу з самої клієнтської машини. Обидва цих стовпця допоможуть вам з'ясувати ім'я клієнтської операційної системи, в якій працює утиліта SQL * Plus. Виконаємо наступний запит:

SQL> select program, process.
2 from v$session
3 where sid =
4 (select sid
5 from v$mystat
6 where rownum = 1
7 )
8 /

PROGRAM PROCESS
———— ————–
sqlplus.exe 704:416

У даному випадку це – клієнт Windows SQL * Plus, це підтверджується наявністю ". Exe" в ім'я програм, а також двокрапкою (:) в ідентифікаторі процесу. Якщо ж для підключення до цього ж серверу бази даних я використовую UNIX-клієнта, я побачу щось схоже на це:

SQL> select program, process
.
.
.
8 /

PROGRAM PROCESS
————————- ————–
sqlplus@host(TNS V1-V3) 10227

В імені програми відсутній розширення ". Exe", оскільки воно не використовується в середовищі UNIX, а в ідентифікаторі процесу клієнта відсутня двокрапка, як це було в Windows-клієнта.

Початкове інтерактивне обговорення і розвиток це теми див. на сайті asktom.oracle.com/~tkyte/DetermineOS.html. Дякую всім інтерактивних учасників за хороші ідеї.

"Прискорює" роботу додатків

Питання. У нас є програма, яка створює користувачів і визначає для них приватні синоніми. Іноді адміністратор системи безпеки виконує множинні вилучення користувачів, яким більше не потрібен доступ до бази даних. Щоб видалити користувача, у якого є близько тисячі приватних синонімів може знадобитися близько двох хвилин. Я незадоволений таким занадто повільним видаленням вийшли з ужитку облікових записів. Чи є у вас якісь пропозиції щодо підвищення продуктивності виконання оператора DROP USER, не рахуючи переведення системи на використання публічних синонімів?

Відповідь. Вся справа в сприйнятті. Кожного разу коли я маю довго працює процес, я думаю, як його виконувати у фоновому режимі, щоб "нещасливий" кінцевий користувач ніколи не чекав його завершення. Якщо кінцевий користувач не повинен чекати завершення процесу, він буде здаватися йому спрацював миттєво.

Отже, будемо виконувати довго працює процес у фоновому режимі, і кінцевий користувач подумає: "Клас, справді він працює швидко"! Я рекомендую виконувати оператор DROP USER ім'я_користувача CASCADE наступним чином:

1. ALTER USER ім'я_користувача LOCK;
(Обліковий запис блокується, так що досягається "мета забезпечення безпеки".)
2. dbms_job.submit (l_job, "execute immediate" "drop user a cascade" ";");
3. commit;

Користувач відразу ж отримує повідомлення, що все в порядку. Блокування облікового запису забороняє їй доступ до бази даних, а фактичне видалення схеми користувача (на нього може знадобитися якийсь час) розпочнеться у фоновому режимі незабаром після виконання оператора COMMIT (кінцевий користувач не повинен чекати завершення видалення).

Я вдаюся до цього способу завжди, коли з'являються імовірно довго виконуються завдання – приховування реальної роботи, завдяки фонового режиму, і негайне продовження роботи кінцевих користувачів, так що вони думають, додаток працює набагато швидше, ніж це є насправді.

Не працює параметр NLS_DATE_FORMAT

Питання. Чому параметр NLS_DATE_FORMAT (формат дати) у моєму файлі init.ora іноді не працює? Я встановлюю його, але в моїх програмах формат дати за замовчуванням не встановлюється правильно.

Відповідь. Якщо в середовищі клієнта встановлені будь-які NLS-параметри, вони завжди перекривають NLS-параметри на стороні сервера. Наприклад, якщо клієнт встановить параметр NLS_LANG, всі NLS-параметри на стороні сервера будуть ігноруватися. Сервер буде використовувати значення, вказані клієнтом, і значення за замовчуванням для всіх інших NLS-параметрів, ігноруючи установки у файлі init.ora.

Зазвичай це відбувається в Windows-клієнтах. При інсталяції таких клієнтів у реєстрі за замовчуванням встановлюється параметр NLS_LANG. Вирішити вашу проблему можна одним з таких способів:


Особисто я віддаю перевагу другий спосіб. Якщо ваш додаток залежить від конкретного формату дати, що встановлюється за умовчанням, то його слід запитувати явно. Причина: якщо ви в одній системі бази даних інсталюєте два додатки з конфліктуючих форматами дати, то ви не зможете їх використовувати без явної установки форматів дат. Краще всього, щоб програми не залежали від конкретних установок форматів по типовий файл init.ora.

create or replace trigger
data_logon_trigger
after logon
ON DATABASE
begin
execute immediate
“alter session
set nls_date_format =
“”your format here”” “;
end;
/

Написання чисел по буквах

Питання. Я намагаюся писати числа по буквах. Тобто, я хочу щоб число 123 друкувалося як one hundred twenty-three. Чи є для цього відповідні функції?

Відповідь. Вірите чи ні, майже все це є. Є формат дат "Jsp", який дозволяє писати по буквах юліанському подання дати:

SQL> select to_char(sysdate,”J”),
2 to_char(sysdate,”Jsp”)
3 from dual;

TO_CHAR
—————-
TO_CHAR(SYSDATE,”JSP”)
——————————————
2453812
Two Million Four Hundred Fifty-Three
Thousand Eight Hundred Twelve

Це працює і для чисел у межах діапазону юліанських дат, інакше ви отримаєте повідомлення про помилку:

ERROR at line 1:
ORA-01854: julian date must be
between 1 and 5373484

Трохи творчості і я можу розширити цей діапазон (якщо число 5373484 недостатньо велике). Функція PL / SQL на лістингу 1 показує, як ви може зробити це ж. Я пропоную ознайомитися з інтерактивним обговоренням цієї теми на сайті asktom.oracle.com/~tkyte/SpellNumber.html, Там же ви можете побачити її розвиток, включаючи внесок учасників в написання чисел по буквах на інших мовах.






Лістинг 1: функція PL / SQL для написання чисел по буквах.
create or replace
function spell_number( p_number in number )
return varchar2
as
type myArray is table of varchar2(255);
l_str myArray := myArray( “”,
” thousand “, ” million “,
” billion “, ” trillion “,
” quadrillion “, ” quintillion “,
” sextillion “, ” septillion “,
” octillion “, ” nonillion “,
” decillion “, ” undecillion “,
” duodecillion ” );

l_num varchar2(50) default trunc( p_number );
l_return varchar2(4000);
begin
for i in 1 .. l_str.count
loop
exit when l_num is null;

if (to_number (substr (l_num, length (l_num) -2, 3)) <> 0)
then
l_return := to_char(
to_date(
substr(l_num, length(l_num)-2, 3),
“J” ),
“Jsp” ) // l_str(i) // l_return;
end if;
l_num := substr( l_num, 1, length(l_num)-3 );
end loop;

return l_return;
end;
/

Складання звітів про вільний простір в базі даних

Питання. Мені потрібно в утиліті SQL * Plus виводити звіти, які для кожного табличного простору показують вільний простір. Чи є у вас працює запит, який вміє це робити?

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

Проблема в тому, що в поданні DBA_FREE_SPACE вільний простір показується на рівні екстент, а в уявленнях DBA_DATA_FILES і DBA_TEMP_FILES показується виділений простір у файлах даних табличних просторів. Перед об'єднанням цих уявлень мені потрібно згрупувати їх дані на рівні табличних просторів. Для цього добре підходять вкладені уявлення, тому я буду використовувати їх у запиті, показаному на лістингу 2. Крім того, для пристосування запиту до табличним просторам, які повністю заповнені (у поданні DBA_FREE_SPACE відсутні записи про них), тому для отримання повної відповіді я буду використовувати зовнішнє з'єднання.






Лістинг 2: складання звіту про вільний простір в кожному табличному просторі.
set linesize 121
————————————————– —————————–
— free.sql

— This SQL Plus script lists freespace by tablespace
————————————————– —————————–

column dummy noprint
column pct_used format 999.9 heading "% / Used"
column name format a19 heading "Tablespace Name"
column Kbytes format 999,999,999 heading "Kbytes"
column used format 999,999,999 heading "Used"
column free format 999,999,999 heading "Free"
column largest format 999,999,999 heading "Largest"
column max_size format 999,999,999 heading "MaxPoss / Kbytes"
column pct_max_used format 999. heading "% / Max / Used"
break on report
compute sum of kbytes on report
compute sum of free on report
compute sum of used on report

 
select (select decode(extent_management,”LOCAL”,”*”,” “) //
decode (segment_space_management, "AUTO", "a", "m")
from dba_tablespaces where tablespace_name = b.tablespace_name) / /
nvl(b.tablespace_name,
nvl(a.tablespace_name,”UNKOWN”)) name,
kbytes_alloc kbytes,
kbytes_alloc-nvl(kbytes_free,0) used,
nvl(kbytes_free,0) free,
((kbytes_alloc-nvl(kbytes_free,0))/
kbytes_alloc)*100 pct_used,
nvl(largest,0) largest,
nvl(kbytes_max,kbytes_alloc) Max_Size,
decode (kbytes_max, 0, 0, (kbytes_alloc / kbytes_max) * 100) pct_max_used
from ( select sum(bytes)/1024 Kbytes_free,
max(bytes)/1024 largest,
tablespace_name
from sys.dba_free_space
group by tablespace_name ) a,
( select sum(bytes)/1024 Kbytes_alloc,
sum(maxbytes)/1024 Kbytes_max,
tablespace_name
from sys.dba_data_files
group by tablespace_name
union all
select sum(bytes)/1024 Kbytes_alloc,
sum(maxbytes)/1024 Kbytes_max,
tablespace_name
from sys.dba_temp_files
group by tablespace_name )b
where a.tablespace_name (+) = b.tablespace_name
order by 1
/

Цей запит дозволяє отримати:

 


Перетворення уявлень чисел в інші системи числення 1Вопрос. Як перетворювати числа в якісь інші системи числення (скажімо, з основою 2 або 16) і навпаки?

Відповідь. У відповіді дві частини. Починаючи з СУБД Oracle8i, Функції TO_CHAR і TO_NUMBER можуть перетворювати числа з основою 10 (десяткова система числення) в числа з підставою 16 (шістнадцяткова система числення) і навпаки:

SQL> select to_char(123,”XX”) to_hex,
2 to_number(“7B”,”XX”) from_hex
3 from dual
4 /

TO_ FROM_HEX
—— —————–
7B 123

Якщо вам потрібні інші системи числення, такі як вісімкова (з основою 8) або двійкова (з основою 2), ви можете зробити це дуже легко, використовуючи мову PL / SQL; насправді, я також буду перетворювати і числа з основою 16. Спочатку я напишу функцію, яка перетворює позитивні десяткові числа в числа з будь-яким іншим підставою – дощенту 36 (розширення алгоритму, що використовується для представлення чисел у різних системах числення, аж до шістнадцятковій системи числення). Див. лістинг 3.






Лістинг 3: перетворення десяткових чисел в числа з іншою підставою (до заснування 36).
 create or replace function to_base (p_dec in number, p_base in number)
return varchar2
is
l_str varchar2(255) default NULL;
l_num number default p_dec;
l_hex varchar2 (50) default "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
begin
if ( trunc(p_dec) <> p_dec OR p_dec < 0 ) then
raise PROGRAM_ERROR;
end if;
loop
l_str: = substr (l_hex, mod (l_num, p_base) +1, 1) / / l_str;
l_num := trunc( l_num/p_base );
exit when ( l_num = 0 );
end loop;
return l_str;
end to_base;
/

Тепер мені потрібна відповідна функція для зворотного перетворення чисел з будь-яким заданим підставою в десяткові числа. Вона показана на лістингу 4.






Лістинг 4: перетворення чисел з іншою підставою в десяткові числа.
create or replace function to_dec
( p_str in varchar2,
p_from_base in number default 16 ) return number
is
l_num number default 0;
l_hex varchar2 (50) default "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
begin
if (p_from_base = 16)
then
l_num := to_number( p_str, rpad(“x”,63,”x”) );
else
for i in 1 .. length(p_str) loop
l_num: = l_num * p_from_base + instr (l_hex, upper (substr (p_str, i, 1))) -1;
end loop;
end if;
return l_num;
end to_dec;
/

Для зручності я для найбільш поширених перетворень використовую невелику функцію, показану на лістингу 5.






Лістинг 5: поширені функції перетворення чисел в різні системи числення.
 create or replace function to_hex (p_dec in number) return varchar2
is
begin
return to_char( p_dec, “fm”//rpad(“x”,63,”x”) );
end to_hex;
/
create or replace function to_bin (p_dec in number) return varchar2
is
begin
return to_base( p_dec, 2 );
end to_bin;
/
create or replace function to_oct (p_dec in number) return varchar2
is
begin
return to_base( p_dec, 8 );
end to_oct;
/

Привілей SYSDBA

Питання. Мені потрібно в середовищі Microsoft Windows Server 2003 заборонити користувачам, які мають роль oradba підключення без пароля до сервера моєї бази даних. Коли я підключаюся як адміністратор (член групи oradba) я можу, вказуючи AS SYSDBA, підключитися до сервера з будь-яким паролем, навіть з порожнім.

Відповідь. Насправді, з технічної точки зору, ви використовували пароль. Ви увійшли в операційну систему, ввівши пароль.

Привілей SYSDBA – надзвичайно потужна привілей. Коли ви підключаєтеся, вказуючи AS SYSDBA, то використовується аутентифікація на рівні операційної системи; аутентифікація на рівні бази даних не потрібно. По суті, вона потрібна для підключення, коли ще не запущений екземпляр сервера бази даних. Вам потрібно обмежувати можливості облікових записів, які знаходяться в цій групі. Видаліть з неї користувачів, які не повинні мати такі надмірно великі можливості.

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


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

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

Ваш отзыв

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

*

*