- •Текст вопроса
- •Текст вопроса
- •cursor_sharing
- •exact
- •force
- •similar
- •_disable_cursor_sharing
- •db_file_multiblock_read_count
- •optimizer_dynamic_sampling
- •Текст вопроса
- •Сбор статистики
- •Oracle не работает планировщик заданий
- •How does AUTO_SAMPLE_SIZE work in Oracle Database 11g?
- •By Hong Su on Apr 08, 2013
- •Effect of auto sample size on histogram gathering
- •Effect of auto sample size on index stats gathering
Object 21
Лабораторные по курсу оптимизация БД Oracle номер 6
1. Выполните скрипт join_setup.sql из-под учётной записи пользователя SYS.
|
|
|
|
|
|
|
|
|
|
|
|
join_setup.sql |
-- execute as sys user |
|
|
|
|
|
|
|
|||||
GRANT |
|
|
ANY |
|
|
|
|
|
|
|||
SELECT |
|
dictionary |
TO |
OE; |
||||||||
GRANT |
select |
_ |
catalog_role |
TO |
OE; |
|
||||||
GRANT |
|
|
|
|
||||||||
SELECT |
|
ANY |
dictionary |
|
TO |
SH; |
|
|||||
GRANT |
select |
_ |
catalog_role |
TO |
SH; |
|
||||||
EXIT |
; |
|
|
|
|
|
|
|
|
|
|
|
2.Подключитесь к схеме пользователя SCOTT и далее выполняйте запросы под этой учётной записью, пока не будет сказано иначе.
3.Соединение вложенными циклами (Nested Loop Join)
a. Выполните трассировку (autotrace) запроса small_tables_join.sql дважды - для загрузки буферного кэша.
(1) Приведите скриншот второго плана выполнения и статистики, отметьте стоимость и число логических чтений.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
small_tables_join.sql |
||||
SELECT |
ename |
, |
e.deptno |
, |
d.deptno |
, |
d.dname |
|
|
|
||||||||||
FROM |
emp e |
, |
dept |
d |
|
|
|
|
|
|
|
|
|
|
|
|||||
WHERE |
|
e.deptno |
= |
|
|
|
|
|
|
|
|
|
||||||||
|
|
|
d.deptno |
AND |
ename |
LIKE |
'A%' |
; |
b. Очистите буферный кэш
ALTERSYSTEM flush buffer_cache;
и выполните трассировку запроса с добавлением хинта USE_HASH (small_tables_hash_join.sql).
(2) Приведите скриншот плана выполнения и статистики, прокомментируйте основные различия.
|
|
|
|
|
|
|
|
|
|
|
small_tables_hash_join.sql |
|
|||||||||
SELECT |
/*+ USE_HASH(E D) */ ename |
, |
e.deptno |
, |
d.deptno |
, |
d.dname |
||||||||||||||
FROM |
emp e |
, |
dept |
d |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|||
WHERE |
|
e.deptno |
= |
|
|
|
|
|
|
|
|
|
|||||||||
|
|
|
d.deptno |
AND |
ename |
LIKE |
'A%' |
; |
c.Снова очистите буферный кэш
ALTERSYSTEM flush buffer_cache;
и выполните трассировку запроса с добавлением хинта USE_MERGE (small_tables_merge_join.sql).
(3) Приведите скриншот плана выполнения и статистики, прокомментируйте основные различия.
|
|
|
|
|
|
|
|
|
|
|
small_tables_merge_join.sql |
|
||||||||
SELECT |
/*+ USE_MERGE(E D) */ ename |
, |
e.deptno |
, |
|
d.deptno |
, |
d.dname |
||||||||||||
FROM |
emp e |
, |
dept |
d |
|
|
|
|
|
|
|
|
|
|
|
|
|
|||
WHERE |
|
e.deptno |
= |
|
|
|
|
|
|
|
|
|
||||||||
|
|
|
d.deptno |
AND |
ename |
LIKE |
'A%' |
; |
(4)Какой план, на Ваш взгляд, оказался лучшим и почему?
2задание
4.Подключитесь к схеме пользователя OE и далее выполняйте запросы под этой учётной записью, пока не будет сказано иначе.
5. Соединение слиянием (Merge Join)
a. Выполните трассировку (autotrace) запроса oe_query.sql дважды - для загрузки буферного кэша.
(1) Приведите скриншот второго плана выполнения и статистики, отметьте стоимость и число логических чтений.
|
|
|
|
|
|
|
|
|
oe_query.sql |
SELECT |
* |
|
|
|
|
|
|
|
|
FROM |
orders h |
, |
order_items l |
|
|
||||
WHERE |
l.order |
_ |
id |
= |
h.order_id; |
|
b. Очистите буферный кэш
ALTERSYSTEM flush buffer_cache;
и выполните трассировку запроса с добавлением хинта USE_HASH (oe_query_hash.sql).
(2) Приведите скриншот плана выполнения и статистики, прокомментируйте основные различия.
oe_query_hash.sql
SELECT /*+ USE_HASH(h l) */ *
FROM orders h, order_items l WHERE l.order_id = h.order_id;
c.Снова очистите буферный кэш
ALTERSYSTEM flush buffer_cache;
и выполните трассировку запроса с добавлением хинта USE_NL (oe_query_nl.sql).
(3) Приведите скриншот плана выполнения и статистики, прокомментируйте основныеразличия.
oe_query_nl.sql
SELECT /*+ USE_NL(h l) */ *
FROM orders h, order_items l WHERE l.order_id = h.order_id;
(4) Какой план, на Ваш взгляд, оказался лучшим и почему?
3задание
6.Подключитесь к схеме пользователя SH и далее выполняйте запросы под этой учётной записью, пока не будет сказано иначе.
7. Хэш-соединение (Hash Join)
a. Выполните трассировку (autotrace) запроса sh_query.sql дважды - для загрузки буферного кэша.
(1) Приведите скриншот второго плана выполнения и статистики, отметьте стоимость и число логических чтений.
sh_query.sql
SELECT c.cust_first_name, c.cust_last_name, c.cust_id, COUNT(s.prod_id)
FROM sh.customers c, sh.sales s WHERE c.cust_id = s.cust_id
AND c.cust_id < 100
GROUPBY c.cust_first_name, c.cust_last_name, c.cust_id;
b. Очистите буферный кэш
ALTERSYSTEM flush buffer_cache;
и выполните трассировку запроса с добавлением хинта USE_NL (sh_query_nl.sql).
(2) Приведите скриншот плана выполнения и статистики, прокомментируйте основныеразличия.
SELECT /*+ USE_NL(c s) */
sh_query_nl.sql
c.cust_first_name, c.cust_last_name, c.cust_id, COUNT(s.prod_id)
FROM sh.customers c, sh.sales s
WHERE c.cust_id = s.cust_id
AND c.cust_id < 100
GROUPBY c.cust_first_name, c.cust_last_name, c.cust_id;
c. Снова очистите буферный кэш
ALTERSYSTEM flush buffer_cache;
и выполните трассировку запроса с добавлением хинта USE_MERGE (sh_query_merge.sql)
.(3) Приведите скриншот плана выполнения и статистики, прокомментируйте основные различия.
SELECT /*+ USE_MERGE(c s) */
sh_query_merge.sql
c.cust_first_name, c.cust_last_name, c.cust_id, COUNT(s.prod_id)
FROM sh.customers c, sh.sales s
WHERE c.cust_id = s.cust_id
AND c.cust_id < 100
GROUPBY c.cust_first_name, c.cust_last_name, c.cust_id;
(4) Какой план, на Ваш взгляд, оказался лучшим и почему?
Номер 7
Использование итератора значений списка IN (IN-list Iterator)
Подключитесь к схеме пользователя SH и выполните трассировку (autotrace) запроса query08.sql.
(1) Приведите скриншот плана выполнения и прокомментируйте результат.
|
|
|
|
|
|
|
|
|
|
|
|
|
query08.sql |
SELECT |
c. |
* |
|
|
|
|
|
|
|
|
|
|
|
FROM |
|
customers c |
|
|
|
|
|
|
|
|
|
||
WHERE |
cust_id |
IN |
( |
88340 |
, |
104590 |
, |
44910 |
) |
; |
|
Использование хэш-кластеров (Hach Clusters)
Выполните скрипт shc_setup.sql для создания и наполнения схемы SCH. В числе прочего будет
создана таблица BIGEMP_FACT, входящая в однотабличный (single table) хэш-кластер BIGEMP_CLUSTER. Таблица была отсортирована по столбцам deptno и sal перед применением хэшфункции.
shc_setup.sql
-- run with sqlplus /nolog @shc_setup.sql
CONNECT/AS sysdba
DROPUSER shc CASCADE;
CREATE USER shc IDENTIFIED BY shc;
GRANT DBA TO SHC;
GRANT select_catalog_role TO SHC;
GRANTSELECTANY dictionary TO SHC;
CONNECT shc/shc
SET echo ON
SET linesize 200
DROPCLUSTER bigemp_cluster including tables;
CREATE CLUSTER bigemp_cluster (deptno NUMBER, sal NUMBER sort)
HASHKEYS 10000
single TABLE HASH IS deptno SIZE 50
TABLESPACE users;
CREATE TABLE bigemp_fact (
empno NUMBER PRIMARY KEY, sal NUMBER sort, job VARCHAR2(12) NOT NULL, deptno NUMBER NOT NULL, hiredate DATE NOT NULL)
CLUSTER bigemp_cluster (deptno, sal);
BEGIN
FOR i IN 1..1400000 LOOP
INSERT INTO bigemp_fact VALUES(i,i,'J1',10,SYSDATE);
END LOOP;
COMMIT;
END;
/
BEGIN
FOR i IN 1..1400000 LOOP
INSERT INTO bigemp_fact VALUES(1400000+i,i,'J1',20,SYSDATE);
END LOOP;
COMMIT;
END;
/
EXEC dbms_stats.gather_schema_stats('SHC');
EXIT
4. Создайте соединение для пользователя SCH со следующими параметрами:
Connection Name: shc Username: shc Password: shc
SID: orcl
Далее используйте это соединение, пока не будет сказано иначе.
5. Выполните скрипт query15a.sql - для задания значений параметров инициализации WORKAREA_SIZE_POLICY
иSORT_AREA_SIZE
иочистки буферного кэша и разделяемого пула.
query15a.sql
SET echo off
ALTER SESSION SET workarea_size_policy=manual;
ALTERSESSIONSET sort_area_size=50000;
ALTER SYSTEM flush shared_pool;
ALTERSYSTEM flush buffer_cache;
6.Выполните трассировку (autotrace) запроса query15b.sql.
(1) Приведите скриншот плана выполнения, отметьте время выполнения запроса, стоимость и количество логических чтений. Прокомментируйте результат.
query15b.sql
SELECT*FROM bigemp_fact WHERE deptno=10;
7.Снова выполните скрипт query15a.sql.
query15a.sql
SET echo off
ALTER SESSION SET workarea_size_policy=manual;
ALTERSESSIONSET sort_area_size=50000;
ALTER SYSTEM flush shared_pool;
ALTERSYSTEM flush buffer_cache;
8.Выполните трассировку (autotrace) запроса query16.sql.
(2) Приведите скриншот плана выполнения и прокомментируйте результат.
query16.sql
SELECT*FROM bigemp_fact WHERE deptno=10ORDERBY sal;
9.Снова выполните скрипт query15a.sql.
query15a.sql
SET echo off
ALTER SESSION SET workarea_size_policy=manual;
ALTERSESSIONSET sort_area_size=50000;
ALTER SYSTEM flush shared_pool;
ALTERSYSTEM flush buffer_cache;
10.Выполните трассировку (autotrace) запроса query17.sql.
(3) Приведите скриншот плана выполнения и прокомментируйте результат.
query17.sql
SELECT*FROM bigemp_fact WHERE deptno=10ORDERBY sal DESC;
11.Снова выполните скрипт query15a.sql.
query15a.sql
SET echo off
ALTER SESSION SET workarea_size_policy=manual;
ALTERSESSIONSET sort_area_size=50000;
ALTER SYSTEM flush shared_pool;
ALTERSYSTEM flush buffer_cache;
12.Выполните трассировку (autotrace) запроса query18.sql.
(4) Приведите скриншот плана выполнения и прокомментируйте результат.
query18.sql
SELECT*FROM bigemp_fact WHERE deptno=10ORDERBY empno;
13.Снова выполните скрипт query15a.sql.
query15a.sql
SET echo off
ALTER SESSION SET workarea_size_policy=manual;
ALTERSESSIONSET sort_area_size=50000;
ALTER SYSTEM flush shared_pool;
ALTERSYSTEM flush buffer_cache;
14.Выполните трассировку (autotrace) запроса query19.sql.
(5) Приведите скриншот плана выполнения и прокомментируйте результат.
query19.sql
SELECT*FROM bigemp_fact WHERE deptno=10ORDERBY sal, empno;
3 задание
Использование индексированного кластера (Index Cluster)
15. Выполните скрипт nic_setup.sql для создания и наполнения схемы NIC. В числе прочего будут созданы большие таблицы EMP и DEPT и индексы для столбца deptno каждой из этих таблиц.
nic_setup.sql
-- run with sqlplus /nolog
CONNECT/AS sysdba
DROPUSER NIC CASCADE;
CREATE USER nic IDENTIFIED BY nic;
GRANT DBA TO NIC;
GRANT SELECT_CATALOG_ROLE TO NIC;
GRANTSELECTANY dictionary TO NIC;
CONNECT nic/nic
SET echo ON
DROPCLUSTER emp_dept including tables;
DROP TABLE emp purge;
DROPTABLE dept purge;
CREATE TABLE emp ( empno NUMBER(7) ,
ename VARCHAR2(15) NOT NULL, job VARCHAR2(9) ,
mgr NUMBER(7) , hiredate DATE , sal NUMBER(7) , comm NUMBER(7) , deptno NUMBER(3)
);
CREATE TABLE dept ( deptno NUMBER(3) , dname VARCHAR2(14), loc VARCHAR2(14), c VARCHAR2(500)
);
CREATE INDEX emp_index
ON emp(deptno)
TABLESPACE users
STORAGE (INITIAL 50K
NEXT 50K
MINEXTENTS 2
MAXEXTENTS 10
PCTINCREASE 33);
CREATE INDEX dept_index
ON dept(deptno)
TABLESPACE users
STORAGE (INITIAL 50K
NEXT 50K
MINEXTENTS 2
MAXEXTENTS 10
PCTINCREASE 33);
BEGIN
FOR i IN 1..999 LOOP
INSERT INTO dept VALUES (i,'D'||i,'L'||i,dbms_random.string('u',500));
END LOOP;
COMMIT;
END;
/
BEGIN
FOR i IN 1..500000 LOOP
INSERT INTO emp VALUES
(i,dbms_random.string('u',15),dbms_random.string('u',9),i,SYSDATE,i,i,MOD(i,999));
END LOOP;
COMMIT;
END;
/
EXEC dbms_stats.gather_schema_stats('NIC');
EXIT;
16. Создайте соединение для пользователя NIC со следующими параметрами:
Connection Name: nic Username: nic Password: nic
SID: orcl
Далее используйте это соединение, пока не будет сказано иначе.
17.Выполните скрипт nic_query_a.sql, который выполняет те же действия, что
и query15a.sql + устанавливает значение параметра инициализации HASH_AREA_SIZE.
nic_query_a.sql
ALTER SESSION SET workarea_size_policy=manual;
ALTER SESSION SET sort_area_size=50000;
ALTERSESSIONSET hash_area_size=5000;
18.Выполните трассировку (autotrace) запроса nic_query_b.sql.
(1) Приведите план выполнения, отметьте время выполнения запросса, стоимость и количество логических чтений
Прокомментируйте результат.
nic_query_b.sql
SELECT*FROM emp,dept WHERE emp.deptno=dept.deptno AND emp.deptno >800;
19.Как можно повысить производительность предыдущего запроса?
(2) Приведите своё решение (теоретическое описание, выполнять не нужно). Создать индексный кластер
20. Выполните скрипт ic_setup.sql для создания и наполнения схемы IC. ic_setup.sql
-- run with sqlplus /nolog
CONNECT/AS sysdba
DROPUSER IC CASCADE;
CREATEUSER ic IDENTIFIEDBY ic;
|
|
|
|
|
|
|
|
|
|
GRANT |
DBA |
TO |
ic; |
|
|
|
|
GRANT |
SELECT_CATALOG_ROLE |
TO |
ic; |
|
||||
GRANT |
SELET |
ANY |
DICTIONARY |
TO |
ic; |
CONNECT ic/ic
SET echo ON
DROP TABLE emp purge;
DROPTABLE dept purge;
DROPCLUSTER emp_dept including tables;
CREATE CLUSTER emp_dept (deptno NUMBER(3))
SIZE 600
TABLESPACE users
STORAGE (INITIAL 200K
NEXT 300K
MINEXTENTS 2
PCTINCREASE 33);
CREATE TABLE emp ( empno NUMBER(7) ,
ename VARCHAR2(15) NOT NULL, job VARCHAR2(9) ,
mgr NUMBER(7) , hiredate DATE , sal NUMBER(7) , comm NUMBER(7) , deptno NUMBER(3))
CLUSTER emp_dept (deptno);
CREATE TABLE dept ( deptno NUMBER(3) , dname VARCHAR2(14), loc VARCHAR2(14), c VARCHAR2(500))
CLUSTER emp_dept (deptno);
CREATE INDEX emp_dept_index
ON CLUSTER emp_dept
TABLESPACE users
STORAGE (INITIAL 50K
NEXT 50K
MINEXTENTS 2
MAXEXTENTS 10
PCTINCREASE 33);
BEGIN
FOR i IN 1..999 LOOP
INSERT INTO dept VALUES (i,'D'||i,'L'||i,dbms_random.string('u',500));
END LOOP;
COMMIT;
END;
/
BEGIN
FOR i IN 1..500000 LOOP
INSERT INTO emp VALUES
(i,dbms_random.string('u',15),dbms_random.string('u',9),i,SYSDATE,i,i,MOD(i,999));
END LOOP;
COMMIT;
END;
/
EXEC dbms_stats.gather_schema_stats('IC');
EXIT;
21. Создайте соединение для пользователя IC со следующими параметрами:
Connection Name: ic Username: ic Password: ic
SID: orcl
Далее используйте это соединение, пока не будет сказано иначе.
22.Снова выполните скрипт nic_query_a.sql.
nic_query_a.sql
ALTER SESSION SET workarea_size_policy=manual;
ALTER SESSION SET sort_area_size=50000;
ALTERSESSIONSET hash_area_size=5000;
23. Ещё раз выполните трассировку (autotrace) запроса nic_query_b.sql.
(3) Приведите план выполнения и прокомментируйте результат.
nic_query_b.sql
SELECT*FROM emp,dept WHERE emp.deptno=dept.deptno AND emp.deptno >800;
24.Важно: закройте все окна SQL Developer, относящиеся к сессиям пользователя SH и разорвите соединение (disconnect). Завершите также сессии SQL*Plus, если таковые есть.
25.В окне терминала выполните скрипт ap_cleanup.sh - для очистки окружения. Этот скрипт
пересоздаёт схему SH. Если Вы не увидели сообщения об успешном удалении пользователя или появилось сообщение об ошибке, подождите, пока скрипт завершит свою работу, убедитесь, что все сессии для пользователя SH завершены и соединения закрыты, после чего запустите скрипт снова.
ap_cleanup.sh
#!/bin/bash
cd/home/oracle/labs/SQL_Access_Advisor/shсв
cp*$ORACLE_HOME/demo/schema/sales_history
sqlplus /as sysdba @/home/oracle/labs/Access_Paths/ap_cleanup.sql
SET echo ON
@sh_main sh example temp oracle_4U /u01/app/oracle/product/11.2.0/dbhome_1/demo/SCHEMA/sales_history/ /home/oracle/ v3
EXIT;
@sh_main
номер 7.2
Скрипты, упоминаемые в данном блоке упражнений, расположены в каталоге$HOME/labs/Query_Result_Cache.
1. Выполните скриптresult_cache_setup.shдля создания и наполнения схемы QRC.
result_cache_setup.sql
SET echo ON
DROPUSER qrc CASCADE;
CREATE USER qrc IDENTIFIED BY qrc
DEFAULT TABLESPACE users
TEMPORARYTABLESPACE temp;
GRANTCONNECT,RESOURCE, dba TO qrc;
CONNECT qrc/qrc
EXEC dbms_result_cache.flush;
DROPTABLE cachejfv purge;
CREATETABLE cachejfv(c VARCHAR2(500))TABLESPACE users;
INSERT INTO cachejfv
VALUES('aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaa');
INSERT INTO cachejfv SELECT * FROM cachejfv; INSERT INTO cachejfv SELECT * FROM cachejfv; INSERT INTO cachejfv SELECT * FROM cachejfv; INSERT INTO cachejfv SELECT * FROM cachejfv; INSERT INTO cachejfv SELECT * FROM cachejfv; INSERT INTO cachejfv SELECT * FROM cachejfv; INSERT INTO cachejfv SELECT * FROM cachejfv; INSERT INTO cachejfv SELECT * FROM cachejfv; INSERT INTO cachejfv SELECT * FROM cachejfv; INSERT INTO cachejfv SELECT * FROM cachejfv; INSERT INTO cachejfv SELECT * FROM cachejfv; INSERT INTO cachejfv SELECT * FROM cachejfv; INSERT INTO cachejfv SELECT * FROM cachejfv; INSERT INTO cachejfv SELECT * FROM cachejfv; INSERT INTO cachejfv SELECT * FROM cachejfv; INSERT INTO cachejfv SELECT * FROM cachejfv; INSERT INTO cachejfv SELECT * FROM cachejfv; INSERT INTO cachejfv SELECT * FROM cachejfv; INSERT INTO cachejfv SELECT * FROM cachejfv; INSERT INTO cachejfv SELECT * FROM cachejfv; INSERTINTO cachejfv SELECT*FROM cachejfv;
INSERTINTO cachejfv VALUES('b');
COMMIT;
ALTERSYSTEM flush buffer_cache;
2. Создайте соединение для пользователя QRC со следующими параметрами:
Connection Name: qrc Username: qrc Password: qrc
SID: orcl
Далее используйте это соединение, пока не будет сказано иначе.
3. Определите текущее содержимое кэша результатов с помощью скрипта check_result_cashe.sql.
(1) Прокомментируйте
SELECT TYPE, status, name, object_no, row_count,row_size_avg
FROM v$result_cache_objects
ORDERBY1;
4.Выполните скрипт query1.sql.
(2) Зафиксируйте время, в течение которого он выполнялся.
SELECT /*+ result_cache q_name(Q1) */
query1.sql
COUNT(*)
FROM cachejfv c1, cachejfv c2, cachejfv c3, cachejfv c4, cachejfv c5,
cachejfv c6, cachejfv c7
WHERE c1.c='b' AND c2.c ='b' AND c3.c ='b' AND c4.c ='b' AND c5.c ='b'AND c6.c ='b'AND c7.c ='b';
время 1.544ms elasted
5.С помощью кнопки Explain Plan
(3) выведите план выполнения запроса из скрипта query1.sql. Что Вы можете отметить (по теме лабораторной)?
6. Снова определите текущее содержимое кэша результатов с помощью
скрипта check_result_cashe.sql. (4) Приведите и прокомментируйте результат.
check_result_cache.sql
SELECT TYPE, status, name, object_no, row_count,row_size_avg
FROM v$result_cache_objects
ORDERBY1;
7.Очистите буферный кэш Вашего экземпляра:
ALTERSYSTEM FLUSH buffer_cache;
8.Снова выполните скрипт query1.sql. (5) Зафиксируйте время выполнения и прокомментируйте результат.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
query1.sql |
|
|
|
|
|
|
||||
SELECT |
/*+ result_cache q_name(Q1) */ |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
||||||||||||||||||
COUNT |
(*) |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
||
FROM |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
||||
|
cachejfv c1 |
, |
cachejfv c2 |
, |
cachejfv c3 |
, |
cachejfv c4 |
, |
cachejfv c5 |
, |
|||||||||||||||||||||||
cachejfv c6 |
, |
cachejfv c7 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|||||||||||
|
|
|
= |
'b' |
|
AND |
c2.c |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|||||||||||
WHERE |
c1.c |
|
= |
'b' |
|
AND |
c3.c |
= |
'b' |
|
AND |
c4.c |
= |
'b' |
|||||||||||||||||||
AND |
|
c5.c |
= |
'b' |
|
AND |
c6.c |
= |
'b' |
AND |
c7.c |
= |
'b' |
; |
|
9.Вставьте новую строку в таблицу CACHEJFV:
INSERT INTO cachejfv VALUES('c'); COMMIT;
10.Снова определите текущее содержимое кэша результатов с помощью скрипта check_result_cashe.sql.
(6) Приведите и прокомментируйте результат.
check_result_cache.sql
SELECT TYPE, status, name, object_no, row_count,row_size_avg
FROM v$result_cache_objects
ORDERBY1;
11. Снова выполните скрипт query1.sql. (7) Зафиксируйте время выполнения.
SELECT /*+ result_cache q_name(Q1) */
query1.sql
COUNT(*)
FROM cachejfv c1, cachejfv c2, cachejfv c3, cachejfv c4, cachejfv c5,
cachejfv c6, cachejfv c7
WHERE c1.c='b' AND c2.c ='b' AND c3.c ='b' AND c4.c ='b' AND c5.c ='b'AND c6.c ='b'AND c7.c ='b';
1,084ms elapsed
12. Определите текущее содержимое кэша результатов с помощью
скрипта check_result_cashe.sql. (8) Приведите и прокомментируйте результат.
check_result_cache.sql
SELECT TYPE, status, name, object_no, row_count,row_size_avg
FROM v$result_cache_objects
ORDERBY1;
13. Сгенерируйте детализированный отчёт по использованию кэша результатов и
(9) приведите результат.
SET SERVROUTPUT ON
EXEC DBMS_RESULT_CACHE.MEMORY_REPORT(detailed=>true);
14. Очистите буферный кэш:
ALTER SYSTEM FLUSH buffer_cache;
и снова выполните скрипт query1.sql.
(10) Зафиксируйте время выполнения и прокомментируйте результат.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
query1.sql |
|
|
|
|
|
|
||||
SELECT |
/*+ result_cache q_name(Q1) */ |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
||||||||||||||||||
COUNT |
(*) |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
||
FROM |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
||||
|
cachejfv c1 |
, |
cachejfv c2 |
, |
cachejfv c3 |
, |
cachejfv c4 |
, |
cachejfv c5 |
, |
|||||||||||||||||||||||
cachejfv c6 |
, |
cachejfv c7 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|||||||||||
|
|
|
= |
'b' |
|
AND |
c2.c |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|||||||||||
WHERE |
c1.c |
|
= |
'b' |
|
AND |
c3.c |
= |
'b' |
|
AND |
c4.c |
= |
'b' |
|||||||||||||||||||
AND |
|
c5.c |
= |
'b' |
|
AND |
c6.c |
= |
'b' |
AND |
c7.c |
= |
'b' |
; |
|
36ms elapsed
15.Выключите использование кэша результатов с помощью следующей команды:
EXEC DBMS_RESULT_CACHE.BYPASS(bypass_mode=>true);
16.Снова выполните скрипт query1.sql.
(11) Зафиксируйте время выполнения и прокомментируйте результат.
SELECT /*+ result_cache q_name(Q1) */
query1.sql
COUNT(*)
FROM cachejfv c1, cachejfv c2, cachejfv c3, cachejfv c4, cachejfv c5,
cachejfv c6, cachejfv c7
WHERE c1.c='b' AND c2.c ='b' AND c3.c ='b' AND c4.c ='b' AND c5.c ='b'AND c6.c ='b'AND c7.c ='b';
1,444ms elapsed
17.
a.Включите использование кэша результатов и очистите буферный кэш:
EXEC DBMS_RESULT_CACHE.BYPASS(bypass_mode=>false); ALTERSYSTEM FLUSH buffer_cache;
b.Убедитесь, что он снова используется (ещё раз выполните скрипт query1.sql и
(12) зафиксируйте время выполнения):
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
query1.sql |
|
|
|
|
|
|
||||
SELECT |
/*+ result_cache q_name(Q1) */ |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
||||||||||||||||||
COUNT |
(*) |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
||
FROM |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
||||
|
cachejfv c1 |
, |
cachejfv c2 |
, |
cachejfv c3 |
, |
cachejfv c4 |
, |
cachejfv c5 |
, |
|||||||||||||||||||||||
cachejfv c6 |
, |
cachejfv c7 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|||||||||||
|
|
|
= |
'b' |
|
AND |
c2.c |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|||||||||||
WHERE |
c1.c |
|
= |
'b' |
|
AND |
c3.c |
= |
'b' |
|
AND |
c4.c |
= |
'b' |
|||||||||||||||||||
AND |
|
c5.c |
= |
'b' |
|
AND |
c6.c |
= |
'b' |
AND |
c7.c |
= |
'b' |
; |
|
81ms elasted
задание 2
18. Выполните скриптquery2.sql.(1)Зафиксируйте время выполнения и прокомментируйте результат.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
query2.sql |
|
|
|
|
||||
SELECT |
COUNT |
(*) |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
||||||
FROM |
|
cachejfv |
|
|
c1 |
, |
cachejfv c2 |
, |
cachejfv c3 |
, |
cachejfv c4 |
, |
||||||||||||||||||
cachejfv c5 |
, |
|
cachejfv c6 |
, |
cachejfv c7 |
|
|
|
|
|
|
|
||||||||||||||||||
WHERE |
c1.c |
= |
'b' |
|
AND |
c2.c |
= |
'b' |
|
AND |
c3.c |
|
= |
'b' |
|
AND |
c4.c |
= |
'b' |
|||||||||||
AND |
c5.c |
= |
'b' |
|
AND |
c6.c |
= |
'b' |
AND |
|
c7.c |
= |
'b' |
; |
|
|||||||||||||||
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1,195 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
19. Каким образом можно заставить предыдущий запрос использовать кэшированные результаты без применения подсказок (hints)?
(2) Зафиксируйте своё решение.
|
Параметр |
|
Описание |
|
|
|
|
|
|
|
result_cache_max_size |
|
Максимальный размер кэша (например, 5M для 5 MB). Если |
|
|
|
установить в 0, кэш результатов будет полностью выключен. |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
пределяет процент от максимального размера кэша |
|
|
result_cache_max_result |
|
(result_cache_max_size), который может использоваться одним |
|
|
|
|
запросом. |
|
|
|
|
|
|
|
|
|
Если задано значение FORCE, то все запросы кэшируются, |
|
|
result_cache_mode |
|
если они умещаются в кэш. Значение по умолчанию MANUAL |
|
|
|
|
означает, что кэшируются только запросы с подсказкой. |
|
|
|
|
|
|
|
result_cache_remote_expiratio |
|
Определяет количество минут, которое результат в кэше, |
|
|
n |
|
который обращался к удаленному объекту, остается |
|
|
|
действительным. По умолчанию 0. |
|
|
|
|
|
|
|
|
|
|
|
|
alter session set RESULT_CACHE_MODE='FORCE';
a.(3)Просмотрите текущее содержимое кэша результатов и примените своё решение.
alter session set RESULT_CACHE_MODE='FORCE';
b. Проверьте результат, просмотрев план выполнения запроса из скрипта query2.sql (с помощью кнопки explain plan).
(4) Приведите и прокомментируйте план (по теме данной лабораторной).
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
query2.sql |
|
|
|
|
||||
SELECT |
COUNT |
(*) |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
||||||
FROM |
|
cachejfv |
|
|
c1 |
, |
cachejfv c2 |
, |
cachejfv c3 |
, |
cachejfv c4 |
, |
||||||||||||||||||
cachejfv c5 |
, |
|
cachejfv c6 |
, |
cachejfv c7 |
|
|
|
|
|
|
|
||||||||||||||||||
WHERE |
c1.c |
= |
'b' |
|
AND |
c2.c |
= |
'b' |
|
AND |
c3.c |
|
= |
'b' |
|
AND |
c4.c |
= |
'b' |
|||||||||||
AND |
c5.c |
= |
'b' |
|
AND |
c6.c |
= |
'b' |
AND |
|
c7.c |
= |
'b' |
; |
|
c.Очистите буферный кэш Вашего экземпляра
ALTERSYSTEM FLUSH buffer_cache;
Запустите скрипт query2.sql и убедитесь, что он выполняется практически мгновенно ((5) зафиксируйте время выполнения).
58ms
d. (6) Отмените изменения, сделанные Вами в п. a).
alter session set RESULT_CACHE_MODE='MANUAL';
20. Очистите кэш результатов:
EXEC DBMS_RESULT_CACHE.FLUSH;
Просмотрите содержимое представления V$RESULT_CACHE_OBJECTS, чтобы убедиться, что кэш пуст.
SELECT TYPE, status, name, object_no, row_count,row_size_avg
FROM v$result_cache_objects
ORDER BY 1;
21. Выполните скрипт cre_func.sql - для создания PL/SQL функции, использующей кэш результатов.
cre_func.sql
CREATE OR REPLACE FUNCTION CACHEJFV_COUNT(v VARCHAR2)
RETURN NUMBER
result_cache relies_on (cachejfv)
IS
cnt NUMBER;
BEGIN
SELECT COUNT(*) INTO cnt
FROM cachejfv c1,cachejfv c2,cachejfv c3,cachejfv c4,cachejfv c5,cachejfv c6, cachejfv c7 WHERE c1.c=v AND c2.c=v AND c3.c=v AND c4.c=v AND c5.c=v AND c6.c=v AND c7.c=v;
RETURN cnt; END;
/
дополнение
КЭШИРОВАНИЕ РЕЗУЛЬТАТОВ PL/SQL
ФУНКЦИЙ В ORACLE DATABASE 11G
SEPTEMBER 8, 2010 DBA_WP_USER LEAVE A COMMENT
В версии Oracle Database 11g появилась новая замечательная возможность кэширования результатов PL/SQL функций. Кэшировать можно как результаты обычных PL/SQL функций, так и результаты функций в PL/SQL пакетах. Замечательной особенностью нового механизма кэширования Oracle является то, что кэширование результатов функций осуществляется на уровне SGA, т.е. кэш результатов разделяется между всеми сессиями пользователей, что ведет к уменьшению использования памяти сервером базы данных. Также при объявлении PL/SQL функции можно указать, когда кэш должен стать недействительным. Это может происходить автоматически при фиксации изменений данных в некоторых таблицах, список которых можно указать при объявлении PL/SQL функции или же выполнением соответствующей команды из встроенного
пакета DBMS_RESULT_CACHE .
Эти новые возможности реализуются при помощи ключевых
слов result_cache и relies_on. Пример объявления кэширующей функции:
CREATEORREPLACE
FUNCTIONtest(pnIDINNUMBER)RETURNVARCHAR2
result_cache relies_on(TABLE_NAME1,TABLE_NAME2)
IS
BEGIN
...
ENDtest;
/
В этом примере ключевое слово result_cache заставляет Oracle кэшировать результаты функции для заданного входного параметра, а ключевое
слово relies_on позволяет перечислить список таблиц, при фиксации изменений в которых (в любой пользовательской сессии) кэш функции становится недействительным, и будет вычисляться заново при следующем обращении к этой функции.
Если кэшируемая функция объявлена в PL/SQL пакете, то ключевое
слово result_cache в спецификации пакета указывать нельзя (если это сделать, то произойдет ошибка компиляции), это возможно только при объявлении функции в теле пакета.
Чтобы использовать новые возможности кэширования сервера баз
данных 11g необходимо оценить выигрыш в скорости, предоставляемый новой технологией. Для оценки создадим тестовый PL/SQL пакет, при помощи которого будем сравнивать скорость выполнения с использованием традиционного подхода к выборке данных, с использованием result_cache, а также технологию кэширования при помощи индексных массивов, описанную нами ранее в статьях Индексные массивы в Oracle PL/SQLи PL/SQL и Java. Кто быстрее?
Для тестирования будем выполнять поиск по маске в имени объекта из системного представления ALL_OBJECTS. Код тестового пакета приведен ниже:
CREATEORREPLACE
PACKAGEtest_result_cache
IS
FUNCTIONGetCountStd(psMASKINVARCHAR2)RETURNPLS_INTEGER;
PROCEDURETestCountStd(pnCOUNTINPLS_INTEGER);
TYPEttArrISTABLEOFPLS_INTEGERINDEXBYVARCHAR2(8);
gtArr ttArr;
FUNCTIONGetCountArr(psMASKINVARCHAR2)RETURNPLS_INTEGER;
PROCEDURETestCountArr(pnCOUNTINPLS_INTEGER);
FUNCTIONGetCountCache(psMASKINVARCHAR2)RETURNPLS_INTEGERresult_cache;
PROCEDURETestCountCache(pnCOUNTINPLS_INTEGER);
ENDtest_result_cache;
/
CREATEORREPLACE
PACKAGEBODYtest_result_cache
IS
FUNCTIONGetCountStd(psMASKINVARCHAR2)RETURNPLS_INTEGER
IS
nPLS_INTEGER;
BEGIN
SELECTCOUNT(*)
INTOn
FROMALL_OBJECTS
WHEREOBJECT_NAMELIKE'%'||psMASK||'%';
RETURNn;
ENDGetCountStd;
PROCEDURETestCountStd(pnCOUNTINPLS_INTEGER)
IS
nPLS_INTEGER;
BEGIN
FORiIN1..pnCOUNTLOOP
n:=GetCountStd('IN');
n:=GetCountStd('OUT');
n:=GetCountStd('PARAM');
n:=GetCountStd('END');
n:=GetCountStd('OPT');
ENDLOOP;
ENDTestCountStd;
FUNCTIONGetCountArr(psMASKINVARCHAR2)RETURNPLS_INTEGER
IS
nPLS_INTEGER;
BEGIN
IFgtArr.EXISTS(psMASK)
THEN
RETURNgtArr(psMask);
ENDIF;
SELECTCOUNT(*)
INTOn
FROMALL_OBJECTS
WHEREOBJECT_NAMELIKE'%'||psMASK||'%';
gtArr(psMask):=n;
RETURNn;
ENDGetCountArr;
PROCEDURETestCountArr(pnCOUNTINPLS_INTEGER)
IS
nPLS_INTEGER;
BEGIN
gtArr.DELETE;
FORiIN1..pnCOUNTLOOP
n:=GetCountArr('IN');
n:=GetCountArr('OUT');
n:=GetCountArr('PARAM');
n:=GetCountArr('END');
n:=GetCountArr('OPT');
ENDLOOP;
ENDTestCountArr;
FUNCTIONGetCountCache(psMASKINVARCHAR2)RETURNPLS_INTEGERresult_cache
IS
nPLS_INTEGER;
BEGIN
SELECTCOUNT(*)
INTOn
FROMALL_OBJECTS
WHEREOBJECT_NAMELIKE'%'||psMASK||'%';
RETURNn;
ENDGetCountCache;
PROCEDURETestCountCache(pnCOUNTINPLS_INTEGER)
IS
nPLS_INTEGER;
BEGIN
DBMS_RESULT_CACHE.INVALIDATE(USER,'TEST_RESULT_CACHE');
FORiIN1..pnCOUNTLOOP
n:=GetCountCache('IN');
n:=GetCountCache('OUT');
n:=GetCountCache('PARAM');
n:=GetCountCache('END');
n:=GetCountCache('OPT');
ENDLOOP;
ENDTestCountCache;
ENDtest_result_cache;
/
Перед компиляцией тестового пакета необходимо дать разрешение владельцу схемы на выполнение встроенного PL/SQL пакета DBMS_RESULT_CACHE:
GRANTEXECUTEONSYS.DBMS_RESULT_CACHETOSCHEMA_OWNER;
Для выполнения тестов запускаем sql*plus, выполнив предварительно команду set timing on;
Каждая процедура тестирования имеет параметр количества повторов в цикле групп поисков по ALL_OBJECTS. Для получения разумного времени выполнения примем это значение в 50 итераций. Результаты тестирования:
Традиционный подход:
EXECtest_result_cache.TestCountStd(50);
Elapsed: 00:00:25.23
Использование индексных массивов:
EXECtest_result_cache.TestCountArr(50);
Elapsed: 00:00:00.50
Использование result_cache:
EXECtest_result_cache.TestCountCache(50);
Elapsed: 00:00:00.51
Как видно, обе технологии кэширования обеспечили выигрыш в скорости около 30 раз. Однако применение индексных массивов использует пользовательскую память для каждой сессии, а технология result_cache использует SGA, единую память для всех сессий пользователей. Сброс кэша в обоих случаях в нашем примере необходимо производится вручную, однако для технологии с result_cache можно указать список таблиц, изменения в которых приведет к автоматическому сбросу кэша. Скорость кэширования в этих тестах оказалась примерно одинаковой. Но все таки попробуем выяснить, какая технология кэширования быстрее. Для этого увеличим на несколько порядков количество итераций:
Использование индексных массивов:
EXECtest_result_cache.TestCountArr(500000);
Elapsed: 00:00:02.32
Использование result_cache:
EXECtest_result_cache.TestCountCache(500000);
Elapsed: 00:00:03.25
Как видно, все же технология индексных массивов выигрывает примерно на 40 процентов. И это при том, что индексом в массиве в нашем случае
является varchar2. В тех случаях, если можно будет использовать в качестве индекса pls_integer, выигрыш в скорости будет еще более значительным. Как показали наши тесты, полностью технологию кэширования с применением
индексных массивов кэширование result_cache вытеснить не сможет. Использование индексных массивов может быть предпочтительнее в тех случаях, где критично время выполнения расчетных задач. Однако новая технология кэширования несомненно получит широкое применение. Множество функций в уже существующих приложениях можно перевести на технологию result_cache, гарантированно получив значительный выигрыш в производительности. Например, во многих приложениях есть функции получения записи по идентификатору. Теперь такие функции могут быть быстро и эффективно переписаны по новому, например, для таблицы с именем TABLE1:
SUBTYPEtrRCRDISTABLE1%ROWTYPE;
...
FUNCTIONGET_RCRD(pnIDINNUMBER)RETURNtrRCRD result_cache relies_on(TABLE1)
IS
lrRCRD trRCRD;
BEGIN
SELECT*
INTOlrRCRD
FROMTABLE_NAME
WHEREID=pnID;
RETURNlrRCRD;
ENDGET_RCRD;
Новая технология кэширования может быть использована и в SQL запросах в вашем PL/SQL коде при помощи нового хинта (подсказки оптимизатору), например:
PROCEDUREA1
IS
nPLS_INTEGER;
BEGIN
...
SELECT/*+ result_cache */COUNT(*)
INTOn
FROMTABLE1;
...
ENDA1;
Вэтом случае система автоматически будет отслеживать возможные изменения таблиц в запросе и перезагружать кэш.
Внашем тестовом примере был использован встроенный
пакет DBMS_RESULT_CACHE, который позволяет принудительно сбрасывать кэш (делать его недействительным) и выполнять некоторые другие функции по управлению кэшем. Для целей разработки наиболее востребованными могут быть следующие функции этого пакета:
–DBMS_RESULT_CACHE.FLUSH – общий сброс всего кэша экземпляра базы данных.
–DBMS_RESULT_CACHE.INVALIDATE – принудительный сброс кэша для заданной
функции или PL/SQL пакета. В качестве первого параметра здесь передается имя владельца схемы, в качестве второго имя функции, процедуры или пакета. К сожалению, нет возможности указать конкретную функцию в заданном пакете, сброс кэша происходит целиком для всех функций PL/SQL пакета.
Более подробно о пакете DBMS_RESULT_CACHEможно прочитать в официальной документации.
Для просмотра текущего состояния кэша могут быть полезны следующие динамические представления:
V$RESULT_CACHE_MEMORY
V$RESULT_CACHE_OBJECTS
V$RESULT_CACHE_DEPENDENCY
Размер кэша в SGA задается с помощью параметра экземпляра базы данных RESULT_CACHE_SIZE
22. Определите текущее содержимое кэша результатов с помощью скрипта check_result_cashe.sql.
(7) Прокомментируйте результат
SELECT TYPE, status, name, object_no, row_count,row_size_avg
FROM v$result_cache_objects
ORDERBY1;
23. Вызовите созданную в п.21 функцию, передав в качестве значения параметра 'b'.
(8) Зафиксируйте время выполнения и прокомментируйте результат.
24. Очистите буферный кэш:
ALTERSYSTEM FLUSH buffer_cache;
и снова вызовите функцию CACHEJFV_COUNT, передав в качестве значения параметра 'b'.
(9) Зафиксируйте время выполнения и прокомментируйте результат.
25. Ещё раз очистите буферный кэш:
ALTERSYSTEM FLUSH buffer_cache;
и вызовите функцию CACHEJFV_COUNT, теперь передав в качестве значения параметра 'c'. (10) Зафиксируйте время выполнения и прокомментируйте результат.
Лабораторная 9 9.1
Вопрос1
Пока нет ответа Балл: 1
Отметить вопрос
Текст вопроса
1. Откройте окно терминала и запустите скриптsysstats_setup.sh(под пользователем oracle) - для создания и наполнения схемы JFV и сбора объектной статистики.
sysstats_setup.sh
#!/bin/bash
cd /home/oracle/labs/System_Stats sqlplus /as sysdba @sysstats_setup.sql
SET echo ON
CONNECT/AS sysdba;
DROPUSER jfv CASCADE;
CREATEUSER jfv IDENTIFIEDBY jfv DEFAULTTABLESPACE users TEMPORARYTABLESPACE temp; GRANTCONNECT,RESOURCE, dba TO jfv;
CONNECT jfv/jfv
DROPTABLE t purge;
DROPTABLE z purge;
CREATETABLE t(c NUMBER);
INSERTINTO t VALUES(1);
COMMIT;
INSERTINTO t SELECT*FROM t;
COMMIT;
INSERTINTO t SELECT*FROM t;
COMMIT;
CREATETABLE z(d NUMBER);
BEGIN
FOR i IN 1..100 LOOP
INSERT INTO z VALUES (i);
END LOOP;
COMMIT;
END;
/
CREATEUNIQUEINDEX iz ON z(d);
EXECUTE dbms_stats.gather_table_stats('JFV','T',CASCADE=>true);
EXECUTE dbms_stats.gather_table_stats('JFV','Z',CASCADE=>true);
EXIT;
2. Выполните скриптsysstats_start.shдля очистки кэшей и установки параметра CPUSPEEDNW=0 (для проверки обратите внимание на значение параметра CPUSPEEDNW в представлении aux_stats$,
данные из которого выводятся в конце выполнения скрипта).(1)Поясните что означает установленное значение для данного параметра.
sysstats_start.sh
#!/bin/bash
cd /home/oracle/labs/System_Stats sqlplus /nolog @sysstats_start.sql
sysstats_start.sql
CONNECT/AS sysdba;
ALTERSYSTEM flush shared_pool;
ALTERSYSTEM flush buffer_cache;
EXECUTE dbms_stats.delete_system_stats;
EXECUTE DBMS_STATS.SET_SYSTEM_STATS (pname =>'cpuspeednw', pvalue =>0);
SELECT sname,pname,pval1 FROM aux_stats$;
EXIT;
Вопрос2
Пока нет ответа Балл: 1
Отметить вопрос
Текст вопроса
3. Подключитесь к SQL*Plus как пользователь JFV и выполните скрипт select_without_sysstats.sql. (1) Зафиксируйте время его выполнения.
select_without_sysstats.sql
SET echo ON
SETTIMINGON
SELECT /* Without system stats */ COUNT(*)
FROM t,z
WHERE t.c=z.d;
SETTIMING off
4. Запустите скрипт show_latest_exec_plan.sql для просмотра плана выполнения запроса из п.3 и
определения стоимости запроса, рассчитанной оптимизатором, а также стоимости использования CPU и стоимости операций ввода-вывода при последнем выполнении запроса. (2) Зафиксируйте и прокомментируйте результат (обратите внимание на примечания к плану).
show_latest_exec_plan.sql
SET echo ON
SELECT*FROMTABLE(dbms_xplan.display_cursor);
col operations format a20 col object_name format a11 col options format a15 col cost_cpu_io format a30
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
SELECT |
operation operations |
, |
object_name |
, |
options |
, |
||||||||||||||||||||
COST |
|| |
' -- ' |
|| |
cpu_cost |
|| |
' -- ' |
|| |
io_cost cost_cpu_io |
|
|
|||||||||||||||||
FROM |
|
( |
SELECT |
* |
|
FROM |
v$ |
sql_plan |
WHERE |
address |
IN |
( |
SELECT |
address |
|||||||||||||
FROM |
|
v |
$sql |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
||
WHERE |
|
|
sql_ |
|
|
|
|
|
|
|
|||||||||||||||||
|
|
text |
LIKE |
'%system stats%' |
AND |
||||||||||||||||||||||
sql_ |
text |
NOT |
LIKE |
'%connect%' |
)) |
; |
|
|
|
|
|
|
|
|
|
|
5. Каким образом можно помочь оптимизатору найти более оптимальный план в следующий раз?
(3) Зафиксируйте и примените своё решение собрать системную статистику. Из нее будет понятно какой метод соединения применить. Например,
если недопустимо нагружать процессор из за большого количества открытых сессий, то hash_join может быть менее предпочтителен , а если идет большая нагрузка на I/o , то nested_loop окажется не оптимальным решением. В связи с тем, что оптимизатор учитывает нагрузку системы, то планы запросов будут отличаться , если отличается системная статистика.
Режимы
GATHERING_MODE = NOWORKLOAD вначале, когда нет нагрузки
EXECUTE DBMS_STATS.GATHER_SYSTEM_STATS( GAVERING_MODE => 'NOWORKLOAD')
запускается внутренний тест и на его основе собирается информация
DBMS_STATS.GATHER_SYSTEM_STATS( INTERVAL => 120 , STATTAB => 'TABLE_FOR_STATS', STATID => 'oltp' )
EXECUTE DBMS_STATS.GATHER_SYSTEM_STATS( GAVERING_MODE => 'START') EXECUTE DBMS_STATS.GATHER_SYSTEM_STATS( GAVERING_MODE => 'STOP')
6.Выполните скрипт show_ss.sql и
(4) прокомментируйте результат.
|
|
|
|
|
|
|
|
|
|
|
show_ss.sql |
|
SET |
echo |
ON |
|
|
|
|
|
|
|
|
|
|
SELECT |
sname |
, |
pname |
, |
pval1 |
FROM |
aux_stats$; |
|
7. Перед проверкой влияния внесённых изменений очистите разделяемый пул и буферный кэш с помощью скрипта flush_sga.sql.
flush_sga.sql
SET echo ON
ALTER SYSTEM flush shared_pool;
ALTERSYSTEM flush buffer_cache;
8.Проверьте своё решение, выполнив скрипт select_with_sysstats.sql.
(5) Прокомментируйте результат.
select_with_sysstats.sql
SETTIMINGON
SELECT /* With system stats */ COUNT(*)
FROM t,z
WHERE t.c=z.d;
SETTIMING off
9. Очистите окружение с помощью скрипта sysstats_cleanup.sh.
sysstats_cleanup.sh
#!/bin/bash
cd /home/oracle/labs/System_Stats
sqlplus /as sysdba @sysstats_cleanup.sql
sysstats_cleanup.sql
SET echo ON
DROPUSER jfv CASCADE;
ALTERSYSTEM flush shared_pool;
EXIT;
9.2
1. Откройте окно терминала и запустите скриптags_setup.sh(под пользователем oracle) - для создания схемы AGS, таблицы EMP и индекса для неё.
ags_setup.sh
#!/bin/bash
cd /home/oracle/labs/Automatic_Gather_Stats sqlplus /as sysdba @ags_setup.sql
ags_setup.sql
SET echo ON
DROPUSER ags CASCADE;
CREATEUSER ags IDENTIFIEDBY ags;
grant dba TO ags;
connect ags/ags
DROPTABLE emp purge;
CREATE TABLE emp
(
empno NUMBER, ename VARCHAR2(20), phone VARCHAR2(20), deptno NUMBER
);
INSERT INTO emp with tdata AS (select rownum empno from all_objects where rownum<= 1000) select rownum,
dbms_random.string ('u', 20),
dbms_random.string ('u', 20),
CASE
when rownum/100000 <= 0.001 THEN MOD(ROWNUM, 10)
ELSE 10
END
FROM tdata a, tdata b
WHERE rownum<=100000;
COMMIT;
CREATEINDEX emp_i1 ON emp(deptno);
EXIT;
2. Выполните скрипт ags_start.sh.
ags_start.sh
#!/bin/sh
sqlplus /nolog @ags_start.sql
ags_start.sql
SET echo ON
CONNECT/AS sysdba
ALTERSYSTEM flush shared_pool;
--
-- Turn off AUTOTASK
--
ALTERSYSTEMSET"_enable_automatic_maintenance"=0;
exec dbms_stats.delete_schema_stats('AGS');
EXIT;
3. В SQL-Developer создайте соединение для пользователя AGSсо следующими параметрами: Connection Name: ags_connection
Username: ags Password: ags
SID: orcl
Далее используйте это соединение, пока не будет сказано иначе.
4.С помощью скриптаshow_deptno_distribution.sqlпосмотрите распределение значений в столбце deptno таблицы EMP.
5.(1)Прокомментируйте результат.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
show_deptno_distribution.sql |
|
||||||||
SELECT |
deptno |
, |
COUNT |
(*) |
cnt_per |
|
_deptno |
, |
( |
COUNT |
(*)* |
100 |
)/ |
nr |
deptno_percent |
||||||||||||
FROM |
|
emp |
, |
( |
SELECT |
MAX |
( |
empno |
) |
nr |
|
||||||||||||||||
FROM |
|
emp |
) |
|
|
|
|
|
|
|
|
|
|
||||||||||||||
GROUP |
|
|
|
|
|
|
|||||||||||||||||||||
|
|
BY |
|
deptno |
, |
nr |
|||||||||||||||||||||
ORDER |
|
BY |
|
deptno; |
|
|
|
5. (2) Определите, созданы ли гистограммы
для какого-либо из столбцов таблицы EMP (используйте представление user_tab_columns).
6. (3) Определите, собрана ли статистика по таблице EMP:
a. В браузере соединения ags_connection выберите таблицу EMP. b. В открывшемся справа окне выберите вкладку Statictics. Обновите (F5) информацию при необходимости.
7.Аналогичным образом
(4) определите, собрана ли статистика по индексу таблицы EMP
(сначала необходимо узнать его имя - на вкладке Indexes для таблицы Emp, затем открыть соответствующий индекс из браузера соединения). Обратите внимание на значение параметра LAST_ANALYZED.
8. Выполните трассировку (autotrace) запросов из скриптов literal9.sql и literal10.sql.
(5) Зафиксируйте и прокомментируйте результат (предположите, почему были выбраны правильные методы доступа).
literal9.sql
SELECTCOUNT(*),MAX(empno)FROM emp WHERE deptno =9;
literal10.sql
SELECTCOUNT(*),MAX(empno)FROM emp WHERE deptno =10;
9. (6) Проверьте своё предположение,
просмотрев содержимое столбцов name и value в представлении v$parameter (для соответствующего параметра инициализации).