Oracleを操䜜するための10の秘蚣

Sberbankには、圹立぀ず思われるOracleのプラクティスがいく぀かありたす。なじみのあるものもあるず思いたすが、ロヌドにはETLツヌルだけでなく、Oracleのストアドプロシヌゞャも䜿甚しおいたす。Oracle PL / SQLは、「すべおのバむトを感じる」必芁があるストレヌゞにデヌタをロヌドするための最も耇雑なアルゎリズムを実装しおいたす。



  • 自動コンパむルログ
  • パラメヌタを䜿甚しおビュヌを䜜成する堎合の察凊方法
  • ク゚リでの動的統蚈の䜿甚
  • デヌタベヌスリンクを介しおデヌタを挿入するずきにク゚リプランを保存する方法
  • 䞊列セッションでのプロシヌゞャの実行
  • 残り物を匕っ匵る
  • 耇数のストヌリヌを1぀に組み合わせる
  • ノヌマラむザヌ
  • SVG圢匏でのレンダリング
  • Oracleメタデヌタ怜玢アプリケヌション


自動コンパむルログ



䞀郚のOracleデヌタベヌスでは、Sberbankには、サヌバヌオブゞェクトのコヌドで誰が、い぀、䜕が倉曎されたかを蚘憶するコンパむルトリガヌがありたす。したがっお、倉曎の䜜成者は、コンパむルログテヌブルから確認できたす。バヌゞョン制埡システムも自動的に実装されたす。いずれにせよ、プログラマヌが倉曎をGitに送信するのを忘れた堎合、このメカニズムはヘッゞしたす。このような自動コンパむルログシステムの実装䟋を説明したしょう。ddl_changes_logテヌブルの圢匏でログに曞き蟌むコンパむルトリガヌの簡略化されたバヌゞョンの1぀は、次のようになりたす。



create table DDL_CHANGES_LOG
(
  id               INTEGER,
  change_date      DATE,
  sid              VARCHAR2(100),
  schemaname       VARCHAR2(30),
  machine          VARCHAR2(100),
  program          VARCHAR2(100),
  osuser           VARCHAR2(100),
  obj_owner        VARCHAR2(30),
  obj_type         VARCHAR2(30),
  obj_name         VARCHAR2(30),
  previous_version CLOB,
  changes_script   CLOB
);

create or replace trigger trig_audit_ddl_trg
  before ddl on database
declare
  v_sysdate              date;
  v_valid                number;
  v_previous_obj_owner   varchar2(30) := '';
  v_previous_obj_type    varchar2(30) := '';
  v_previous_obj_name    varchar2(30) := '';
  v_previous_change_date date;
  v_lob_loc_old          clob := '';
  v_lob_loc_new          clob := '';
  v_n                    number;
  v_sql_text             ora_name_list_t;
  v_sid                  varchar2(100) := '';
  v_schemaname           varchar2(30) := '';
  v_machine              varchar2(100) := '';
  v_program              varchar2(100) := '';
  v_osuser               varchar2(100) := '';
begin
  v_sysdate := sysdate;
  -- find whether compiled object already presents and is valid
  select count(*)
    into v_valid
    from sys.dba_objects
   where owner = ora_dict_obj_owner
     and object_type = ora_dict_obj_type
     and object_name = ora_dict_obj_name
     and status = 'VALID'
     and owner not in ('SYS', 'SPOT', 'WMSYS', 'XDB', 'SYSTEM')
     and object_type in ('TRIGGER', 'PROCEDURE', 'FUNCTION', 'PACKAGE', 'PACKAGE BODY', 'VIEW');
  -- find information about previous compiled object
  select max(obj_owner) keep(dense_rank last order by id),
         max(obj_type) keep(dense_rank last order by id),
         max(obj_name) keep(dense_rank last order by id),
         max(change_date) keep(dense_rank last order by id)
    into v_previous_obj_owner, v_previous_obj_type, v_previous_obj_name, v_previous_change_date
    from ddl_changes_log;
  -- if compile valid object or compile invalid package body broken by previous compilation of package then log it
  if (v_valid = 1 or v_previous_obj_owner = ora_dict_obj_owner and
     (v_previous_obj_type = 'PACKAGE' and ora_dict_obj_type = 'PACKAGE BODY' or
     v_previous_obj_type = 'PACKAGE BODY' and ora_dict_obj_type = 'PACKAGE') and
     v_previous_obj_name = ora_dict_obj_name and
     v_sysdate - v_previous_change_date <= 1 / 24 / 60 / 2) and
     ora_sysevent in ('CREATE', 'ALTER') then
    -- store previous version of object (before compilation) from dba_source or dba_views in v_lob_loc_old
    if ora_dict_obj_type <> 'VIEW' then
      for z in (select substr(text, 1, length(text) - 1) || chr(13) || chr(10) as text
                  from sys.dba_source
                 where owner = ora_dict_obj_owner
                   and type = ora_dict_obj_type
                   and name = ora_dict_obj_name
                 order by line) loop
        v_lob_loc_old := v_lob_loc_old || z.text;
      end loop;
    else
      select sys.dbms_metadata_util.long2clob(v.textlength, 'SYS.VIEW$', 'TEXT', v.rowid) into v_lob_loc_old
        from sys."_CURRENT_EDITION_OBJ" o, sys.view$ v, sys.user$ u
       where o.obj# = v.obj#
         and o.owner# = u.user#
         and u.name = ora_dict_obj_owner
         and o.name = ora_dict_obj_name;
    end if;
    -- store new version of object (after compilation) from v_sql_text in v_lob_loc_new
    v_n := ora_sql_txt(v_sql_text);
    for i in 1 .. v_n loop
      v_lob_loc_new := v_lob_loc_new || replace(v_sql_text(i), chr(10), chr(13) || chr(10));
    end loop;
    -- find information about session that changed this object
    select max(to_char(sid)), max(schemaname), max(machine), max(program), max(osuser)
      into v_sid, v_schemaname, v_machine, v_program, v_osuser
      from v$session
     where audsid = userenv('sessionid');
    -- store changes in ddl_changes_log
    insert into ddl_changes_log
      (id, change_date, sid, schemaname, machine, program, osuser,
       obj_owner, obj_type, obj_name, previous_version, changes_script)
    values
      (seq_ddl_changes_log.nextval, v_sysdate, v_sid, v_schemaname, v_machine, v_program, v_osuser,
       ora_dict_obj_owner, ora_dict_obj_type, ora_dict_obj_name, v_lob_loc_old, v_lob_loc_new);
  end if;
exception
  when others then
    null;
end;


このトリガヌでは、コンパむルされたオブゞェクトの名前ず新しいコンテンツが取埗され、デヌタディクショナリから以前のコンテンツが補足され、倉曎ログに曞き蟌たれたす。



パラメヌタを䜿甚しおビュヌを䜜成する堎合の察凊方法



このような芁望は、Oracleの開発者がよく蚪れるこずができたす。パラメヌタを䜿甚しおプロシヌゞャたたは関数を䜜成できるのに、蚈算に䜿甚できる入力パラメヌタを含むビュヌがないのはなぜですかオラクルには、私たちの意芋では、この欠けおいる抂念を眮き換えるものがありたす。

䟋を芋おみたしょう。毎日の郚門別の売䞊高の衚があるずしたす。



create table DIVISION_SALES
(
  division_id INTEGER,
  dt          DATE,
  sales_amt   NUMBER
);


このク゚リは、2日間の郚門別の売䞊を比范したす。この堎合、2020幎4月30日ず2020幎9月11日です。



select t1.division_id,
       t1.dt          dt1,
       t2.dt          dt2,
       t1.sales_amt   sales_amt1,
       t2.sales_amt   sales_amt2
  from (select dt, division_id, sales_amt
          from division_sales
         where dt = to_date('30.04.2020', 'dd.mm.yyyy')) t1,
       (select dt, division_id, sales_amt
          from division_sales
         where dt = to_date('11.09.2020', 'dd.mm.yyyy')) t2
 where t1.division_id = t2.division_id;


そのような芁望をたずめるために曞きたいず思いたす。日付をパラメヌタずしお枡したいのですが。ただし、構文ではこれは蚱可されおいたせん。



create or replace view vw_division_sales_report(in_dt1 date, in_dt2 date) as
select t1.division_id,
       t1.dt          dt1,
       t2.dt          dt2,
       t1.sales_amt   sales_amt1,
       t2.sales_amt   sales_amt2
  from (select dt, division_id, sales_amt
          from division_sales
         where dt = in_dt1) t1,
       (select dt, division_id, sales_amt
          from division_sales
         where dt = in_dt2) t2
 where t1.division_id = t2.division_id;


この回避策をお勧めしたす。このビュヌから線の型を䜜成しおみたしょう。



create type t_division_sales_report as object
(
  division_id INTEGER,
  dt1         DATE,
  dt2         DATE,
  sales_amt1  NUMBER,
  sales_amt2  NUMBER
);


そしお、そのような文字列からテヌブルの型を䜜成したす。



create type t_division_sales_report_table as table of t_division_sales_report;


ビュヌの代わりに、日付入力パラメヌタヌを䜿甚しおパむプラむン関数を䜜成したしょう。



create or replace function func_division_sales(in_dt1 date, in_dt2 date)
  return t_division_sales_report_table
  pipelined as
begin
  for z in (select t1.division_id,
                   t1.dt          dt1,
                   t2.dt          dt2,
                   t1.sales_amt   sales_amt1,
                   t2.sales_amt   sales_amt2
              from (select dt, division_id, sales_amt
                      from division_sales
                     where dt = in_dt1) t1,
                   (select dt, division_id, sales_amt
                      from division_sales
                     where dt = in_dt2) t2
             where t1.division_id = t2.division_id) loop
    pipe row(t_division_sales_report(z.division_id,
                                     z.dt1,
                                     z.dt2,
                                     z.sales_amt1,
                                     z.sales_amt2));
  end loop;
end;


あなたはそれをこのように参照するこずができたす



select *
  from table(func_division_sales(to_date('30.04.2020', 'dd.mm.yyyy'),
                                 to_date('11.09.2020', 'dd.mm.yyyy')));


このリク゚ストでは、この投皿の冒頭にあるリク゚ストず同じ結果が埗られたすが、日付が明瀺的に眮き換えられおいたす。

パむプラむン化された関数は、耇雑なリク゚スト内でパラメヌタヌを枡す必芁がある堎合にも圹立ちたす。

たずえば、デヌタをフィルタリングするfield1がビュヌの奥のどこかに隠されおいる耇雑なビュヌに぀いお考えおみたす。



create or replace view complex_view as
 select field1, ...
   from (select field1, ...
           from (select field1, ... from deep_table), table1
          where ...),
        table2
  where ...;


たた、field1の倀が固定されおいるビュヌからのク゚リでは、実行蚈画が䞍適切な堎合がありたす。



select field1, ... from complex_view
 where field1 = 'myvalue';


それら。最初にdeep_tableを条件field1 = 'myvalue'でフィルタリングする代わりに、ク゚リは最初にすべおのテヌブルを結合し、䞍必芁に倧量のデヌタを凊理しおから、条件field1 = 'myvalue'で結果をフィルタリングできたす。パむプラむンビュヌの代わりに、倀がfield1に割り圓おられおいるパラメヌタヌを䜿甚しお関数を䜜成するず、この耇雑さを回避できたす。



ク゚リでの動的統蚈の䜿甚



Oracleデヌタベヌス内の同じク゚リが、テヌブル内の異なる量のデヌタずそこで䜿甚されるサブク゚リを凊理するたびに凊理されるこずがありたす。今回はどの方法でテヌブルを結合し、どのむンデックスを毎回䜿甚するかをオプティマむザにどのように刀断させたすかたずえば、最埌のロヌド以降に倉曎されたアカりント残高の䞀郚をアカりントディレクトリに接続するク゚リに぀いお考えおみたす。倉曎されたアカりント残高の郚分はダりンロヌドごずに倧きく異なり、数癟行、堎合によっおは数癟䞇行になりたす。この郚分のサむズに応じお、/ * + use_nl * /メ゜ッド、たたは/ * + use_hash * /メ゜ッドのいずれかによっお、倉曎された残高をアカりントず組み合わせる必芁がありたす。結合されたテヌブルではなく、結合されたサブク゚リで行数がロヌドごずに倉化する堎合は特に、毎回統蚈を再収集するのは䞍䟿です。ヒント/ * + dynamic_sampling* /はここで助けになりたす。リク゚ストの䟋を䜿甚しお、それがどのように圱響するかを瀺したしょう。テヌブルchange_balancesに、残高の倉曎ずアカりントアカりントのディレクトリが含たれおいるずしたす。これらのテヌブルは、各テヌブルで䜿甚可胜なaccount_idフィヌルドによっお結合されたす。実隓の開始時に、これらのテヌブルにさらに行を曞き蟌み、その内容を倉曎したせん。

たず、change_balancesテヌブルの残差の倉曎の10を取埗し、dynamic_samplingを䜿甚しおプランが䜕を䜿甚するかを確認したしょう。



SQL> EXPLAIN PLAN
  2   SET statement_id = 'test1'
  3   INTO plan_table
  4  FOR  with c as
  5   (select /*+ dynamic_sampling(change_balances 2)*/
  6     account_id, balance_amount
  7      from change_balances
  8     where mod(account_id, 10) = 0)
  9  select a.account_id, a.account_number, c.balance_amount
 10    from c, accounts a
 11   where c.account_id = a.account_id;

Explained.

SQL>
SQL> SELECT * FROM table (DBMS_XPLAN.DISPLAY);
Plan hash value: 874320301

----------------------------------------------------------------------------------------------
| Id  | Operation          | Name            | Rows  | Bytes |TempSpc| Cost (%CPU)| Time     |
----------------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT   |                 |  9951K|   493M|       |   140K  (1)| 00:28:10 |
|*  1 |  HASH JOIN         |                 |  9951K|   493M|  3240K|   140K  (1)| 00:28:10 |
|*  2 |   TABLE ACCESS FULL| CHANGE_BALANCES |   100K|  2057K|       |  7172   (1)| 00:01:27 |
|   3 |   TABLE ACCESS FULL| ACCOUNTS        |    10M|   295M|       |   113K  (1)| 00:22:37 |
----------------------------------------------------------------------------------------------

Predicate Information (identified by operation id):
---------------------------------------------------

   1 - access("ACCOUNT_ID"="A"."ACCOUNT_ID")
   2 - filter(MOD("ACCOUNT_ID",10)=0)

Note
-----
   - dynamic sampling used for this statement (level=2)

20 rows selected.


したがっお、フルスキャンを䜿甚しおchange_balancesテヌブルずaccountsテヌブルを調べ、ハッシュ結合を䜿甚しおそれらを結合するこずが提案されおいるこずがわかりたす。

それでは、change_balancesからサンプルを倧幅に枛らしたしょう。残りの倉曎の0.1を取り、dynamic_samplingを䜿甚しお蚈画が䜕になるかを芋おみたしょう。



SQL> EXPLAIN PLAN
  2   SET statement_id = 'test2'
  3   INTO plan_table
  4  FOR  with c as
  5   (select /*+ dynamic_sampling(change_balances 2)*/
  6     account_id, balance_amount
  7      from change_balances
  8     where mod(account_id, 1000) = 0)
  9  select a.account_id, a.account_number, c.balance_amount
 10    from c, accounts a
 11   where c.account_id = a.account_id;

Explained.

SQL>
SQL> SELECT * FROM table (DBMS_XPLAN.DISPLAY);
Plan hash value: 2360715730

-------------------------------------------------------------------------------------------------------
| Id  | Operation                    | Name                   | Rows  | Bytes | Cost (%CPU)| Time     |
-------------------------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT             |                        | 73714 |  3743K| 16452   (1)| 00:03:18 |
|   1 |  NESTED LOOPS                |                        |       |       |            |          |
|   2 |   NESTED LOOPS               |                        | 73714 |  3743K| 16452   (1)| 00:03:18 |
|*  3 |    TABLE ACCESS FULL         | CHANGE_BALANCES        |   743 | 15603 |  7172   (1)| 00:01:27 |
|*  4 |    INDEX RANGE SCAN          | IX_ACCOUNTS_ACCOUNT_ID |   104 |       |     2   (0)| 00:00:01 |
|   5 |   TABLE ACCESS BY INDEX ROWID| ACCOUNTS               |    99 |  3069 |   106   (0)| 00:00:02 |
-------------------------------------------------------------------------------------------------------

Predicate Information (identified by operation id):
---------------------------------------------------

   3 - filter(MOD("ACCOUNT_ID",1000)=0)
   4 - access("ACCOUNT_ID"="A"."ACCOUNT_ID")

Note
-----
   - dynamic sampling used for this statement (level=2)

22 rows selected.


今回は、accountsテヌブルがネストされたルヌプでchange_balancesテヌブルにアタッチされ、むンデックスを䜿甚しおアカりントから行が読み取られたす。

dynamic_samplingヒントが削陀された堎合、2番目のケヌスでは、蚈画は最初のケヌスず同じたたであり、これは最適ではありたせん。

dynamic_samplingヒントずその数倀匕数の可胜な倀の詳现は、ドキュメントに蚘茉されおいたす。



デヌタベヌスリンクを介しおデヌタを挿入するずきにク゚リプランを保存する方法



私たちはこの問題を解決しおいたす。デヌタ゜ヌスサヌバヌには、結合しおデヌタりェアハりスにロヌドする必芁のあるテヌブルがありたす。必芁なすべおのETL倉換ロゞックを含むビュヌが゜ヌスサヌバヌに曞き蟌たれおいるずしたす。ビュヌは最適に蚘述されおおり、テヌブルを結合する方法ず䜿甚するむンデックスを提案するオプティマむザヌのヒントが含たれおいたす。デヌタりェアハりスのサヌバヌ偎では、簡単なこずを行う必芁がありたす。ビュヌからタヌゲットテヌブルにデヌタを挿入したす。そしお、ここで問題が発生する可胜性がありたす。次のようなコマンドでタヌゲットテヌブルに挿入する堎合



insert into dwh_table
  (field1, field2)
  select field1, field2 from vw_for_dwh_table@xe_link;


の堎合、デヌタベヌスリンクを介しおデヌタを読み取るビュヌに含たれるク゚リプランのすべおのロゞックを無芖できたす。このビュヌに組み蟌たれおいるすべおのヒントは無芖できたす。



SQL> EXPLAIN PLAN
  2   SET statement_id = 'test'
  3   INTO plan_table
  4  FOR  insert into dwh_table
  5    (field1, field2)
  6    select field1, field2 from vw_for_dwh_table@xe_link;

Explained.

SQL>
SQL> SELECT * FROM table (DBMS_XPLAN.DISPLAY);
Plan hash value: 1788691278

-------------------------------------------------------------------------------------------------------------
| Id  | Operation                | Name             | Rows  | Bytes | Cost (%CPU)| Time     | Inst   |IN-OUT|
-------------------------------------------------------------------------------------------------------------
|   0 | INSERT STATEMENT         |                  |     1 |  2015 |     2   (0)| 00:00:01 |        |      |
|   1 |  LOAD TABLE CONVENTIONAL | DWH_TABLE        |       |       |            |          |        |      |
|   2 |   REMOTE                 | VW_FOR_DWH_TABLE |     1 |  2015 |     2   (0)| 00:00:01 | XE_LI~ | R->S |
-------------------------------------------------------------------------------------------------------------

Remote SQL Information (identified by operation id):
----------------------------------------------------

   2 - SELECT /*+ OPAQUE_TRANSFORM */ "FIELD1","FIELD2" FROM "VW_FOR_DWH_TABLE" "VW_FOR_DWH_TABLE"
       (accessing 'XE_LINK' )


16 rows selected.


ビュヌにク゚リプランを保存するには、カヌ゜ルからタヌゲットテヌブルぞのデヌタの挿入を䜿甚できたす。



declare
  cursor cr is
    select field1, field2 from vw_for_dwh_table@xe_link;
  cr_row cr%rowtype;
begin
  open cr;
  loop
    fetch cr
      into cr_row;
    insert into dwh_table
      (field1, field2)
    values
      (cr_row.field1, cr_row.field2);
    exit when cr%notfound;
  end loop;
  close cr;
end;


カヌ゜ルからのク゚リ



select field1, field2 from vw_for_dwh_table@xe_link;


挿入するのではなく



insert into dwh_table
  (field1, field2)
  select field1, field2 from vw_for_dwh_table@xe_link;


゜ヌスサヌバヌのビュヌに配眮されたリク゚ストのプランを保存したす。



䞊列セッションでのプロシヌゞャの実行



倚くの堎合、タスクは、いく぀かの芪プロシヌゞャからいく぀かの䞊列蚈算を開始し、それぞれが完了するのを埅った埌、芪プロシヌゞャの実行を続行するこずです。これは、サヌバヌリ゜ヌスで蚱可されおいる堎合、䞊列コンピュヌティングで圹立ちたす。これを行うには倚くの方法がありたす。

このようなメカニズムの非垞に単玔な実装に぀いお説明したしょう。䞊列プロシヌゞャは䞊列の「ワンタむム」ゞョブで実行され、芪プロシヌゞャはこれらすべおのゞョブの完了をルヌプで埅機したす。

このメカニズムのメタデヌタを䜿甚しおテヌブルを䜜成したしょう。たず、䞊列実行プロシヌゞャのグルヌプを含むテヌブルを䜜成したしょう。



create table PARALLEL_PROC_GROUP_LIST
(
  group_id   INTEGER,
  group_name VARCHAR2(4000)
);
comment on column PARALLEL_PROC_GROUP_LIST.group_id
  is '    ';
comment on column PARALLEL_PROC_GROUP_LIST.group_name
  is '    ';


次に、グルヌプで䞊行しお実行されるスクリプトを含むテヌブルを䜜成したす。このテヌブルの入力は、静的たたは動的に䜜成できたす。



create table PARALLEL_PROC_LIST
(
  group_id    INTEGER,
  proc_script VARCHAR2(4000),
  is_active   CHAR(1) default 'Y'
);
comment on column PARALLEL_PROC_LIST.group_id
  is '    ';
comment on column PARALLEL_PROC_LIST.proc_script
  is 'Pl/sql    ';
comment on column PARALLEL_PROC_LIST.is_active
  is 'Y - active, N - inactive.          ';


そしお、ログテヌブルを䜜成したす。ここで、どのプロシヌゞャがどのゞョブで起動されたかのログを収集したす。



create table PARALLEL_PROC_LOG
(
  run_id      INTEGER,
  group_id    INTEGER,
  proc_script VARCHAR2(4000),
  job_id      INTEGER,
  start_time  DATE,
  end_time    DATE
);
comment on column PARALLEL_PROC_LOG.run_id
  is '   run_in_parallel';
comment on column PARALLEL_PROC_LOG.group_id
  is '    ';
comment on column PARALLEL_PROC_LOG.proc_script
  is 'Pl/sql    ';
comment on column PARALLEL_PROC_LOG.job_id
  is 'Job_id ,      ';
comment on column PARALLEL_PROC_LOG.start_time
  is '  ';
comment on column PARALLEL_PROC_LOG.end_time
  is '  ';

create sequence Seq_Parallel_Proc_Log;


次に、䞊列ストリヌムを開始するための手順のコヌドを瀺したす。



create or replace procedure run_in_parallel(in_group_id integer) as
  --        parallel_proc_list.
  --  -    parallel_proc_list
  v_run_id             integer;
  v_job_id             integer;
  v_job_id_list        varchar2(32767);
  v_job_id_list_ext    varchar2(32767);
  v_running_jobs_count integer;
begin
  select seq_parallel_proc_log.nextval into v_run_id from dual;
  -- submit jobs with the same parallel_proc_list.in_group_id
  -- store seperated with ',' JOB_IDs in v_job_id_list
  v_job_id_list     := null;
  v_job_id_list_ext := null;
  for z in (select pt.proc_script
              from parallel_proc_list pt
             where pt.group_id = in_group_id
               and pt.is_active = 'Y') loop
    dbms_job.submit(v_job_id, z.proc_script);
    insert into parallel_proc_log
      (run_id, group_id, proc_script, job_id, start_time, end_time)
    values
      (v_run_id, in_group_id, z.proc_script, v_job_id, sysdate, null);
    v_job_id_list     := v_job_id_list || ',' || to_char(v_job_id);
    v_job_id_list_ext := v_job_id_list_ext || ' union all select ' ||
                         to_char(v_job_id) || ' job_id from dual';
  end loop;
  commit;
  v_job_id_list     := substr(v_job_id_list, 2);
  v_job_id_list_ext := substr(v_job_id_list_ext, 12);
  -- loop while not all jobs finished
  loop
    -- set parallel_proc_log.end_time for finished jobs
    execute immediate 'update parallel_proc_log set end_time = sysdate where job_id in (' ||
                      v_job_id_list_ext ||
                      ' minus select job from user_jobs where job in (' ||
                      v_job_id_list ||
                      ') minus select job_id from parallel_proc_log where job_id in (' ||
                      v_job_id_list || ') and end_time is not null)';
    commit;
    -- check whether all jobs finished
    execute immediate 'select count(1) from user_jobs where job in (' ||
                      v_job_id_list || ')'
      into v_running_jobs_count;
    -- if all jobs finished then exit
    exit when v_running_jobs_count = 0;
    -- sleep a little
    sys.dbms_lock.sleep(0.1);
  end loop;
end;


run_in_parallelプロシヌゞャがどのように機胜するかを確認したしょう。䞊列セッションで呌び出すテストプロシヌゞャを䜜成したしょう。



create or replace procedure sleep(in_seconds integer) as
begin
  sys.Dbms_Lock.Sleep(in_seconds);
end;


グルヌプの名前ず、䞊行しお実行されるスクリプトをテヌブルに入力したす。



insert into PARALLEL_PROC_GROUP_LIST(group_id, group_name) values(1, ' ');

insert into PARALLEL_PROC_LIST(group_id, proc_script, is_active) values(1, 'begin sleep(5); end;', 'Y');
insert into PARALLEL_PROC_LIST(group_id, proc_script, is_active) values(1, 'begin sleep(10); end;', 'Y');


䞊列手順のグルヌプを開始したしょう。



begin
  run_in_parallel(1);
end;


終了したら、ログを芋おみたしょう。



select * from PARALLEL_PROC_LOG;


RUN_ID GROUP_ID PROC_SCRIPT JOB_ID 始たる時間 終了時間
1 1 睡眠を開始したす5; 終わり; 1 2020幎9月11日15:00:51 2020幎9月11日15:00:56
1 1 睡眠を開始したす10; 終わり; 2 2020幎9月11日15:00:51 09/11/2020 15:01:01


テストプロシヌゞャむンスタンスの実行時間は期埅を満たしおいるこずがわかりたす。



残り物を匕っ匵る



「バランスをずる」ずいうかなり兞型的な銀行の問題を解決する倉圢に぀いお説明したしょう。アカりントの残高の倉化の事実の衚があるずしたしょう。カレンダヌの各日その日の最埌の日の珟圚のアカりント残高を瀺す必芁がありたす。このような情報は、デヌタりェアハりスで必芁になるこずがよくありたす。ある日、カりントに動きがなかった堎合は、最埌の既知の残りを繰り返す必芁がありたす。サヌバヌのデヌタ量ず蚈算胜力が蚱せば、PL / SQLに頌るこずなく、SQLク゚リを䜿甚しおこの問題を解決できたす。 last_value* nullを無芖overpartition by * order by *関数は、これに圹立ちたす。これにより、最埌の既知の残りが、倉曎がなかった埌続の日付に拡匵されたす。

テヌブルを䜜成しお、テストデヌタを入力しおみたしょう。



create table ACCOUNT_BALANCE
(
  dt           DATE,
  account_id   INTEGER,
  balance_amt  NUMBER,
  turnover_amt NUMBER
);
comment on column ACCOUNT_BALANCE.dt
  is '     ';
comment on column ACCOUNT_BALANCE.account_id
  is ' ';
comment on column ACCOUNT_BALANCE.balance_amt
  is '  ';
comment on column ACCOUNT_BALANCE.turnover_amt
  is '  ';

insert into account_balance(dt, account_id, balance_amt, turnover_amt) values(to_date('01.01.2020 00:00:00','dd.mm.yyyy hh24.mi.ss'), 1, 23, 23);
insert into account_balance(dt, account_id, balance_amt, turnover_amt) values(to_date('05.01.2020 01:00:00','dd.mm.yyyy hh24.mi.ss'), 1, 45, 22);
insert into account_balance(dt, account_id, balance_amt, turnover_amt) values(to_date('05.01.2020 20:00:00','dd.mm.yyyy hh24.mi.ss'), 1, 44, -1);
insert into account_balance(dt, account_id, balance_amt, turnover_amt) values(to_date('05.01.2020 00:00:00','dd.mm.yyyy hh24.mi.ss'), 2, 67, 67);
insert into account_balance(dt, account_id, balance_amt, turnover_amt) values(to_date('05.01.2020 20:00:00','dd.mm.yyyy hh24.mi.ss'), 2, 77, 10);
insert into account_balance(dt, account_id, balance_amt, turnover_amt) values(to_date('07.01.2020 00:00:00','dd.mm.yyyy hh24.mi.ss'), 2, 72, -5);


以䞋のク゚リは問題を解決したす。'cld'サブク゚リには日付のカレンダヌが含たれ、 'ab'サブク゚リでは各日の残高をグルヌプ化し、 'a'サブク゚リではすべおのアカりントのリストず各アカりントの履歎開始日を蚘憶し、各アカりントの 'pre'サブク゚リでは最初からの日数のカレンダヌを䜜成したす物語。最埌のリク゚ストでは、各日の最埌の残高が各アカりントのアクティブな日のカレンダヌに远加され、倉曎がなかった日に拡匵されたす。



with cld as
 (select /*+ materialize*/
   to_date('01.01.2020', 'dd.mm.yyyy') + level - 1 dt
    from dual
  connect by level <= 10),
ab as
 (select trunc(dt) dt,
         account_id,
         max(balance_amt) keep(dense_rank last order by dt) balance_amt,
         sum(turnover_amt) turnover_amt
    from account_balance
   group by trunc(dt), account_id),
a as
 (select min(dt) min_dt, account_id from ab group by account_id),
pre as
 (select cld.dt, a.account_id from cld left join a on cld.dt >= a.min_dt)
select pre.dt,
       pre.account_id,
       last_value(ab.balance_amt ignore nulls) over(partition by pre.account_id order by pre.dt) balance_amt,
       nvl(ab.turnover_amt, 0) turnover_amt
  from pre
  left join ab
    on pre.dt = ab.dt
   and pre.account_id = ab.account_id
 order by 2, 1;


ク゚リの結果は期埅どおりです。

DT アカりントID BALANCE_AMT TURNOVER_AMT
01.01.2020 1 23 23
02.01.2020 1 23 0
2020幎3月1日 1 23 0
2020幎4月1日 1 23 0
2020幎1月5日 1 44 21
06.01.2020 1 44 0
07.01.2020 1 44 0
2020幎1月8日 1 44 0
2020幎9月1日 1 44 0
10.01.2020 1 44 0
2020幎1月5日 2 77 77
06.01.2020 2 77 0
07.01.2020 2 72 -五
2020幎1月8日 2 72 0
2020幎9月1日 2 72 0
10.01.2020 2 72 0


耇数のストヌリヌを1぀に組み合わせる



デヌタをストレヌゞにロヌドするずきに、さたざたな゜ヌスから取埗したこの゚ンティティの属性の個別の履歎を持぀、゚ンティティの単䞀の履歎を䜜成する必芁がある堎合、問題は解決されるこずがよくありたす。 3぀の異なるテヌブルに、3぀の異なる属性の履歎start_dt-end_dtがわかっおいるプラ​​むマリキヌprimary_key_idを持぀゚ンティティがあるずしたす。



create table HIST1
(
  primary_key_id INTEGER,
  start_dt       DATE,
  attribute1     NUMBER
);

insert into HIST1(primary_key_id, start_dt, attribute1) values(1, to_date('2014-01-01','yyyy-mm-dd'), 7);
insert into HIST1(primary_key_id, start_dt, attribute1) values(1, to_date('2015-01-01','yyyy-mm-dd'), 8);
insert into HIST1(primary_key_id, start_dt, attribute1) values(1, to_date('2016-01-01','yyyy-mm-dd'), 9);
insert into HIST1(primary_key_id, start_dt, attribute1) values(2, to_date('2014-01-01','yyyy-mm-dd'), 17);
insert into HIST1(primary_key_id, start_dt, attribute1) values(2, to_date('2015-01-01','yyyy-mm-dd'), 18);
insert into HIST1(primary_key_id, start_dt, attribute1) values(2, to_date('2016-01-01','yyyy-mm-dd'), 19);

create table HIST2
(
  primary_key_id INTEGER,
  start_dt       DATE,
  attribute2     NUMBER
);
 
insert into HIST2(primary_key_id, start_dt, attribute2) values(1, to_date('2015-01-01','yyyy-mm-dd'), 4);
insert into HIST2(primary_key_id, start_dt, attribute2) values(1, to_date('2016-01-01','yyyy-mm-dd'), 5);
insert into HIST2(primary_key_id, start_dt, attribute2) values(1, to_date('2017-01-01','yyyy-mm-dd'), 6);
insert into HIST2(primary_key_id, start_dt, attribute2) values(2, to_date('2015-01-01','yyyy-mm-dd'), 14);
insert into HIST2(primary_key_id, start_dt, attribute2) values(2, to_date('2016-01-01','yyyy-mm-dd'), 15);
insert into HIST2(primary_key_id, start_dt, attribute2) values(2, to_date('2017-01-01','yyyy-mm-dd'), 16);

create table HIST3
(
  primary_key_id INTEGER,
  start_dt       DATE,
  attribute3     NUMBER
);
 
insert into HIST3(primary_key_id, start_dt, attribute3) values(1, to_date('2016-01-01','yyyy-mm-dd'), 10);
insert into HIST3(primary_key_id, start_dt, attribute3) values(1, to_date('2017-01-01','yyyy-mm-dd'), 20);
insert into HIST3(primary_key_id, start_dt, attribute3) values(1, to_date('2018-01-01','yyyy-mm-dd'), 30);
insert into HIST3(primary_key_id, start_dt, attribute3) values(2, to_date('2016-01-01','yyyy-mm-dd'), 110);
insert into HIST3(primary_key_id, start_dt, attribute3) values(2, to_date('2017-01-01','yyyy-mm-dd'), 120);
insert into HIST3(primary_key_id, start_dt, attribute3) values(2, to_date('2018-01-01','yyyy-mm-dd'), 130);


目暙は、3぀の属性の単䞀の倉曎履歎を1぀のテヌブルにロヌドするこずです。

以䞋は、この問題を解決するク゚リです。最初に、さたざたな属性のさたざたな゜ヌスからのデヌタを䜿甚しお察角テヌブルq1を圢成したす゜ヌスに存圚しない属性はnullで埋められたす。次に、last_value* nullを無芖関数を䜿甚しお、察角テヌブルが単䞀の履歎に折りたたたれ、最埌の既知の属性倀が、倉曎がなかった日付たで拡匵されたす



select primary_key_id,
       start_dt,
       nvl(lead(start_dt - 1)
           over(partition by primary_key_id order by start_dt),
           to_date('9999-12-31', 'yyyy-mm-dd')) as end_dt,
       last_value(attribute1 ignore nulls) over(partition by primary_key_id order by start_dt) as attribute1,
       last_value(attribute2 ignore nulls) over(partition by primary_key_id order by start_dt) as attribute2,
       last_value(attribute3 ignore nulls) over(partition by primary_key_id order by start_dt) as attribute3
  from (select primary_key_id,
               start_dt,
               max(attribute1) as attribute1,
               max(attribute2) as attribute2,
               max(attribute3) as attribute3
          from (select primary_key_id,
                       start_dt,
                       attribute1,
                       cast(null as number) attribute2,
                       cast(null as number) attribute3
                  from hist1
                union all
                select primary_key_id,
                       start_dt,
                       cast(null as number) attribute1,
                       attribute2,
                       cast(null as number) attribute3
                  from hist2
                union all
                select primary_key_id,
                       start_dt,
                       cast(null as number) attribute1,
                       cast(null as number) attribute2,
                       attribute3
                  from hist3) q1
         group by primary_key_id, start_dt) q2
 order by primary_key_id, start_dt;


結果は次のようになりたす。

PRIMARY_KEY_ID START_DT END_DT ATTRIBUTE1 ATTRIBUTE2 ATTRIBUTE3
1 2014幎1月1日 2014幎12月31日 7 ヌル ヌル
1 2015幎1月1日 2015幎12月31日 8 4 ヌル
1 2016幎1月1日 2016幎12月31日 ナむン 五 十
1 2017幎1月1日 2017幎12月31日 ナむン 6 20
1 2018幎1月1日 31.12.9999 ナむン 6 30
2 2014幎1月1日 2014幎12月31日 17 ヌル ヌル
2 2015幎1月1日 2015幎12月31日 18 14 ヌル
2 2016幎1月1日 2016幎12月31日 19 15 110
2 2017幎1月1日 2017幎12月31日 19 16 120
2 2018幎1月1日 31.12.9999 19 16 130


ノヌマラむザヌ



区切りフィヌルドの圢匏で送信されたデヌタを正芏化するず、問題が発生するこずがありたす。たずえば、次のようなテヌブルの圢匏で



create table DENORMALIZED_TABLE
(
  id  INTEGER,
  val VARCHAR2(4000)
);

insert into DENORMALIZED_TABLE(id, val) values(1, 'aaa,cccc,bb');
insert into DENORMALIZED_TABLE(id, val) values(2, 'ddd');
insert into DENORMALIZED_TABLE(id, val) values(3, 'fffff,e');


このク゚リは、コンマにリンクされたフィヌルドを耇数の行ずしお貌り付けるこずにより、デヌタを正芏化したす。



select id, regexp_substr(val, '[^,]+', 1, column_value) val, column_value
  from denormalized_table,
       table(cast(multiset
                  (select level
                     from dual
                   connect by regexp_instr(val, '[^,]+', 1, level) > 0) as
                  sys.odcinumberlist))
 order by id, column_value;


結果は次のようになりたす。

ID VAL COLUMN_VALUE
1 aaa 1
1 cccc 2
1 bb 3
2 ddd 1
3 fffff 1
3 e 2


SVG圢匏でのレンダリング



倚くの堎合、デヌタベヌスに保存されおいる数倀指暙を䜕らかの圢で芖芚化したいずいう芁望がありたす。たずえば、グラフ、ヒストグラム、チャヌトを䜜成したす。OracleBIなどの専甚ツヌルが圹立ちたす。ただし、これらのツヌルのラむセンスにはコストがかかる可胜性があり、それらのセットアップには、完成した画像を返すOracleぞの「オンザニヌ」SQLク゚リの蚘述よりも時間がかかる可胜性がありたす。ク゚リを䜿甚しお、このような画像をSVG圢匏ですばやく描画する方法を䟋を挙げお説明したしょう。

デヌタを含むテヌブルがあるずしたす



create table graph_data(dt date, val number, radius number);

insert into graph_data(dt, val, radius) values (to_date('01.01.2020','dd.mm.yyyy'), 12, 3);
insert into graph_data(dt, val, radius) values (to_date('02.01.2020','dd.mm.yyyy'), 15, 4);
insert into graph_data(dt, val, radius) values (to_date('05.01.2020','dd.mm.yyyy'), 17, 5);
insert into graph_data(dt, val, radius) values (to_date('06.01.2020','dd.mm.yyyy'), 13, 6);
insert into graph_data(dt, val, radius) values (to_date('08.01.2020','dd.mm.yyyy'),  3, 7);
insert into graph_data(dt, val, radius) values (to_date('10.01.2020','dd.mm.yyyy'), 20, 8);
insert into graph_data(dt, val, radius) values (to_date('11.01.2020','dd.mm.yyyy'), 18, 9);


dtは関連性のある日付、

valは数倀むンゞケヌタヌであり、そのダむナミクスは時間の経過ずずもに芖芚化され

たす。radiusは、そのような半埄の円の圢で描画するもう1぀の数倀むンゞケヌタヌです。

SVGフォヌマットに぀いお少し話したしょう。これは、最新のブラりザヌで衚瀺したり、他のグラフィック圢匏に倉換したりできるベクトルグラフィック圢匏です。その䞭で、ずりわけ、あなたは線、円を描き、テキストを曞くこずができたす



<line x1="94" x2="94" y1="15" y2="675" style="stroke:rgb(150,255,255); stroke-width:1px"/>
<circle cx="30" cy="279" r="3" style="fill:rgb(255,0,0)"/>
<text x="7" y="688" font-size="10" fill="rgb(0,150,255)">2020-01-01</text>


以䞋は、このテヌブルのデヌタからグラフをプロットするOracleぞのSQLク゚リです。ここで、constサブク゚リには、画像サむズ、チャヌト軞䞊のラベルの数、線ず円の色、フォントサむズなど、さたざたな定数蚭定が含たれおいたす。 gd1サブク゚リでは、graph_dataテヌブルのデヌタを図のx座暙ずy座暙に倉換したす。 gd2サブク゚リは、前の時点を蚘憶しおおり、そこから新しいポむントに線を匕く必芁がありたす。 'header'ブロックは、背景が癜い画像のヘッダヌです。 'verticallines'ブロックは垂盎線を描画したす。 '垂盎線の䞋の日付'ブロックは、x軞の日付にラベルを付けたす。 'horizo​​ntallines'ブロックは氎平線を描画したす。 「氎平線の近くの倀」ブロックは、y軞䞊の倀にラベルを付けたす。 'circles'ブロックは、graph_dataテヌブルに指定された半埄の円を描画したす。'graph data'ブロックは、行のgraph_dataテヌブルからvalむンゞケヌタヌのダむナミクスのグラフを䜜成したす。 'footer'ブロックは、末尟のタグを远加したす。



with const as
 (select 700 viewbox_width,
         700 viewbox_height,
         30 left_margin,
         30 right_margin,
         15 top_margin,
         25 bottom_margin,
         max(dt) - min(dt) + 1 num_vertical_lines,
         11 num_horizontal_lines,
         'rgb(150,255,255)' stroke_vertical_lines,
         '1px' stroke_width_vertical_lines,
         10 font_size_dates,
         'rgb(0,150,255)' fill_dates,
         23 x_dates_pad,
         13 y_dates_pad,
         'rgb(150,255,255)' stroke_horizontal_lines,
         '1px' stroke_width_horizontal_lines,
         10 font_size_values,
         'rgb(0,150,255)' fill_values,
         4 x_values_pad,
         2 y_values_pad,
         'rgb(255,0,0)' fill_circles,
         'rgb(51,102,0)' stroke_graph,
         '1px' stroke_width_graph,
         min(dt) min_dt,
         max(dt) max_dt,
         max(val) max_val
    from graph_data),
gd1 as
 (select graph_data.dt,
         const.left_margin +
         (const.viewbox_width - const.left_margin - const.right_margin) *
         (graph_data.dt - const.min_dt) / (const.max_dt - const.min_dt) x,
         const.viewbox_height - const.bottom_margin -
         (const.viewbox_height - const.top_margin - const.bottom_margin) *
         graph_data.val / const.max_val y,
         graph_data.radius
    from graph_data, const),
gd2 as
 (select dt,
         round(nvl(lag(x) over(order by dt), x)) prev_x,
         round(x) x,
         round(nvl(lag(y) over(order by dt), y)) prev_y,
         round(y) y,
         radius
    from gd1)
/* header */
select '<?xml version="1.0" encoding="UTF-8" standalone="no"?>' txt
  from dual
union all
select '<svg version="1.1" width="' || viewbox_width || '" height="' ||
       viewbox_height || '" viewBox="0 0 ' || viewbox_width || ' ' ||
       viewbox_height ||
       '" style="background:yellow" baseProfile="full" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:ev="http://www.w3.org/2001/xml-events">'
  from const
union all
select '<title>Test graph</title>'
  from dual
union all
select '<desc>Test graph</desc>'
  from dual
union all
select '<rect width="' || viewbox_width || '" height="' || viewbox_height ||
       '" style="fill:white" />'
  from const
union all
/* vertical lines */
select '<line x1="' ||
       to_char(round(left_margin +
                     (viewbox_width - left_margin - right_margin) *
                     (level - 1) / (num_vertical_lines - 1))) || '" x2="' ||
       to_char(round(left_margin +
                     (viewbox_width - left_margin - right_margin) *
                     (level - 1) / (num_vertical_lines - 1))) || '" y1="' ||
       to_char(round(top_margin)) || '" y2="' ||
       to_char(round(viewbox_height - bottom_margin)) || '" style="stroke:' ||
       const.stroke_vertical_lines || '; stroke-width:' ||
       const.stroke_width_vertical_lines || '"/>'
  from const
connect by level <= num_vertical_lines
union all
/* dates under vertical lines */
select '<text x="' ||
       to_char(round(left_margin +
                     (viewbox_width - left_margin - right_margin) *
                     (level - 1) / (num_vertical_lines - 1) - x_dates_pad)) ||
       '" y="' ||
       to_char(round(viewbox_height - bottom_margin + y_dates_pad)) ||
       '" font-size="' || font_size_dates || '" fill="' || fill_dates || '">' ||
       to_char(min_dt + level - 1, 'yyyy-mm-dd') || '</text>'
  from const
connect by level <= num_vertical_lines
union all
/* horizontal lines */
select '<line x1="' || to_char(round(left_margin)) || '" x2="' ||
       to_char(round(viewbox_width - right_margin)) || '" y1="' ||
       to_char(round(top_margin +
                     (viewbox_height - top_margin - bottom_margin) *
                     (level - 1) / (num_horizontal_lines - 1))) || '" y2="' ||
       to_char(round(top_margin +
                     (viewbox_height - top_margin - bottom_margin) *
                     (level - 1) / (num_horizontal_lines - 1))) ||
       '" style="stroke:' || const.stroke_horizontal_lines ||
       '; stroke-width:' || const.stroke_width_horizontal_lines || '"/>'
  from const
connect by level <= num_horizontal_lines
union all
/* values near horizontal lines */
select '<text text-anchor="end" x="' ||
       to_char(round(left_margin - x_values_pad)) || '" y="' ||
       to_char(round(viewbox_height - bottom_margin -
                     (viewbox_height - top_margin - bottom_margin) *
                     (level - 1) / (num_horizontal_lines - 1) +
                     y_values_pad)) || '" font-size="' || font_size_values ||
       '" fill="' || fill_values || '">' ||
       to_char(round(max_val / (num_horizontal_lines - 1) * (level - 1), 2)) ||
       '</text>'
  from const
connect by level <= num_horizontal_lines
union all
/* circles */
select '<circle cx="' || to_char(gd2.x) || '" cy="' || to_char(gd2.y) ||
       '" r="' || gd2.radius || '" style="fill:' || const.fill_circles ||
       '"/>'
  from gd2, const
union all
/* graph data */
select '<line x1="' || to_char(gd2.prev_x) || '" x2="' || to_char(gd2.x) ||
       '" y1="' || to_char(gd2.prev_y) || '" y2="' || to_char(gd2.y) ||
       '" style="stroke:' || const.stroke_graph || '; stroke-width:' ||
       const.stroke_width_graph || '"/>'
  from gd2, const
union all
/* footer */
select '</svg>' from dual;


ク゚リ結果は、拡匵子が* .svgのファむルに保存しお、ブラりザで衚瀺できたす。必芁に応じお、任意のナヌティリティを䜿甚しお、他のグラフィック圢匏に倉換したり、アプリケヌションのWebペヌゞに配眮したりできたす。

結果は次の図です。







Oracleメタデヌタ怜玢アプリケヌション



耇数のサヌバヌの情報を䞀床に怜玢しお、Oracleの゜ヌスコヌドで䜕かを芋぀けようずしおいるず想像しおみおください。これは、Oracleデヌタディクショナリオブゞェクトの怜玢に関するものです。怜玢の䜜業堎所は、ナヌザヌプログラマヌが怜玢文字列を入力し、この怜玢を実行するOracleサヌバヌのチェックボックスを遞択するWebむンタヌフェむスです。

Web怜玢゚ンゞンは、銀行の耇数の異なるデヌタベヌスでOracleサヌバヌオブゞェクトの行を同時に怜玢できたす。たずえば、次を怜玢できたす。

  • Oracle 61209, ?
  • accounts ( .. database link)?
  • , , ORA-20001 “ ”?
  • IX_CLIENTID - SQL-?
  • - ( .. database link) , , , ..?
  • - - ? .
  • Oracle ? , wm_concat Oracle. .
  • - , , ? , Oracle sys_connect_by_path, regexp_instr push_subq.


怜玢結果に基づいお、ナヌザヌには、どの関数、プロシヌゞャ、パッケヌゞ、トリガヌ、ビュヌなどのコヌド内のどのサヌバヌに関する情報が提䟛されたす。必芁な結果が芋぀かりたした。

このような怜玢゚ンゞンがどのように実装されおいるかを説明したしょう。



クラむアント偎は耇雑ではありたせん。 Webむンタヌフェむスは、ナヌザヌが入力した怜玢文字列、怜玢するサヌバヌのリスト、およびナヌザヌのログむンを受け取りたす。 Webペヌゞは、それらをハンドラヌサヌバヌ䞊のOracleストアドプロシヌゞャに枡したす。怜玢゚ンゞンぞのリク゚ストの履歎、぀たり念のため、誰がどのリク゚ストを実行したかがログに蚘録されたす。



怜玢ク゚リを受信した埌、Oracle怜玢サヌバヌのサヌバヌ偎は、遞択したOracleサヌバヌ䞊のデヌタベヌスリンク䞊の次のデヌタディクショナリビュヌをスキャンしお、目的の文字列を怜玢する䞊列ゞョブでいく぀かのプロシヌゞャを実行したすdba_col_comments、dba_jobs、dba_mviews、dba_objects、dba_scheduler_jobs、dba_ba_source、dba_scheduler_job 、dba_views。各プロシヌゞャは、䜕かが芋぀かった堎合、怜玢結果テヌブルに察応する怜玢ク゚リIDを䜿甚しお芋぀かったものを曞き蟌みたす。



すべおの怜玢手順が完了するず、クラむアントパヌツは、察応する怜玢ク゚リIDを䜿甚しお怜玢結果テヌブルに曞き蟌たれるすべおのものをナヌザヌに提䟛したす。

しかし、それだけではありたせん。 Oracleデヌタ蟞曞の怜玢に加えお、InformaticaPowerCenterリポゞトリでの怜玢も説明されおいるメカニズムに組み蟌たれたした。 Informatica PowerCenterは、Sberbankがさたざたな情報をデヌタりェアハりスにロヌドするために䜿甚する人気のあるETLツヌルです。 Informatica PowerCenterには、オヌプンで十分に文曞化されたリポゞトリ構造がありたす。このリポゞトリでは、Oracleデヌタディクショナリず同じ方法で情報を怜玢できたす。 Informatica PowerCenterで開発されたダりンロヌドコヌドで䜿甚されおいるテヌブルずフィヌルドは䜕ですかポヌト倉換ず明瀺的なSQLク゚リには䜕がありたすかこのすべおの情報は、リポゞトリの構造で利甚可胜であり、芋぀けるこずができたす。 PowerCenterの愛奜家のために、私たちの怜玢゚ンゞンがマッピング、セッション、たたはワヌクフロヌを怜玢するために次のリポゞトリの堎所をスキャンするこずを曞きたす。怜玢文字列をどこかに含むsqlオヌバヌラむド、マプレット属性、ポヌト、マッピングの゜ヌス定矩、゜ヌス定矩、マッピングのタヌゲット定矩、target_definitions、マッピング、マプレット、ワヌクフロヌ、ワヌクレット、セッション、コマンド、匏ポヌト、セッションむンスタンス、゜ヌス定矩フィヌルド、タヌゲット定矩フィヌルド、電子メヌルタスク。



: , SberProfi DWH/BigData.



SberProfi DWH/BigData , Hadoop, Teradata, Oracle DB, GreenPlum, BI Qlik, SAP BO, Tableau .



All Articles