Хотя упомянутые JOB, SCHEDULE, PROGRAM, WINDOW и проч., причисляются к объектам хранения БД (и видны в таблицах DBA/ALL/USEROBJECTS), не только их создание и удаление, но и изменение свойств выполняются так, как было удобно разработчику: через API. Для всех перечисленных видов объектов существует довольно много поведенческих свойств, указанию которых нет места в процедурах LIKE 'CREATE_%'. Устанавливать их следует явно единой для всех процедурой SET_ATTRIBUTE. Вот пример, как для задания MY_WINDOW_JOB (а) задать приоритет выполнения (по отношению к другим заданиям своего класса), если на одно время пришлось выполнение нескольких заданий одновременно, и (б) потребовать прекращения (процедурой STOP_JOB), если оно еще не выполнилось, а ресурсное окошко уже закрылось:
EXECUTE DBMS_SCHEDULER.DISABLE ( 'my_window_job', TRUE )
BEGIN DBMS_SCHEDULER.SET_ATTRIBUTE ( name => 'my_window_job' , attribute => 'JOB_PRIORITY' , value => 1 ); DBMS_SCHEDULER.SET_ATTRIBUTE ( name => 'my_window_job' , attribute => 'STOP_ON_WINDOW_CLOSE' , value => TRUE ) ); END; /
EXECUTE DBMS_SCHEDULER.ENABLE ( 'my_window_job' )
Полный список атрибутов и объектов, к которым они применимы, имеется в документации по Oracle.
,
преподаватель технологий Oracle
...Я старался дознаться у них, почему Нил, начиная от летнего солнцестояния, выходит из берегов и поднимается в течение приблизительно 100 дней; по истечении же этого срока вода снова спадает, ...и затем низкий уровень воды сохраняется целую зиму, вплоть до следующего летнего солнцестояния. Геродот, История |
В статье рассматриваются некоторые свойства и примеры употребления планировщика заданий, появившегося в версии Oracle 10 на смену старому.
Из самостоятельно существующих программы и расписания можно составить задание:
BEGIN DBMS_SCHEDULER.CREATE_JOB ( job_name => 'compound_j ob' , program_name => 'simple_program' , schedule_name => 'simple_schedule'
, enabled => TRUE ); END; /
При наличии параметра пример может выглядеть так:
BEGIN DBMS_SCHEDULER.CREATE_JOB ( job_name => 'compound_job1' , program_name => 'simple_program1' , schedule_name => 'simple_schedule' , enabled => FALSE ); END; /
BEGIN DBMS_SCHEDULER.SET_JOB_ANYDATA_VALUE ( job_name => 'compound_job1' , argument_name => 'DELTA' , argument_value => ANYDATA.CONVERTNUMBER ( 3 ) END; /
EXECUTE DBMS_SCHEDULER.ENABLE ( 'compound_job1' )
Обратите внимание, что в этом случае задание сначала создается выключенным, и только после указания значения параметра программе оно может включаться.
Простой запуск задания очень напоминает запуск с помощью процедуры SUBMIT из пакета DBMS_JOB. Однако, в отличие от SUBMIT, он возможен только при наличии привилегии CREATE JOB. В последующих примерах созданием заданий и управлением ими для простоты будет заниматься пользователь SCOTT, хотя в жизни разумно подумать об отдельном администраторе для этой цели. Выдадим пользователю SCOTT нужную привилегию:
CONNECT / AS SYSDBA GRANT CREATE JOB TO scott;
Кроме системных привилегий, использование планировщика регулируется объектными привилегиями EXECUTE, ALTER и ALL, выдача которых применительно (GRANT ... ON) к заданию, программе, расписанию или классу заданий позволяет работать с объектами БД типов JOB, PROGRAM, SCHEDULE и JOB CLASS соответственно, введенных в Oracle 10 вместе с новым планировщиком.
Ввиду того, что в дальнейшем предполагаются эксперименты с изменениями зарплаты сотрудников, будет удобно исходную зарплату сохранить:
CONNECT scott/tiger ALTER TABLE emp ADD ( oldsal NUMBER ); UPDATE emp SET oldsal = sal; COMMIT;
Более развитая возможность DBMS_SCHEDULER позволяет скомпоновать задание из независимых элементов: программы и расписания. Характерная особенность в том, что оба эти элемента самостоятельны; их можно комбинировать в разных заданиях и изменять, не внося изменений в определения заданий.
Очередной запуск внутреннего задания может прийтись на время активного использования ресурсов СУБД другими процессами. Это может замедлить выполнение планового задания, обесценить его выполнение и даже поставить его выполнение под угрозу. Справиться с этой проблемой призвано ресурсное окошко. Суть его состоит в одновременном с очередным запуском задания автоматическом переключении СУБД на работу по требуемому ресурсному плану (план поведения для распределителя ресурсов СУБД, resource manager). Сами ресурсные окошки (windows) принадлежат схеме SYS, но создавать их разрешено и другим пользователям при наличии соответствующей привилегии:
CONNECT / AS SYSDBA GRANT MANAGE SCHEDULER TO scott;
Ресурсный план построить несложно, но, чтобы не отвлекаться, воспользуемся встроенным в любую БД планом SYSTEM_PLAN (см. таблицу DBA_RSRC_PLANS). Тогда создание окошка может выглядеть так:
CONNECT scott/tiger
BEGIN DBMS_SCHEDULER.CREATE_WINDOW ( window_name => 'my_job_window' , resource_plan => 'SYSTEM_PLAN' , start_date => SYSTIMESTAMP , repeat_interval => 'FREQ=MINUTELY; INTERVAL=3' , duration => INTERVAL 4' MINUTE END; /
EXECUTE DBMS_SCHEDULER.ENABLE ( 'sys.my_job_window' )
Теперь каждые три минуты на минуту будет включаться ресурсный план SYSTEM_PLAN. Это легко наблюдать, выдав несколько раз от имени SYS:
COL window_name FORMAT A20 COL log_date FORMAT A4 0 SELECT * FROM ( SELECT log_date, window_name, operation FROM dba_scheduler_window_log ORDER BY log_date DESC ) WHERE ROWNUM
Если подгадать момент, когда значение OPERATION для окошка MY_JOB_WINDOW станет OPEN, от имени SYS можно будет удостовериться, что план включен:
SYS> SHOW PARAMETER resource
NAME TYPE VALUE -------------------------------------------------------------------------- resource_limit boolean FALSE resource_manager_plan string SCHEDULER[0xD5A4]:SYSTEM_PLAN
Чтобы связать с этим периодически открывающимся ресурсным окошком задание, пользователю SCOTT достаточно указать его вместо расписания:
Простой пример создания программы:
BEGIN DBMS_SCHEDULER.CREATE_PROGRAM ( program_name => 'simple_program'
, program_type => 'STORED_PROCEDURE' , program_action => 'updatesal' , enabled => TRUE ); END; /
Список сведений об имеющихся программах для планировщика имеется в таблицах DBA/ALL/USER_SCHEDULER_PROGRAMS.
Другими значениями параметра PROGRAM_TYPE могут быть 'PLSQL_BLOCK' и 'EXECUTABLE' (см. выше).
При наличии у процедуры параметров их количество потребуется указать особо:
CREATE PROCEDURE salary ( deer NUMBER ) AS BEGIN UPDATE emp SET sal = sal - deer; END; /
BEGIN DBMS_SCHEDULER.CREATE_PROGRAM ( program_name => 'simple_program1'
, program_type => 'STORED_PROCEDURE' , program_action => 'salary' , enabled => FALSE
, number_of_arguments => 1 ) ; END; /
Обратите внимание, что программа создана «отключенной». Дело в том, что указать фактические значения параметрам программе во «включенном» состоянии нельзя, так что последовательность действий будет следующая:
BEGIN DBMS_SCHEDULER.DEFINE_PROGRAM_ARGUMENT ( program_name => 'simple_program1'
, argument_position => 1 , argument_name => 'DELTA' , argument_type => 'NUMBER' ) ; END; /
EXECUTE DBMS_SCHEDULER.ENABLE ( 'simple_program1' )
Пример создания расписания:
BEGIN DBMS_SCHEDULER.CREATE_SCHEDULE ( schedule_name => 'simple_schedule'
, start_date => SYSTIMESTAMP , repeat_interval => 'FREQ=WEEKLY; BYDAY=MON, TUE, WED, THU, FRI' , end_date => SYSTIMESTAMP + INTERVAL '1' MONTH ) ; END; /
В общем случае язык указания графика для расписания (параметр REPEAT_INTERVAL) допускает ссылаться на ранее созданные таким же образом расписания.
Список сведений об имеющихся расписаниях для планировщика имеется в таблицах DBA/ALL/USER_SCHEDULER_SCHEDULES.
Совсем новым в планировщике Oracle 10 является возможность запускать плановые задания в ОС. Однако чтобы это было возможно, в ОС должна быть запущена программа extjob из ПО СУБД. На Windows она запускается службой OracleJobScheduler. Для того чтобы следующий пример проработал, службу необходимо запустить. Вдобавок потребуется выдать пользователю SCOTT еще одну привилегию.
Пример запуска:
CONNECT / AS SYSDBA GRANT CREATE EXTERNAL JOB TO scott;
CONNECT scott/tiger BEGIN DBMS_SCHEDULER.CREATE_JOB ( job_name => 'simple_job' , job_type => 'EXECUTABLE' , jobaction => 'cmd.exe /C dir > \temp\out.txt'
, enabled => TRUE ); END; /
Обратите внимание, что в Windows выдача команды ОС или же запуск командного файла напрямую (без вызова cmd.exe), не проходит.
В Unix аналогичное действие можно записать как 'ls > /tmp/out. txt'.
Пример внутреннего задания в виде неименованного блока PL/SQL:
BEGIN DBMS_SCHEDULER.CREATE_JOB
( job_name => 'simple_job' , jobtype => 'PLSQL_BLOCK' , job_action => 'UPDATE emp SET sal = sal +1;' , enabled => TRUE ); END; /
Обратите внимание:
Обрамлять блок словами BEGIN и END не обязательно, так как код пакета DBMS_SCHEDULER это сделает самостоятельно (ради особой программной логики, добавляемой им к тексту пользователя).
Задание запускается в этом же сеансе и сопровождается неявной выдачей COMMIT. В этом легко удостовериться:
COMMIT; UPDATE emp SET sal = sal + 1; BEGIN DBMS_SCHEDULER.CREATE_JOB (... как выше ...) END; ROLLBACK;
Зарплата SAL увеличится на 2. Проверить это в качестве упражнения.
Для хранимой процедуры задание формируется аналогично:
CREATE PROCEDURE updatesal AS BEGIN UPDATE emp SET sal = sal - 1; END;
/
BEGIN DBMS_SCHEDULER.CREATE_JOB ( job_name => 'simple_job' , jobtype => 'STORED_PROCEDURE' , job_action => 'updatesal' , enabled => TRUE ) ; END; /
Обратите внимание, что нам не потребовалось удалять старое задание SIMPLE_JOB, так как при выбранных нами параметрах процедуры CREATE_JOB задания (и первое, и второе) прогонялись однократно, моментально и сразу же удалялись автоматически. Последнее как раз можно и отменить посредством не использованного в примере выше параметра AUTO_DROP.
В случае невозможности запустить задание СУБД, подобно тому, как это делалось для старого планировщика (пакет DBMS_JOB), будет делать повторные попытки, но только по несколько иной схеме: через секунду, затем через 10 секунд, затем через 100 и далее – всего 6 раз, если только до этого не наступит очередной плановый момент.
Так же, как для пакета DBMS_JOB, в новом планировщике предусмотрено именно плановое, а не одноразовое исполнение задания. Добавим к последнему вызову параметр:
, start_date => SYSTIMESTAMP + INTERVAL '10' SECOND
В результете корневой файл out.txt получим через 10 секунд после создания задания. Добавим еще параметр:
, repeat_interval => 'FREQ=MONTHLY; BYDAY=SUN, -1 SAT'
В результате задание будет исполняться ежемесячно по воскресениям и последним субботам месяца. В отличие от DBMS_JOB, DBMS_SCHEDULER, в дополнение к возможности употребить выражение на PL/SQL, имеет для формулирования графика запуска еще и специальный язык. Он позволяет указывать частоту, интервал и уточнитель запуска задания. Примеры:
FREQ=HOURLY;INTERVAL=4 каждые 4 часа; FREQ=HOURLY;INTERVAL=4;BYMINUTE=10;BYSECOND=30 каждые 4 часа на 10-й минуте, 30-й секунде; FREQ=YEARLY;BYYEARDAY=-276 каждое 31-е марта; FREQ=YEARLY;BYMONTH=MAR;BYMONTHDAY=31 каждое 31-е марта;
Для проверки правильности составления выражения можно воспользоваться специальной процедурой:
DECLARE next_run_date TIMESTAMP; BEGIN DBMS_SCHEDULER.EVALUATE_CALENDAR_STRING ( 'FREQ=HOURLY;INTERVAL=4;BYMINUTE=10;BYSECOND=30'
, SYSTIMESTAMP , NULL , next_run_date ) ; DBMS_OUTPUT.PUT_LINE ( 'next_run_date: ' next_run_date ); END;
Полное описание языка приводится в документации по Oracle.
Если указать план запуска, задание появится в системе уже надолго. Удалить его при необходимости можно будет так:
EXECUTE DBMS_SCHEDULER.DROP_JOB ( 'simple_job', TRUE )
Информацию об имеющихся заданиях пользователь SCOTT может посмотреть запросом:
SELECT job_name, state, enabled FROM user_scheduler_jobs;
Более подробную информацию SCOTT обнаружит в таблицах USER_SCHEDULER_%, а более общую – в обычной таблице USER_OBJECTS.
Установленная в БД XML DB позволяет средствами СУБД, без привлечений внешнего контейнера сервлетов, организовать сервлетный доступ к данным в базе. Фактически это означает возможность организовать для доступа к данным сервер web «внутри СУБД». В статье показано на примерах, как это можно сделать.
Oracle XML DB поддерживает Java Servlet API версии 2.2 с некоторыми ограничениями, и с возможностью дополнительно установить сервлет поддержки JSP.
Подготовим текст сервлета в файле XMLDBServlet.java:
import java.io.PrintWriter; import java.io.IOException; import javax.servlet.GenericServlet; import javax.servlet.ServletRequest; import javax.servlet.ServletResponse; import javax.servlet.ServletException;
public class XMLDBServlet extends GenericServlet {
public void service ( ServletRequest request
, ServletResponse response
) throws ServletException, IOException {
String s = request.getParameter ( "rex" );
response.setContentType ( "text/xml" );
PrintWriter out = response.getWriter ( ); out.println ( "<?xml version=\"1.0\"?>" ); out.println ( "<html><head>" ); out.println ( "<title>My XMLDBServlet servlet demo</title>" ); out.println ( "</head><body>" ); out.println ( "<h2>Ave, " + s + " !</h2>" ); out.println ( "</body></html>" ); out.close ( ); } }
Пример ради общности рассматривает употребление суперкласса GenericServlet, а не HttpServlet.
Загрузим сервлет в БД одним из возможных способов:
>loadjava -grant public -u scott/tiger -r XMLDBServlet.java
Проверкой легко убедиться, что СУБД не только загрузит в БД исходный текст, но и получит из него класс.
Чтобы сервлет мог вызываться извне, сведения о нем требуется занести в ресурс-файл /xdbconfig.xml в репозитарии XML DB. Это файл с «объектно-реляционным» храненнем, и подправить его можно либо через WebDAV (системами, обеспечивающими такую правку), либо обычными функциями UPDATEXML и прочими. (Именно этот файл не допускает удаления из репозитария, поэтому выгрузить его, подправить и загрузить заново невозможно).
Однако при желании, для удобства правки файла /xdbconfig.xml можно использовать специально созданые для этого подпрограммы пакета DBMS_XDB. Выполним в SQL*Plus от имени пользователя XDB:
,
Преподаватель технологий Oracle
Люди часто совершают старые ошибки, но при этом ссылаются на новые обстоятельства. А. Эйнштейн. |
Сервлет DBURIServlet написан на C и готов для употребления при установленном репозитарии по адресу /oradb/схема_БД/имя_таблицы[...]. Тем не менее он параметризован, и поэтому представляет интерес для конечных потребителей БД.
Пример обращения:
Правила формирования адреса соответствуют правилам типа DBURITYPE.
Упражнение. Проверить работу сервлета DBURIServlet на следующих обращениях:
Сервлет DBURIServlet имеет параметры:
rowsettag - для смены имени корневого элемента, например:
contenttype - для указания типа MIME, например:
transform - для преобразования текста XML средствами XSLT.
Зарегистрируем в качестве ресурса /public/dept.xsl следующий текст:
<?xml version="1.0"?> <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" > <xsl:output method="html" />
<xsl:template match="ROW"> <tr> <td><xsl:value-of select="DEPTNO"/></td> <td><xsl:value-of select="DNAME"/></td> <td><xsl:value-of select="LOC"/></td> </tr> </xsl:template>
<xsl:template match="DEPT"> <html><head></head><body><title>Departments</title> <table border="3" bordercolor="green">
<xsl:apply-templates select="ROW"/>
</table> </body></html> </xsl:template>
</xsl:stylesheet>
Теперь обращение к XML DB по адресу:
даст следующий результат:
Текст с определением преобразования XSLT можно разместить и в таблице БД, обратившись за ним опять-таки через DBURITYPE примерно так:
transform=/oradb/SCOTT/XSLTDEFS/ROW[TAB='DEPT']/DEFINITION/text()
Упражнение. Создать таблицу XSLTDEFS с определением преобразования XSLT для таблицы DEPT (столбец TAB для имени таблицы и столбец DEFINITION для текста преобразования) и указать сервлету взять данные преобразования оттуда, а не из ресурса XML DB. Указание: поле DEFINITION определить типом VARCHAR2.
Прочие свойства сервлета приведены в документации по XML DB.
В каждом сеансе работы с СУБД можно использовать так называемые контексты, формально представляющие собой именованный набор пар «параметр/значение». Контексты сеансов обладают рядом интересных свойств, существенно повышающих «внутренние» возможности Oracle по созданию приложений. В статье рассматриваются два предопределенных контекста Oracle: USERENV и CLIENTCONTEXT.
,
Преподаватель технологий Oracle,
Узнаю милого по походке.
Поговорка.
,
Преподаватель технологий Oracle,
Сама садик я садила,
Сама буду поливать,
Сама милого любила,
Сама буду забывать.
Русская народная песня
«Обычный» контекст сеанса имеет своею областью действия отдельный сеанс. Иногда этого разработчику приложения вполне достаточно, а иногда хочется большего. Можно ли, например, запретить сеансу самостоятельно выставлять значение атрибута и предоставить ему только чтение, а значение задавать из другого сеанса? Такую возможность обеспечивает глобальный контекст сеанса, называемый еще иногда контекстом приложения. Пример его использования показан ниже:
CONNECT / AS SYSDBA
CREATE OR REPLACE CONTEXT globalcontext USING globalcontext_pckg
ACCESSED GLOBALLY
/
CREATE OR REPLACE PACKAGE globalcontext_pckg AS PROCEDURE set_value ( par VARCHAR2 , val VARCHAR2 , usr VARCHAR2
, usrid VARCHAR2
); END; /
CREATE OR REPLACE PACKAGE BODY globalcontext_pckg AS PROCEDURE set_value ( par VARCHAR2 , val VARCHAR2 , usr VARCHAR2 , usrid VARCHAR2 ) AS BEGIN DBMS_SESSION.SET_CONTEXT ( 'globalcontext' , par , val , usr
, usrid
); END; END; /
EXECUTE globalcontext_pckg.set_value - ( 'sesame' , '123', 'SCOTT', 'XYZ32A6' )
Проверка:
SQL> CONNECT scott/tiger Connected. SQL> SELECT SYS_CONTEXT ( 'globalcontext', 'sesame' ) FROM dual;
SYS_CONTEXT('GLOBALCONTEXT','SESAME') --------------------------------------------------------------------
SQL> EXECUTE DBMS_SESSION.SET_IDENTIFIER ( 'XYZ32A6' );
PL/SQL procedure successfully completed.
SQL> SELECT SYS_CONTEXT ( 'globalcontext', 'sesame' ) FROM dual;
SYS_CONTEXT('GLOBALCONTEXT','SESAME') -------------------------------------------------------------------- 123
SQL> EXECUTE DBMS_SESSION.SET_IDENTIFIER ( 'XYZ32A6ZZZ' );
PL/SQL procedure successfully completed.
SQL> SELECT SYS_CONTEXT ( 'globalcontext', 'sesame' ) FROM dual;
SYS_CONTEXT('GLOBALCONTEXT','SESAME') ----------------------------------------------------------------------
Тут есть сразу несколько интересных новшеств.
То, что контекст глобальный, было указано словами ACCESSED GLOBALLY при его создании. В процедуре DBMS_SESSION.SET_CONTEXT именно для глобального контекста существуют два дополнительных параметра. Первый сообщает, сеансам чьего пользователя будет доступен этот контекст (для каждого такого пользователя нужно будет выполнить отдельный вызов SET_CONTEXT), а второй - условное значение, которое необходимо будет сообщить для возможности прочитать установленное другим сеансом значения атрибута, своего рода пароль. Сообщение этого условного значения выполняется специальной процедурой DBMS_SESSION.SET_IDENTIFIER.
Таким образом, мало войти в СУБД под «правильным» пользователем; для того, чтобы получить в сеансе значение желаемого атрибута (глобального контекста), нужно будет еще сообщить условную строку. Излишне напоминать, что очевидным кандидатом на такую строку является cookie сеанса общения с web. И только благодаря этому, а также механизму избирательного доступа к частям таблицы в Oracle («виртуальные частные базы данных», VPD/FGAC) и возможности сервера приложений автоматически выдавать SET_IDENTIFIER при обращении к БД, многочисленные пользователи web, формально подключаемые к СУБД под одними и теми же именами пользователей Oracle, смогут увидеть в базе каждый собственные данные.
Еще один предопределенный контекст, с именем CLIENTCONTEXT, также не требует специального создания, однако в отличие от USERENV он позволяет сеансу создавать собственные атрибуты и задавать им значения. Особенность этого контекста в том, что он, в дополнение к обычному способу (изнутри сеанса), позволяет устанавливать значения атрибутам заранее, при открытии соединения с СУБД клиентской программой, и передавать их для обработки в сеанс. Делается это
либо через библиотеку OCI с помощью специального вызова OCIAppCtxSet
либо из программы на Java с помощью методов класса oracle.jdbc.internal.OracleConnection.
Тем самым контекст CLIENTCONTEXT способен при открытии сеанса передать информацию, дополнительную к традиционному имени пользователя и к ограниченному кругу сведений (адрес IP клиента, имя компьютера и пр.), доступному из контекста USERENV.
Значения переданных в сеанс атрибутов контекста CLIENTCONTEXT можно читать как обычно функцией SYS_CONTEXT, и изменять, но можно заводить и новые атрибуты:
SQL> CONNECT scott/tiger Connected. SQL> EXECUTE DBMS_SESSION.SET_CONTEXT ( 'CLIENTCONTEXT', 'a', 'b' )
PL/SQL procedure successfully completed.
SQL> SELECT SYS_CONTEXT ('CLIENTCONTEXT', 'a' ) FROM dual;
SYS_CONTEXT('CLIENTCONTEXT','A') -------------------------------------------------------------------- b
Если бы атрибут A был установлен клиентской программой на C или на Java перед установлением соединения, значение B мы бы увидели сразу.
Второе отличительное свойство контекста CLIENTCONTEXT в том, что Oracle разрешает именно для него обращаться к DBMS_SESSION.SET_CONTEXT напрямую (см. выше). Это исключение: контексты, которые разработчик пожелает создавать сам, позволят обращаться к DBMS_SESSION.SET_CONTEXT только из текста своей доверительной программной единицы.
Один контекст, с названием USERENV, создавать явным образом не требуется. Он доступен любому сеансу связи с СУБД Oracle в виде готового набора значений, разрешающего только прочтение, но не правку. Он позволяет узнать всевозможные сведения о сеансе, полезные для прикладного программирования. Ранее в Oracle существовала одноименная функция, но сейчас она поддерживается ради старых программ.
Пример информации, которую можно получить из контекста USERENV в программу:
COLUMN authent FORMAT A10 COLUMN curr_schema FORMAT A10 COLUMN curr_user FORMAT A10 COLUMN db_name FORMAT A10 COLUMN db_domain FORMAT A10 COLUMN host FORMAT A15 COLUMN ip_address FORMAT A15 COLUMN os_user FORMAT A15
SELECT SYS_CONTEXT ( 'userenv', 'AUTHENTICATION_TYPE' ) authent , SYS_CONTEXT ( 'userenv', 'CURRENT_SCHEMA' ) curr_schema , SYS_CONTEXT ( 'userenv', 'CURRENT_USER' ) curr_user , SYS_CONTEXT ( 'userenv', 'DB_NAME' ) db_name , SYS_CONTEXT ( 'userenv', 'DB_DOMAIN' ) db_domain , SYS_CONTEXT ( 'userenv', 'HOST' ) host , SYS_CONTEXT ( 'userenv', 'IP_ADDRESS' ) ip_address , SYS_CONTEXT ( 'userenv', 'OS_USER' ) os_user FROM dual ;
Полный список атрибутов контекста USERENV можно узнать из документации (в справочнике по SQL, в разделе, посвященному функции SYS_CONTEXT).
Вот пример того, как сведения из этого контекста помогают различить разные условия употребления конкретной программы:
CONNECT scott/tiger
CREATE PROCEDURE whoowns AS BEGIN DBMS_OUTPUT.PUT_LINE ( SYS_CONTEXT ( 'userenv', 'CURRENT_SCHEMA' ) ); DBMS_OUTPUT.PUT_LINE ( SYS_CONTEXT ( 'userenv', 'CURRENT_USER' ) ); DBMS_OUTPUT.PUT_LINE ( user ); END; /
Проверка:
SQL> SET SERVEROUTPUT ON SQL> EXECUTE whoowns SCOTT SCOTT SCOTT
PL/SQL procedure successfully completed.
SQL> ALTER SESSION SET CURRENT_SCHEMA = system;
Session altered.
SQL> EXECUTE scott.whoowns SCOTT SCOTT SCOTT
PL/SQL procedure successfully completed.
SQL> CONNECT / as sysdba Connected. SQL> SET SERVEROUTPUT ON SQL> EXECUTE scott.whoowns SCOTT SCOTT SYS
Для самостоятельного создания контекста служит специальная команда CREATE CONTEXT. Выдать ее (то есть создать контекст) может сеанс, имеющий полномочие CREATE ANY CONTEXT. Слово ANY в названии полномочия (привилегии) свидетельствует о том, что контекст - внесхемный объект в БД Oracle, такой, например, как роль, и отличный, например, от таблицы.
Для каждого контекста требуется указать специальную «доверительную» программную единицу: процедуру, функцию или пакет. Именно из тела этой программной единицы Oracle разрешит обращаться к процедуре DBMS_SESSION.SET_CONTEXT. Принято такое неочевидное решение во имя безопасности, так как доступ к хранимым программным единицам регулируется уже готовым механизмом привилегий.
Выше было показано, как атрибуты контекстов выставляются в процессе сеанса связи с СУБД. Однако по подобию с CLIENTCONTEXT создаваемый контекст тоже можно обеспечить начальными значениями требуемых атрибутов из программы, открывающий сеанс. Это можно сделать
средствами OCI (вызовы OCIAttrSet и OCISessionBegin) и через сервер имен (каталог) LDAP.
Возможность таких начальных присвоений обеспечивается соответствующими указаниями при создании контекста:
CREATE CONTEXT ... INITIALIZED EXTERNALLY и
CREATE CONTEXT ... INITIALIZED EXTERNALLY
Начальные значения атрибутов контекста для сеансов - очень сильное средство, позволяющее наложить на относительно примитивный механизм внутренних пользователей БД инфраструктуру внешних пользователей, часто более проработанную и универсальную. Например, сервер приложений может поддерживать очень много пользователей web-страниц, обладающих собственными свойствами. Моделировать их отдельными локальными для Oracle пользователями может оказаться крайне неэффективно, и в этом случае возможность предварительного установления атрибутов перед обращением к БД будет давать единственный ключ к построению решения.
Положим, доверительной программной единицей должна быть процедура SET_MYCONTEXT_VALUE:
CONNECT / as sysdba
CREATE OR REPLACE CONTEXT mycontext USING set_mycontext_value;
Обратите внимание, что процедура не обязана существовать в момент создания контекста. Но в конце концов ее-таки потребуется создать:
CREATE OR REPLACE PROCEDURE set_mycontext_value ( par IN VARCHAR2 , val IN VARCHAR2 ) AS BEGIN DBMS_SESSION.SET_CONTEXT ( 'mycontext', par, val ); END; /
GRANT EXECUTE ON set_mycontext_value TO scott;
Проверка:
SQL> CONNECT scott/tiger Connected. SQL> SELECT SYS_CONTEXT ( 'mycontext', 'sesame' ) FROM dual;
SYS_CONTEXT('MYCONTEXT','SESAME') ------------------------------------------------------------
SQL> EXECUTE sys.set_mycontext_value ( 'sesame', '123' )
PL/SQL procedure successfully completed.
SQL> SELECT SYS_CONTEXT ( 'mycontext', 'sesame' ) FROM dual;
SYS_CONTEXT('MYCONTEXT','SESAME') ------------------------------------------------------------ 123
Выше серым фоном выделена пустая строка.
С помощью контекста MYCONTEXT и доступной ему процедуры пользователь SCOTT завел значение, которое сможет читать и переустанавливать в собственном сеансе вплоть до завершения. Другой сеанс пользователя SCOTT создаст и будет использовать с помощью этого же контекста свои значения, то есть значения контекста являются собственностью сеанса.
Значения атрибутов контекста живут не долее пределов сеанса и защищены от доступа из других сеансов. В течение сеанса значения переменных пакета могут пропасть («сброс» пакета, хотя пользователи и нечасто прибегают к нему), и значения атрибутов контекста тоже (с помощью пакета DBMS_SESSION). Этим атрибуты схожи с переменными пакета. Но есть и отличия:
в пакете набор переменных фиксирован, а набор атрибутов контекста произволен переменные пакета могут быть разнообразны по структуре, а значения атрибутов контекста - всего лишь строки текста атрибутам контекста можно устанавливать до сеанса и делать доступными в другом сеансе.
Вот еще пример использования нашего контекста:
SQL> EXECUTE set_mycontext_value - > ( 'start work', TO_CHAR ( SYSDATE, 'hh24:mi:ss' ) )
PL/SQL procedure successfully completed.
SQL> REMARK выполняем работу, после чего смотрим когда начинали ...
SQL> SELECT SYS_CONTEXT ( 'mycontext', 'start work' ) FROM dual;
SYS_CONTEXT('MYCONTEXT','STARTWORK') -------------------------------------------------------------------- 13:58:06
Если запросить структуру справочной таблицы доступных контекстов, то видно, что поле для доверительной программной единицы названо PACKAGE:
SQL> SELECT * FROM all_context;
NAMESPACE SCHEMA PACKAGE
---------------------- ---------------------- ---------------------- MYCONTEXT SYS SET_CONTEXT_VALUE
Это не случайно: на практике часто более технологично установку контекста выполнять с помощью доверительного пакета, а не самостоятельной процедуры или функции. Ведь в состав пакета можно включить и прочие программные элементы, моделирующие логику предметной области.
Пример:
CONNECT / as sysdba
CREATE OR REPLACE CONTEXT mycontext USING mycontext_pckg;
CREATE OR REPLACE PACKAGE mycontext_pckg IS PROCEDURE set_value ( par VARCHAR2, val VARCHAR2 ); FUNCTION get_value ( par VARCHAR2 ) RETURN VARCHAR2; END; /
CREATE OR REPLACE PACKAGE BODY mycontext_pckg IS PROCEDURE set_value ( par VARCHAR2, val VARCHAR2 ) IS BEGIN DBMS_SESSION.SET_CONTEXT ( 'mycontext', par, val ); END;
FUNCTION get_value ( par VARCHAR2 ) RETURN VARCHAR2 IS BEGIN RETURN SYS_CONTEXT ( 'mycontext', par ); END; END; /
GRANT EXECUTE ON mycontext_pckg TO scott;
Проверка:
SQL> CONNECT scott/tiger Connected. SQL> SELECT sys.mycontext_pckg.get_value ( 'sesame' ) FROM dual;
SYS.MYCONTEXT_PCKG.GET_VALUE('SESAME') ---------------------------------------------------------------------
SQL> EXECUTE sys.mycontext_pckg.set_value ( 'sesame', '123' )
PL/SQL procedure successfully completed.
SQL> SELECT sys.mycontext_pckg.get_value ( 'sesame' ) FROM dual;
SYS.MYCONTEXT_PCKG.GET_VALUE('SESAME') --------------------------------------------------------------------- 123
Пакет можно спроектировать и иначе, закрыв, например, для пользователя имя атрибута или даже контекста. Можно запрограммировать все, что требует логика предметной области.
, Oracle Certified Professional DBA,
Источник:
,Январь/Февраль 2004
В данной статье описывается один из многих аспектов использования хранимых шаблонов при настройке производительности приложений использующих СУБД Oracle. В частности, приводится пример их использования для настройки приложений, к исходному коду которых, группа сопровождения не имеет доступа. Приводимый пример был испытан в Oracle 9i release 2. Для выполнения SQL выражений использовалась приложение SQL*Plus.
В практике сопровождения довольно часто приходится сталкиваться с задачей настройки производительности приложений, доступ к коду которых не представляется возможным. А производительность приложения сильно страдает из-за нескольких SQL выражений имеющих подсказки оптимизатору (optimizer hints) используя которые оптимизатор выбирает неоптимальный план выполнения SQL выражения. Особенно данная проблема имеет место при переходе организации на новые версии Oracle при использовании уже зарекомендовавших себя с хорошей стороны приложений, к которым все уже привыкли, однако вдруг начавших "жутко тормозить" на новой версии Oracle. Перехватив поток SQL выражений группа ИТ отдела определяет, что причина низкой производительности - подсказки, удалением которых можно добиться восстановления быстродействия. Однако сотрудники ИТ отдела не имеют доступа к исходному коду приложения и поэтому убрать "хинты" не представляется возможным.
Решить подобные проблемы можно используя хранимые шаблоны.
Русскоязычное описание использования хранимых шаблонов для стабилизации плана выполнения SQL выражений хорошо представлено в книге Тома Кайта "Oracle для профессионалов" (Thomas Kyte "Expert One on One: Oracle"), в переводе В. Кравчука, а так же на сайте (http://ln.com.ua/~openxs/projects/oracle/) автора перевода.
Итак, перейдем к примеру. Начнем с постановки задачи. Допустим мы имеем SQL выражение содержащее подсказку /*+ RULE*/. Наша задача - избавиться от этой подсказки.
Подготовим окружение. Создадим таблицу, составной индекс и соберем статистику. Таблица представляет собой некий словарь и содержит список словарей, каждый из которых, содержит некий список сущностей:
Кажется, есть только один способ сгенерировать хранимый шаблон, использование которого в длительной перспективе не сопряжено с риском-- надо быть как можно честнее. Генерировать шаблон нужно в той же схеме и для тех же объектов.
В нашем случае, надо удалить индекс по первичному ключу, сгенерировать план, а затем заменить первичный ключ!
Конечно, вы можете и не захотеть делать это в производственной системе, а если и захотите, может оказаться, что шаблон начнет использовать полный просмотр таблицы.
В итоге, чтобы получить требуемый шаблон необходимо иметь запасную копию схемы (с тем же именем и структурой) в другой базе данных и очень осторожно манипулировать объектами в этой схеме. После получения необходимого шаблона, можно экспортировать его из этой базы данных и импортировать в другую.
Например: в запасной базе данных вполне можно будет удалить первичный ключ, чтобы избежать сканирования (unique scan) соответствующего индекса. Если после этого сервер Oracle не начнет использовать другой индекс автоматически, можно всеми возможными способами обманывать его, например:
Изменить режим оптимизации на first_rows.
Создать данные, уникальные по столбцу N1. (Не создавайте, однако, по нему уникальный индекс, иначе в сгенерированном шаблоне будет указано действие unique scan вместо range scan).
Используйте средства пакета dbms_stats чтобы сказать, что индекс имеет фантакстическую степень кластеризации (clustering_factor).
Используйте параметр optimiser_index_caching чтобы сказать, что индекс на 100% кэширован.
Используйте параметр optimiser_index_cost_adj чтобы сказать, что чтение по несколько блоков (multiblock read) в 100 раз медленнее, чем чтение по одному блоку (single block read).
Используйте средства пакета dbms_stats чтобы задать те же утверждения через таблицу aux_stats$, и добавте также утверждение, что обычно при чтении нескольких блоков читается только два блока.
Пересоздайте индекс так, чтобы он включал оба столбца, заданные в конструкции where.
С учетом текущей струтуры таблиц, в которых хранятся шаблоны, подойдет практически любой способ, если не меняется владелец таблицы, тип объекта и уникальность (или неуникальность) индексов. Если вы можете создать набор данных и среду, которые дают требуемый шаблон без внутренних несогласованностей в производственной системе, то, какие именно трюки при этом использовались, уже не важно.
Если подключиться к схеме outln (которая по умолчанию в Oracle 9 заблокирована) и посмотреть список имеющихся таблиц, окажется, что в Oracle 9 добавлена одна таблица. В схему входят следующие таблицы:
ol$ - SQL-операторы ol$hints - подсказки ol$nodes - блоки запроса
Третья таблица - новая; она используется для привязки списка подсказок к различным блокам во (внутренне переписанной) версии SQL-запроса. Также можно обнаружить, что список подсказок (ol$hints) дополнен подпробностями о длине и смещении фрагментов текста.
Столбцы всех трех таблиц представлены на рис. 2, причем, новые столбцы, появившиеся в версии Oracle 9, помечены звездочками.
ol$
OL_NAME VARCHAR2(30) SQL_TEXT LONG TEXTLEN NUMBER SIGNATURE RAW(16) HASH_VALUE NUMBER HASH_VALUE2 NUMBER *** CATEGORY VARCHAR2(30) VERSION VARCHAR2(64) CREATOR VARCHAR2(30) TIMESTAMP DATE FLAGS NUMBER HINTCOUNT NUMBER SPARE1 NUMBER *** SPARE2 VARCHAR2(1000) ***
ol$hints
OL_NAME VARCHAR2(30) HINT# NUMBER CATEGORY VARCHAR2(30) HINT_TYPE NUMBER HINT_TEXT VARCHAR2(512) STAGE# NUMBER NODE# NUMBER TABLE_NAME VARCHAR2(30) TABLE_TIN NUMBER TABLE_POS NUMBER REF_ID NUMBER *** USER_TABLE_NAME VARCHAR2(64) *** COST FLOAT(126) *** CARDINALITY FLOAT(126) *** BYTES FLOAT(126) *** HINT_TEXTOFF NUMBER *** HINT_TEXTLEN NUMBER *** JOIN_PRED VARCHAR2(2000) *** SPARE1 NUMBER *** SPARE2 NUMBER ***
ol$nodes (новая таблица в версии 9)
OL_NAME VARCHAR2(30) CATEGORY VARCHAR2(30) NODE_ID NUMBER PARENT_ID NUMBER NODE_TYPE NUMBER NODE_TEXTLEN NUMBER NODE_TEXTOFF NUMBER
Рис. 2. Таблицы в схеме outln.
Пара нюансов бросается в глаза сразу -- представления, созданные на базе этих таблиц, не включают массу полезной информации. Хотя в таблице ol$hints и появилось 10 новых столбцов, определение представления user_outline_hints не изменилось. Фактически, это представление и в Oracle 8 было слишком урезанным, не включая, в частности, весьма информативный столбец hint#.
Обратите также внимание, что в Oracle 9 теперь есть два столбца hash_value. Если задать два одинаковых оператора на серверах Oracle 8 и Oracle 9, окажется, что значения в столбце hash_value для них совпадают, но вот добавленный в Oracle 9 столбец hash_value2, скорее всего, имеет совсем другое значение.
Прежде всего, можно обратить внимание на пакет dbms_outln_edit. Он появился в Oracle 9 и, как следует из его имени, предназначен для редактирования хранимых шаблонов, что выглядит многообещающе.
Однако при просмотре описания пакета и чтении руководств оказывается, что в пакет входят только следующие процедуры, связанные с "редактированием":
CREATE_EDIT_TABLES DROP_EDIT_TABLES CHANGE_JOIN_POS
Первые две процедуры позволяют создавать и удалять локальные копии таблиц, обычно находящихся в схеме outln. Третья позволяет изменять порядок соединения таблиц в сохраненном плане. Нет ни одной процедуры, позволяющей просто изменить одну подсказку. В настоящее время этот пакет кажется практически бесполезным, но он со временем, несомненно, станет более "продвинутым".
Запасной вариант, конечно же, связан с непосредственным изменением таблиц! Если подключиться от имени пользователя outln и изучить содержимое таблицы ol$hints (на базе которой построено представление user_outline_hints), можно попытаться выполнить следующее изменение:
update ol$hintsset hint_text = 'INDEX(T1 T1_I1)' where ol_name = 'demo_1' and hint# = 4;
Снова подключившись к тестовой схеме, сбросив содержимое разделяемого пула и включив использование хранимых шаблонов:
connect test_user/test alter system flush shared_pool; alter session set use_stored_outline=true;
можно убедиться, что измененный таким образом план, действительно, работает как требовалось. Но это решение не идеально, если учесть обычные строгие предупреждения о возможных последствиях "непосредственного изменения словаря данных".
Что делать, если известно, как существенно ускорить работу оператора ЯМД, добавив несколько подсказок, но нет доступа к исходному коду, в котором можно было бы вставить эти подсказки?
В предыдущей статье я показал, как можно воспользоваться для этого средствами создания хранимых шаблонов (или стабилизацией плана оптимизатора) сервера.
Хранимый шаблон состоит (грубо говоря) из двух компонентов- SQL-оператора, выполнение которого необходимо контролировать, и списка подсказок, которые сервер Oracle должен применять при каждой оптимизации этого оператора. Оба компонента хранятся в базе данных в схеме outln.
Можно просмотреть список хранимых SQL-операторов м подсказок, которые с ними связаны, с помощью пары запросов, представленных на рис. 1.
select name, used, sql_text from user_outlines where category = 'DEFAULT';
select stage, node, hint from user_outline_hints where name = '{одно из имен}';
Рис. 1. Просмотр хранимых шаблонов.
В предыдущей статье я изложил идею, как "обойти" систему путем создания хранимого шаблона законными методами, а затем - изменения таблиц в схеме outln с помощью пары SQL-операторов, заменяющих полученный результат на данные хранимого шаблона, созданного для аналогичного оператора, но с необходимыми подсказками.
Там же я указал, что этот метод был вполне безопасен в Oracle 8, но может привести к проблемам в Oracle 9 в связи с изменениями в новой версии.
В данной статье рассматриваются эти изменения и описывается законный способ регистрации необходимого набора подсказок для проблемных запросов в таблицах outln.
Oracle 9i Release 2: Database Performance Tuning Guide and Reference -- .
Oracle 9i Release 2: Supplied PL/SQL Packages and Types Reference -- Главы - .
--
Джонатан Льюис () - независимый консультант с более чем 17-летним опытом использования Oracle. Он специализируется на физическом проектировании баз данных и стратегии использования сервера Ortacle. Джонатан - автор книги "Practical Oracle 8i - Designing Efficient Databases", опубликованной издательством Addison-Wesley и один из наиболее известных лекторов среди специалистов по Oracle в Великобритании. Подробнее о его публикациях, презентациях и семинарах можно узнать на сайте , где также находится список ЧаВО The Co-operative Oracle Users' FAQ
по дискуссионным группам Usenet, связанным с СУБД Oracle.
Эта первоначально была опубликована на сайте , сетевом портале, посвященном проблемам различных СУБД и их решениям. Перевод публикуется с разрешения автора.
Наша цель, таким образом, - найти действенный, но достаточно безопасный метод изменения содержимого таблиц шаблонов, не связанный с непосредственным изменением их данных с помощью SQL-операторов.
Исторически (до версии 9) это можно было сделать несколькими способами, основанными на том факте, что содержимое шаблона зависело исключительно от текста выполняемого SQL-оператора, а не от типа или принадлежности упоминаемых в нем объектов.
Первый способ (первоначально описанный, насколько я знаю, Томом Кайтом в его книге "Expert One on One: Oracle") ("Oracle для профессионалов" в моем переводе на русский - прим. переводчика) связан с заменой таблиц представлениями, содержащими необходимые подсказки.
Подключаемся к другой схеме, имеющей доступ к таблице T1, и создаем представление с подсказками с тем же именем, что и исходная таблица:
Create or replace view t1 as Select /*+ index(t1,t1_i1) */ * from test_user.t1;
После создания этого представления, используем эту схему для "перекомпиляции" существующего шаблона с помощью команды:
alter outline demo_1 rebuild;
Учтите, что для успешного выполнения этой команды необходима привилегия alter any outline.
Если вернуться в исходную схему, сбросить содержимое разделяемого пула и включить использование хранимых шаблонов, окажется, что исходный запрос теперь использует индекс T1_I1, что и требовалось.
Почему этот способ работает? Потому что хранимые шаблоны не принадлежат никакой схеме. При пересоздании шаблона по имени demo_1 в новой схеме, имя T1 обозначает локальное представление, содержащее подсказку, поэтому сервер Oracle учитывает эту подсказку в реальном плане выполнения, и, следовательно, в шаблоне. Если обратиться к представлению user_outline_hints, можно обнаружить, что критическая строка действительно имеет вид:
3 1 INDEX(T1 T1_I1)
К сожалению, можно также заметить, что теперь в представлении есть три строки вида:
2 1 NOREWRITE 1 2 NOREWRITE 1 1 NOREWRITE
Первоначально таких строк было только две:
2 1 NOREWRITE 1 1 NOREWRITE
Мы также добавили подсказку, применяющуюся для 'Stage 1, Node 2' ("Стадия 1, Пункт 2"). Я не берусь утверждать, что точно знаю, что это означает, но это должно быть связано с тем, что при анализе и оптимизации запроса из другой схемы сервер Oracle выполнил дополнительный шаг, преобразуя ссылку на представление в ссылку на базовую таблицу.
Хотя пока что это не мешает правильному применению полученного шаблона (по крайней мере, в этом простом случае), кто знает, насколько может измениться в этом отношении сервер Oracle в следующих версиях.
Поскольку использование представлений приводит к аномалии, которая в будущих версиях может обернуться ошибкой, надо использовать более четкое решение. Давайте попробуем выполнить следующее:
Создадим новую схему.
Создадим таблицу T1 в этой схеме.
Создадим ТОЛЬКО индекс T1_I1.
Перестроим шаблон в этой схеме.
Если сравнить содержимое представления user_outline_hints для нашего шаблона до и после перестройки (для этого необходимо будет снова подключиться к исходной схеме), окажется, что они идентичны за исключением той единственной строки, которую мы хотели изменить. Снова подключившись к исходной схеме и, как обычно, сбросив разделяемый пул и включив использование шаблонов, мы увидим, что измененный шаблон успешно используется.
Однако в этом методе есть и скрытая проблема, на этот раз, немного более тонкая. Возвращаясь к рис. 2, на котором представлены определения новых столбцов, появившихся в Oracle 9, - как вы думаете, какая информация содержится в столбце user_table_name? Там хранится уточненное имя таблицы; т.е.:
{имя_пользователя}.{имя_таблицы}
В нашем случае это позволит серверу Oracle понять, что таблица T1, фактически, принадлежит новой схеме, а не исходной. Хотя сервер Oracle и использует полученный хранимый шаблон, информации в таблице достаточно, чтобы он мог понять, что план применяется не для того объекта.
Опять-таки, сейчас этот метод работает, но зачем эта информация вообще сохраняется -- видимо, в связи с планируемыми изменениями в будущих версиях.
, старший консультант отдела бизнес-анализа и хранилищ данных, Консалтинговая группа "Борлас" (Москва)
Источник:
Долгое время Oracle Express, семейство OLAP-продуктов от Oracle, было лидером в области многомерных баз данных. Кроме стандартных средств OLAP-сервера (Express Server) оно обладает рядом важных и отличительных особенностей, таких как модели, формулы и, самое главное, собственным языком программирования - Express Language, а также рядом инструментов для их использования. В целом, для своего времени прикладные аналитические системы на Oracle Express работали достаточно быстро и эффективно. Одним из самих успешных из них стал продукт Oracle Financial Analyzer (OFA), предназначенный для формирования финансовой отчетности, проведения детального финансового анализа, ведения бюджета, финансового планирования и прогнозирования. Этот продукт получил широкое применение, в частности OFA был включен в состав финансовых модулей семейства Oracle E-Business Suite, и легко интегрировался с ними. В 2000 году корпорацией Oracle было принято решение о "переносе" Express Server в состав реляционной СУБД Oracle 9i, и таким образом в ней появилась OLAP Option. Вместо OFA, для работы в среде этой опции было предложено новое финансовое приложение - Oracle Enterprise Budgeting & Planning (EPB). Но и по сей день OFA (и другие аналитические приложения для среды Oracle Express) продолжают использоваться во многих компаниях.
Многие компании на сегодняшний день используют BI-приложения для сбора и анализа корпоративной информации, хранящийся в различных источниках. Для получения единого взгляда на всю информацию предприятия необходимо создание единой модели ее представления. Несомненно, Express Server и OFA являются важным компонентом в общей модели данных.
Один из клиентов компании "Борлас" решил внедрить у себя систему корпоративной отчетности на основе Oracle Business Intelligence Enterprise Edition. Среди множества всех источников, которые использовались для построения единой модели данных в компании была система бюджетирования OFA. Таким образом, пред нами встала задача интеграции OFA и Oracle BI Suite EE. Поскольку OFA является, по сути, надстройкой над Express Server, мы стали решать общую задачу интеграции Express Server и Oracle BI Suite EE.
Рассмотрим пример построения отчета в Oracle BI Suite EE на основе тестовой базы данных, которая поставляется с Oracle Express - demo.db. Возьмем куб - SALES, построенный по трем измерениям: MONTH, PRODUCT, DISTRICT. В представленных ниже листингах отсутствует Java-код для шлюзового RMI-сервера, RMI-клиента, поскольку они достаточно большие и сложные.
Создадим для него соответствующие структуры в СУБД Oracle:
----------------------------------------------- -- Спецификация объектного типа для ячейки куба ----------------------------------------------- create or replace type t_sales_row as object ( sales number, month date, product varchar2(30), district varchar2(30) ); ----------------------------------------------- -- Спецификация табличного типа ----------------------------------------------- create or replace type t_sales_table as table of t_sales_row;
Для построения конвейерной табличной функции необходимо создать соответствующий тип, который реализовывал бы интерфейс ODCITable ----------------------------------------------- -- ODCITable тип ----------------------------------------------- create or replace type t_sales_rowset as object ( key integer,
-- Статическая функция, необходимая для создания контекста -- query - эапрос в Express static function ODCITableStart(sctx out t_sales_rowset, query varchar2) return number as language java name 'SalesRowset.ODCITableStart( oracle.sql.STRUCT[], java.lang.String) return java.math.BigDecimal',
-- Метод экземпляра, необходимый для получения очередной порции выборки
member function ODCITableFetch(self in out t_sales_rowset, nrows in number, outset out t_sales_table) return number as language java name 'SalesRowset.ODCITableFetch( java.math.BigDecimal, oracle.sql.ARRAY[]) return java.math.BigDecimal',
-- Метод экхемпляра, необходимый для закрытия контекста
member function ODCITableClose(self in t_sales_rowset) return number as language java name 'SalesRowset.ODCITableClose() return java.math.BigDecimal' );
Теперь нам надо создать Java пакет SalesRowset опишем только основные методы, которые необходимы для работы ODCITable типа.
На сегодняшний день Oracle предлагает две аналитические платформы: Standard Edition, бывший Oracle Business Intelligence 10g, и Enterprise Edition, интегрированная платформа для реализации различных методов анализа данных, основанная на платформе Siebel Analytics. Кроме того, существует редакция Oracle Business Intelligence Standard Edition One являющаяся сокращенной версией Enterprise Edition для среднего и малого бизнеса.
Oracle BI Suite Standard Edition состоит из двух основных компонентов:
Oracle Discoverer и Oracle Reports.
Oracle Discoverer позволяет строить произвольные отчеты и формировать нерегламентированные запросы. Он легко интегрируется с СУБД Oracle, в том числе с опцией OLAP. Однако он не имеет никаких адаптеров к Express Server и поэтому не может работать с ним. С другой стороны Oracle Reports, компонент для создания и публикации стандартных регламентированных отчетов, предоставляет доступ к различным источникам данных (SQL, PL/SQL, JDBC, XML-файлы и др.), включая готовый адаптер к Express Server.
Oracle BI Suite Enterprise Edition состоит из набора различных компонентов. В основе лежит Oracle BI Server - сервер, обеспечивающий доступ к источникам данных и представляющий их в виде единой модели данных. Он имеет открытый и расширяемый набор адаптеров, отвечающих за связь с источниками данных. Были созданы индивидуальные адаптеры к различным системам, включая реляционные СУБД (Oracle, DB2, SQL Server, Teradata, Informix и др.), корпоративные приложения (OEBS, Peoplesoft, JD Edwards, SAP R/3, mySAP), OLAP-источники (Oracle OLAP, Microsoft Analysis, SAP BW, Hyperion), XML-источники. Однако адаптеров к Oracle Express не было создано.
Семейство программных продуктов Oracle Express состоит из сервера многомерных баз данных (Express Server, Personal Express), инструментов для администрирования (Express Administrator), инструментальные средства для разработки сложных интегрированных клиентских приложений (Express Analyzer, Express Objects), средства для публикации данных в Интернете (Web Publisher) и многое другое. На рисунке 1 приведена архитектура семейства Oracle Express.
По своей сути Oracle Business Intelligence является не монолитным приложением, а набором различных сервисов, которые работают на единой информационной платформе и выполняют каждый свои определенные функции. В Oracle BI EE сервером, на котором реализуются все сервисы, называется Oracle BI Presentation Services. Кроме внутренних сервисов, в нем существует целый набор стандартных SOAP Webсервисов, которые можно использовать при построении различных композитных приложений с использованием BPEL.
По сути, они являются полноценным API, т.е. набором базовых функций для управления всей системой. Они позволяют выполнять следующие задачи:
Получать отчеты и данные из них Доставлять отчеты внешним системам Управлять каталогом метаданных Запускать бизнес-процессы и агенты исполнения (iBot)
См. рисунок
Формальное описание сервисов и методов представлено в WSDL-файл, который находится по адресу http://host:port/analytics/saw.dll?WSDL. XSD-файл для сервисов называется SawServices.xsd и находится в папке \Web\App\Res\Wsdl\Schemas.
Oracle BI предоставляет пользователю следующие 8 сервисов:
HtmlViewService – сервис, позволяющий встраивать отчеты в HTML формате в любые внешние приложения или порталы. Кроме того сервис, позволяет в режиме реального времени изменять конечное представление отчета; iBotService – сервис, позволяющий запускать агенты исполнения (iBot). Создавать или изменять iBot с помощью этого сервиса нельзя; MetadataService – сервис, с помощью которого можно получать метаописания для различных объектов включая ReplicationService – сервис, позволяющий производить экспорт и импорт метаданных из файлов; ReportEditingService – сервис, с помощью которого можно настраивать параметра для отчетов; SAWSessionService – сервис, обслуживающий все сессионные переменные, такие как имя пользователя, пароль, ключ сессия и т.д. Является обязательным и самым первым сервисом в работе; SecurityService – сервис, отвечающий за вопросы безопасности в системе; WebCatalogService – сервис, с помощью которого можно управлять Web-каталогом, позволяет создавать, изменять, удалять любые объекты; XMLViewService – сервис, позволяющий выполнять произвольные запросы к модель данных и получать результаты в XML формате.
Таким образом, интеграция BI с BPEL позволяет решать следующие задачи:
Запускать бизнес процессы из BI системы Интерактивное взаимодействие (Interactive Dashboards, Answers); Регламентированное взаимодействие (Alerts/ iBots);
Встраиваемая в бизнес процессы аналитика Возможность вызова отчетов и получения результатов;
Возможность вызова из бизнес-процессов механизма доставок (Delivers) в Oracle BI.
Антон Шмаков, ведущий консультант-разработчик IBS Borlas
Oracle Magazine - Русское издание
[От редакции OM/RE: Когда эта статья нашего постоянного автора Антона Шмакова была уже принята к публикации в очередном (февральском) выпуске «Oracle Magazine/Русское Издание», на сайте публикаций корпорации Oracle появилась статья Марка Риттмана (Mark Rittman, Oracle ACE Director) и Джоэл Крисп (Joel Crisp) «Integrating Oracle Business Intelligence Enterprise Edition Plus with SOA» на ту же тему, что и работа А.Шмакова. Естественно, что статья А.Шмакова абсолютно независима от публикации М.Риттмана, хотя Антон не скрывает, что для введения в предлагаемую читателям данную работу он пользовался блогом метра-директора коллегии «Асы Oracle».
Перевод статьи M.Rittman и J.Crisp «Integrating Oracle Business Intelligence Enterprise Edition Plus with SOA» планируется к публикации в следующем выпуске журнала OM/RE.]
BI системы последнего поколения представляют собой не просто отдельную программу, в которой пользователи строят и публикуют отчеты, а обширный комплекс технологий и приложений, созданный для удовлетворения всех потребностей BI. Именно таким продуктом и является Oracle Business Intelligence Enterprise Edition (подробнее см. «Oracle BI Suite EE — самая «всеядная» и «интеллектуальная» из аналитических платформ», Oracle Magazine RE, Октябрь 2007.
В целом подход Oracle к созданию сервис ориентированной бизнес аналитике (Service Oriented Business Intelligence) следующий. Одной из основных характеристик платформы Oracle BI EE является понятие “всепроникающей” (Pervasive) бизнес аналитики, что позволяет принимать более обдуманные и взвешенные решения на различных уровнях. Т.е. можно выделить следующие тенденции в развитие SO BI:
Включение BI в бизнес процессы компаний позволяет добавить аналитическую составляющую в Work?ow и обработку различных событий. Интеграция BI-систем и бизнес приложений позволяет объединить транзакционную и аналитическую обработку данных в едином интерфейсе; Интеграция исторических и данных реального времени позволяет строить хранилища данных нового типа, заниматься мониторингом различных аналитических показателей в режиме реального времени. Создание проактивной аналитики позволяет инициировать бизнес процессы из BI систем.
Если говорить про SOA архитектуру, то основными составляющими ее являются следующие компоненты:
Бизнес-процессы (Business Processes) и BPEL – язык формального описания бизнес процессов и протоколов их взаимодействия между собой; Бизнес правила (Business Rules); Бизнес события (Business Events) и корпоративная сервисная шина (ESB); Мониторинг бизнес деятальности (BAM). Внедрение BI в SOA среду позволяет расширить каждый из перечисленных выше компонентов: Аналитические бизнес процессы (Analytic BPEL, ABPEL)
Использование различных аналитические условий и метрики в BPEL процессах; Заниматься оркестровкой сервисов с использованием данных из BI систем;
Аналитические бизнес правила (Analytic Business Rules) Аналитическое управление бизнес событиями (Analytic Business Event Routing):
Возможность генерации бизнес событий (в том числе в шину данных) из агентов (Alert) в BI системах; Использование данных и отчетов для генерации бизнес событий; Возможность строить отчеты и запускать аналитические модели и вычисления из BPEL процессов; Интеллектуальная маршрутизация бизнес событий;
Аналитический мониторинг бизнес деятельности (Analytic BAM).
В предыдущем примере мы показали, как можно вызывать Oracle BI сервисы из BPEL, но существует возможность вызова BPEL процессов из самого Oracle BI EE. Это можно сделать из Oracle BI Delivers. При создании iBot на закладке Advanced можно выбрать дополнительное действие, которое будет отрабатываться при выполнении или невыполнении условий агента. В качестве возможных вариантов можно выбрать:
iBot – возможность запустить другой агент Custom Script – выполнить любой скрипт на JavaScript или VBScript; Work?ow – запустить Siebel CRM Work?ow; Custom Java Program – выполнить произвольный Java код.
В качестве интеграции с BPEL подходят два варианта: Custom Script или Custom Java Program.
В первом случае можно написать небольшую программу, например на JavaScript, которая будет обращаться к некому сервлету (Servlet) и передавать ему параметры, а он будет запускать BPEL процессы. Если BPEL Process имеет HTTP форму запуска, то JavaScript может напрямую обращаться к BPEL процессу и передавать ему параметры.
Второй вариант взаимодействия через Custom Java Program позволяет писать на Java абсолютно любые вызовы и обработки.
В скором времени Oracle обещает добавить полноценную поддержку BPEL в Oracle BI EE, тогда в списке возможных действий в iBot появится еще один пункт BPEL.