русс | укр

Языки программирования

ПаскальСиАссемблерJavaMatlabPhpHtmlJavaScriptCSSC#DelphiТурбо Пролог

Компьютерные сетиСистемное программное обеспечениеИнформационные технологииПрограммирование

Все о программировании


Linux Unix Алгоритмические языки Аналоговые и гибридные вычислительные устройства Архитектура микроконтроллеров Введение в разработку распределенных информационных систем Введение в численные методы Дискретная математика Информационное обслуживание пользователей Информация и моделирование в управлении производством Компьютерная графика Математическое и компьютерное моделирование Моделирование Нейрокомпьютеры Проектирование программ диагностики компьютерных систем и сетей Проектирование системных программ Системы счисления Теория статистики Теория оптимизации Уроки AutoCAD 3D Уроки базы данных Access Уроки Orcad Цифровые автоматы Шпаргалки по компьютеру Шпаргалки по программированию Экспертные системы Элементы теории информации

Материализованные вьюшки


Дата добавления: 2015-08-31; просмотров: 2495; Нарушение авторских прав


Материализованные вьюшки - это запросы, результаты выполнения которых сохраняются в виде таблиц и могут быть обновлены.

Пока мат.вьюшка обновляется, сессии oracle видят состояние мат.вьюшки до момента начала обновления.

Мат.вьюшки обычно применяются для не очень легких запросов или, например, запоминания данных, полученных по некруглосуточно работающим database link-ам.

 

Создадим большие таблицы:

create table kk_tbl_for_mv1 as select level as id, dbms_random.value as val from dual connect by level <= 1000000;

create table kk_tbl_for_mv2 as select level as id, dbms_random.value as val from dual connect by level <= 1500000;

create table kk_tbl_for_mv3 as select level as id, dbms_random.value as val from dual connect by level <= 2000000;

 

Создадим мат.вьюшки:

create materialized view kk_mv1 as select * from kk_tbl_for_mv1 where mod(id, 4) > 0;

create materialized view kk_mv2 as select * from kk_tbl_for_mv2 where mod(id, 4) > 0;

create materialized view kk_mv3 as select * from kk_tbl_for_mv3 where mod(id, 4) > 0;

 

Посмотрим количества строк в этих мат.вьюшках:

select count(1) from kk_mv1;

select count(1) from kk_mv2;

select count(1) from kk_mv3;

 

Убедимся, что в user_objects на каждую мат.вьюшку создается 2 записи - таблица и мат.вьюшка (соответственно и в дереве объектов PL/SQL Developer-а можно увидеть каждый из этих объектов):

select * from user_objects where object_name like 'KK_MV%';

 

На таблицы мат.вьюшек можно создавать индексы.

Обновлять мат.вьюшки можно командой dbms_mview.refresh, например:

begin dbms_mview.refresh('KK_MV1'); end;

 

Для следующего примера воспользуемся таблицей логирования и сиквенсом для генерации значений ее первичного ключа ID:

create table kk_mv_log (id number, lc_date date, lc_message varchar2(200));



create sequence sq_kk_mv_log;

 

Запустим одновременное обновление наших мат.вьюшек в "одноразовых" job-ах, которые выполнятся в параллельных сессиях oracle, что быстрее последовательного обновления.

Воспользуемся вариантом вызова dbms_job.submit без указания параметров next и interval, что создаёт "одноразовый" джоб.

Во время выполнения нижеприведенного блока будем смотреть за активными сессиями в PL/SQL Developer-е (Tools -> Sessions -> Active sessions), а еще посматривать за состоянием системной вьюшки dba_jobs_running, где видны выполняющиеся в текущий момент job-ы:

declare

v_job_number1 integer := 0;

v_job_number2 integer := 0;

v_job_number3 integer := 0;

v_is_running integer := 1;

begin

dbms_job.submit(job => v_job_number1,

what => 'declare v_sqlerrm varchar2(300);

begin

insert into kk_mv_log(id, lc_date, lc_message) values(sq_kk_mv_log.nextval, sysdate, ''Начало обновления KK_MV1'');

dbms_mview.refresh(''KK_MV1'');

insert into kk_mv_log(id, lc_date, lc_message) values(sq_kk_mv_log.nextval, sysdate, ''Завершение обновления KK_MV1'');

exception when others then

v_sqlerrm := sqlerrm;

insert into kk_mv_log(id, lc_date, lc_message) values(sq_kk_mv_log.nextval, sysdate, ''Проблемы при обновлении KK_MV1: '' || v_sqlerrm);

end;');

dbms_job.submit(job => v_job_number2,

what => 'declare v_sqlerrm varchar2(300);

begin

insert into kk_mv_log(id, lc_date, lc_message) values(sq_kk_mv_log.nextval, sysdate, ''Начало обновления KK_MV2'');

dbms_mview.refresh(''KK_MV2'');

insert into kk_mv_log(id, lc_date, lc_message) values(sq_kk_mv_log.nextval, sysdate, ''Завершение обновления KK_MV2'');

exception when others then

v_sqlerrm := sqlerrm;

insert into kk_mv_log(id, lc_date, lc_message) values(sq_kk_mv_log.nextval, sysdate, ''Проблемы при обновлении KK_MV2: '' || v_sqlerrm);

end;');

dbms_job.submit(job => v_job_number3,

what => 'declare v_sqlerrm varchar2(300);

begin

insert into kk_mv_log(id, lc_date, lc_message) values(sq_kk_mv_log.nextval, sysdate, ''Начало обновления KK_MV3'');

dbms_mview.refresh(''KK_MV3'');

insert into kk_mv_log(id, lc_date, lc_message) values(sq_kk_mv_log.nextval, sysdate, ''Завершение обновления KK_MV3'');

exception when others then

v_sqlerrm := sqlerrm;

insert into kk_mv_log(id, lc_date, lc_message) values(sq_kk_mv_log.nextval, sysdate, ''Проблемы при обновлении KK_MV3: '' || v_sqlerrm);

end;');

commit;

loop

/* ожидание 1 секунды */

dbms_lock.sleep(1);

/* в dba_jobs_running джоб появляется не сразу, чтобы им воспользоваться надо сделать задержку до цикла, поэтому воспользуемся user_jobs */

select count(1)

into v_is_running

from user_jobs

where job in (v_job_number1, v_job_number2, v_job_number3);

exit when v_is_running = 0;

end loop;

end;

 

Видим, что по завершении блока одноразовые джобы исчезли из user_jobs и dba_jobs_running:

select * from user_jobs order by job desc;

select * from dba_jobs_running;

 

Посмотрим дату последнего обновления наших мат.вьюшек в user_mviews:

select mview_name, query, last_refresh_date from user_mviews where mview_name like 'KK_MV%';

 

Посмотрим в наш лог обновления мат.вьюшек:

select * from kk_mv_log order by id desc;

"Расклейка" и "склейка" строк.

В этом разделе рассмотрим часто возникающие задачи по склейке и расклейке строк. Здесь применяются регулярные выражения и иерархические запросы. Не обязательно глубоко вникать в эти примеры, главное научиться писать такие же запросы на других структурах данных.

“Расклейка” одной строки.

Часто возникают задачи, когда в запросе из строки вида 'A2,8F8,J5,I77' необходимо сделать 4 строки:

A2

8F8

J5

I77

Применяя иерархический запрос и регулярные выражения, напишем запрос, который "расклеивает" строку, делая из нее несколько строк:

select regexp_substr(s, '[^,]+', 1, level) piece

from (select 'A2,8F8,J5,I77' s from dual)

connect by regexp_substr(s, '[^,]+', 1, level) is not null;

“Расклейка” нескольких строк с группировкой.

Теперь приведу волшебный запрос, который делает “расклейку” не по одной строке, а по всей таблице с группировкой:

with sample_table as

(select 'id1' col1, 'aaa,bb,cccc' col2

from dual

union all

select 'id2', 'ddd'

from dual

union all

select 'id3', 'fff,ggg' from dual)

select col1, regexp_substr(col2, '[^,]+', 1, column_value) col2

from sample_table,

table(cast(multiset

(select level

from dual

connect by regexp_instr(col2, '[^,]+', 1, level) > 0) as

sys.odcinumberlist))

order by col1, column_value;

 

Также в некоторых версиях Oracle будет работать более понятный запрос:

with sample_table as

(select 'id1' col1, 'aaa,bb,cccc' col2

from dual

union all

select 'id2', 'ddd'

from dual

union all

select 'id3', 'fff,ggg' from dual)

select col1, regexp_substr(col2, '[^,]+', 1, level) piece

from sample_table

connect by regexp_substr(col2, '[^,]+', 1, level) is not null

and prior col1 = col1

and prior dbms_random.value is not null;

 

Но первый вариант надежнее.

“Склейка” в одну строку.

Также часто возникают задачи когда, наоборот, в запросе из 4 различных строк вида

A2

8F8

J5

I77

необходимо сделать склеенную строку ' 8F8,A2,I77,J5' (упорядочив по значениям, за это отвечает “over(order by id)”):

 

Применяя функцию sys_connect_by_path, пошагово склеиваем строку:

select ids

from (select ltrim(sys_connect_by_path(id, ','), ',') as ids, level

from (select id, lag(id) over(order by id) as prev_id

from (select 'A2' id

from dual

union all

select '8F8' id

from dual

union all

select 'J5' id

from dual

union all

select 'I77' id from dual))

start with prev_id is null

connect by prev_id = prior id

order by level desc)

where rownum = 1;

“Склейка” нескольких строк с группировкой.

Еще одним способом склеить строку является использование агрегирующей функции WM_CONCAT (она склеивает только через запятую):

select pk, wm_concat(id)

from (select 1 pk, 'A2' id

from dual

union all

select 1 pk, '8F8' id

from dual

union all

select 1 pk, 'J5' id

from dual

union all

select 1 pk, 'I77' id

from dual

union all

select 2 pk, 'GGG' id

from dual

union all

select 2 pk, 'HH69' id from dual)

group by pk;

 

Далее приведу запрос, который склеивает данные с группировкой и сортировкой склеиваемых данных в указанном порядке. Рассмотрим таблицу людей и их хобби с датой начала увлечения. Склеим набор хобби каждого человека в порядке начала увлечения:

with a as

(select /*+ materialize*/

'Прохоров' name,

'играть в политику' hobby,

to_date('20.05.2011', 'dd.mm.yyyy') hobby_start_date

from dual

union all

select 'Абрамович' name,

'кататься на яхте' hobby,

to_date('17.11.2005', 'dd.mm.yyyy') hobby_start_date

from dual

union all

select 'Прохоров' name,

'отдыхать в Куршавеле' hobby,

to_date('31.01.2007', 'dd.mm.yyyy') hobby_start_date

from dual

union all

select 'Вексельберг' name,

'покупать яйца Фаберже' hobby,

to_date('20.02.2004', 'dd.mm.yyyy') hobby_start_date

from dual

union all

select 'Абрамович' name,

'покупать футболистов' hobby,

to_date('11.06.2003', 'dd.mm.yyyy') hobby_start_date

from dual

union all

select 'Прохоров' name,

'изобретать Ё-мобили' hobby,

to_date('29.09.2009', 'dd.mm.yyyy') hobby_start_date

from dual)

select name, max(hobby_list) keep(dense_rank last order by lvl)

from (select name,

ltrim(sys_connect_by_path(hobby, ','), ',') as hobby_list,

level lvl

from (select name,

hobby,

lag(hobby) over(partition by name order by hobby_start_date) as prev_hobby

from a)

start with prev_hobby is null

connect by name = prior name

and prev_hobby = prior hobby)

group by name

order by name;



<== предыдущая лекция | следующая лекция ==>
Задача. Вызов многозначной функции. | Задача. Простая расклейка-склейка.


Карта сайта Карта сайта укр


Уроки php mysql Программирование

Онлайн система счисления Калькулятор онлайн обычный Инженерный калькулятор онлайн Замена русских букв на английские для вебмастеров Замена русских букв на английские

Аппаратное и программное обеспечение Графика и компьютерная сфера Интегрированная геоинформационная система Интернет Компьютер Комплектующие компьютера Лекции Методы и средства измерений неэлектрических величин Обслуживание компьютерных и периферийных устройств Операционные системы Параллельное программирование Проектирование электронных средств Периферийные устройства Полезные ресурсы для программистов Программы для программистов Статьи для программистов Cтруктура и организация данных


 


Не нашли то, что искали? Google вам в помощь!

 
 

© life-prog.ru При использовании материалов прямая ссылка на сайт обязательна.

Генерация страницы за: 0.198 сек.