По материалам Тома Кайта
Если не указывать параметр method_opt, то Oracle соберет гистограммы в режиме auto. Количество баскетов в гистограмме в режиме auto определяется по использованию колонок в запросах в таблице SYS.COL_USAGE$ и распределению данных.
Данная таблица заполняется SMON (если установлен параметр _column_traking_level).
auto: сбора гистограмм также собирается указанием параметра method_opt => 'for all indexed columns size auto'
SIZE 1: при указании параметра method_opt=>'for all columns size 1' в гистограммы попадет бакет с наименьшим и наибольшим значением и общим количеством строк.
Для запрещения сбора гистограмм вообще, необходимо собирать статистику по таблице с параметром method_opt=>'for columns '
gather_stale - собирает гистограммы по таблицам, для которых данные бурно изменялись. Изменения определяются по вьюхам *_tab_modifications. Вьюхи автоматически заполняются при значении параметра STATISTICS_LEVEL = Typical или All.
2008-04-25
2008-04-23
Bind peeking и гистограммы тестирование
Тесты скриптом
Дали следующие результаты:
БЕЗ УКАЗАНИЯ ГИСТОГРАММ (size=auto)
1. Bind peeking во время hard parse: +
2. План первого запроса: индексный (неправильно)
3. Ожидаемая кардинальность 334 строки
4. Bind Peeking второго запроса: - (взял разобранный курсор)
ГИСТОГРАММЫ 254
1. Bind peeking во время hard parse: +
2. План первого запроса: полный (правильно)
3. Ожидаемая кардинальность 1000 строк
4. Bind Peeking второго запроса: - (взял разобранный курсор)
ГИСТОГРАММЫ repeat
(в документации не читал, но Кайт считает, что это без статистики )
1. Bind peeking во время hard parse: + (_|_)
2. План первого запроса: индексный (неправильно)
3. Ожидаемая кардинальность 334 строки
4. Bind Peeking второго запроса: -
Выводы:
1. Bind Peeking работает вне зависимости от наличия гистограмм
2. Bind Peeking работает только при Hard Parse. Заставить работать его просто так мы не можем.
3. Гистограммы помогли (при этом стоит учитывать, что количество уникальных значений меньше, чем количество бакетов)
DROP TABLE a;
CREATE TABLE a(a NUMBER, b CHAR);
CREATE INDEX ix_a ON a(a);
INSERT INTO a SELECT 3, 'x' FROM all_objects WHERE ROWNUM <= 1;
INSERT INTO a SELECT 2, 'x' FROM all_objects WHERE ROWNUM <= 1;
INSERT INTO a SELECT 1, 'x' FROM all_objects WHERE ROWNUM <= 1000;
--EXEC dbms_stats.gather_table_stats('sps', 'a', CASCADE => TRUE)
EXEC dbms_stats.gather_table_stats('sps', 'a', method_opt => 'FOR ALL INDEXED COLUMNS SIZE repeat', CASCADE => TRUE)
--EXEC dbms_stats.gather_table_stats('sps', 'a', method_opt => 'FOR ALL INDEXED COLUMNS SIZE 254', CASCADE => TRUE)
COMMIT;
var sa NUMBER
var ea NUMBER
EXEC :sa := 0;
EXEC :ea := 1;
ALTER SESSION SET tracefile_identifier = 'size_repeat';
ALTER SESSION SET EVENTS '10053 trace name context forever, level 1';
ALTER SESSION SET EVENTS '10046 trace name context forever, level 12';
SELECT * FROM a WHERE a BETWEEN :sa AND :ea;
EXEC :sa := 2;
EXEC :ea := 3;
SELECT * FROM a WHERE a BETWEEN :sa AND :ea;
DISCONNECT;
Дали следующие результаты:
БЕЗ УКАЗАНИЯ ГИСТОГРАММ (size=auto)
1. Bind peeking во время hard parse: +
2. План первого запроса: индексный (неправильно)
3. Ожидаемая кардинальность 334 строки
4. Bind Peeking второго запроса: - (взял разобранный курсор)
ГИСТОГРАММЫ 254
1. Bind peeking во время hard parse: +
2. План первого запроса: полный (правильно)
3. Ожидаемая кардинальность 1000 строк
4. Bind Peeking второго запроса: - (взял разобранный курсор)
ГИСТОГРАММЫ repeat
(в документации не читал, но Кайт считает, что это без статистики )
1. Bind peeking во время hard parse: + (_|_)
2. План первого запроса: индексный (неправильно)
3. Ожидаемая кардинальность 334 строки
4. Bind Peeking второго запроса: -
Выводы:
1. Bind Peeking работает вне зависимости от наличия гистограмм
2. Bind Peeking работает только при Hard Parse. Заставить работать его просто так мы не можем.
3. Гистограммы помогли (при этом стоит учитывать, что количество уникальных значений меньше, чем количество бакетов)
2008-04-21
bind peeking и гистограммы
Oracle обещает
По трейсу 10053 имеем только одно вхождение строки
и имеем следующие планы выполнения:
Это показывает, что для значения переменной :a=2 никакого дополнительного считывания переменной не было и в помине.
Bind Peeking бывает только при hard parse, судя по всему не зависимо от наличия гистограмм
Для отключения bind peeking можно воспользоваться скрытым параметром
There are two cases where the optimizer would peek at the actual bindings of a bind variable and where the actual bindings therefore could make a difference for what plan would get generated.Проверка показывает:
Range predicates. Example:
sales_date between :1 and :2 and price > :3.
Equality predicates when the column has histograms. Example:
order_status = :4
assuming that order_status has histograms.
CREATE TABLE a(a NUMBER, b CHAR);
CREATE INDEX ix_a ON a(a);
INSERT INTO a SELECT 2, 'x' FROM all_objects WHERE ROWNUM <= 1;
INSERT INTO a SELECT 1, 'x' FROM all_objects WHERE ROWNUM <= 1000;
BEGIN
dbms_stats.gather_table_stats(
'sps',
'a',
CASCADE => TRUE,
method_opt => 'for all indexed columns size 50');
END;
/
COMMIT;
var a NUMBER
EXEC :a := 1;
ALTER SESSION SET tracefile_identifier = 'hist_test';
ALTER SESSION SET EVENTS '10053 trace name context forever, level 1';
ALTER SESSION SET EVENTS '10046 trace name context forever, level 12';
SELECT * FROM a WHERE a = :a;
EXEC :a := 2;
SELECT * FROM a WHERE a = :a;
DISCONNECT;
По трейсу 10053 имеем только одно вхождение строки
*******************************************
Peeked values of the binds in SQL statement
*******************************************
и имеем следующие планы выполнения:
SELECT *
FROM
a WHERE a = :a
call count cpu elapsed disk query current rows
------- ------ -------- ---------- ---------- ---------- ---------- ----------
Parse 1 0.00 0.00 0 0 0 0
Execute 1 0.34 0.38 0 0 0 0
Fetch 11 0.00 0.00 0 16 0 1000
------- ------ -------- ---------- ---------- ---------- ---------- ----------
total 13 0.34 0.38 0 16 0 1000
Misses in library cache during parse: 1
Optimizer mode: ALL_ROWS
Parsing user id: 781
Rows Row Source Operation
------- ---------------------------------------------------
1000 TABLE ACCESS FULL A (cr=16 pr=0 pw=0 time=1054 us)
SELECT *
FROM
a WHERE a = :a
call count cpu elapsed disk query current rows
------- ------ -------- ---------- ---------- ---------- ---------- ----------
Parse 1 0.00 0.00 0 0 0 0
Execute 1 0.00 0.00 0 0 0 0
Fetch 1 0.00 0.00 0 7 0 1
------- ------ -------- ---------- ---------- ---------- ---------- ----------
total 3 0.00 0.00 0 7 0 1
Misses in library cache during parse: 0
Optimizer mode: ALL_ROWS
Parsing user id: 781
Rows Row Source Operation
------- ---------------------------------------------------
1 TABLE ACCESS FULL A (cr=7 pr=0 pw=0 time=128 us)
Результаты получаемы через explain plan:
SQL> SELECT * FROM a WHERE a = 2;
Execution Plan
----------------------------------------------------------
-------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)|
-------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 1 | 5 | 2 (0)|
| 1 | TABLE ACCESS BY INDEX ROWID| A | 1 | 5 | 2 (0)|
| 2 | INDEX RANGE SCAN | IX_A | 1 | | 1 (0)|
-------------------------------------------------------------------------
Это показывает, что для значения переменной :a=2 никакого дополнительного считывания переменной не было и в помине.
Bind Peeking бывает только при hard parse, судя по всему не зависимо от наличия гистограмм
Для отключения bind peeking можно воспользоваться скрытым параметром
ALTER SESSION SET "_optim_peek_user_binds"=FALSE;
Разница планов tkprof и set autotrace
По мотивам блога Тома Кайта
По сути дела set autotrace не что иное, как встроенный в SQL*Plus Explain Plan For со всеми вытекающими отсюда последствиями.
Помимо набившей оскомину: "...ваша статистика могла поменяться между реальным выполнением и explain'ом" существуют следующие особенности Explain Plan:
1. Explain Plan делает hard parse, который потом никогда ничем не используется
2. Explain Plan ничего не умеет делать с Bind-переменными, ничего не знает про bind peeking. Все предположения делаются судя по всему из селективности, посчитанной по num distincts
3. Explain plan считает, что все bind переменные имеют строковое значение, поэтому может показывать неправильный план, ввиду отсутствия неявного преобразования типов.
TKPROF при первом выполнении запроса ВСЕГДА делает hard parse, после чего использует сгенерированный план.
По сути дела set autotrace не что иное, как встроенный в SQL*Plus Explain Plan For со всеми вытекающими отсюда последствиями.
Помимо набившей оскомину: "...ваша статистика могла поменяться между реальным выполнением и explain'ом" существуют следующие особенности Explain Plan:
1. Explain Plan делает hard parse, который потом никогда ничем не используется
2. Explain Plan ничего не умеет делать с Bind-переменными, ничего не знает про bind peeking. Все предположения делаются судя по всему из селективности, посчитанной по num distincts
3. Explain plan считает, что все bind переменные имеют строковое значение, поэтому может показывать неправильный план, ввиду отсутствия неявного преобразования типов.
TKPROF при первом выполнении запроса ВСЕГДА делает hard parse, после чего использует сгенерированный план.
2008-04-03
TKPROF
1. Row Source Operation
Показывает, сколько строк ВЫШЛО из этой операции за ОДНО выполнение запроса. Подробнее
2. Настройка aggregate=YES собирает все выполненные запросы в одну кучку и агрегирует их результаты
3. Для определения размера коллекции для выборки (array fetch size) нужно поделить количество выбранных строк на количество fetch. Если количество fetch превышает количество строк, то происходит что-то подобное:
open
execute
fetch
fetch
fetch (а строчек уже и нету)
4. БАГ ДОКУМЕНТАЦИИ Табличка, начиная с 9.2. НЕ ВКЛЮЧАЕТ в себя все операции (+ рекурсивные SQL, например в триггерах). Но в документации написано:
5. CR, R, W в файлах и плане показывает число логических чтений на фазе выполнения и fetch данных. Не затрагивает фазу парсинга. Вывод этих чисел включается через
Показывает, сколько строк ВЫШЛО из этой операции за ОДНО выполнение запроса. Подробнее
2. Настройка aggregate=YES собирает все выполненные запросы в одну кучку и агрегирует их результаты
3. Для определения размера коллекции для выборки (array fetch size) нужно поделить количество выбранных строк на количество fetch. Если количество fetch превышает количество строк, то происходит что-то подобное:
open
execute
fetch
fetch
fetch (а строчек уже и нету)
4. БАГ ДОКУМЕНТАЦИИ Табличка, начиная с 9.2. НЕ ВКЛЮЧАЕТ в себя все операции (+ рекурсивные SQL, например в триггерах). Но в документации написано:
In ch 10 of the Oracle 9i Performance Tuning Guide, it says:Пример
"The resources reported for a statement include those for all of the SQL issued while the statement
was being processed. Therefore, they include any resources used within a trigger, along with the
resources used by any other recursive SQL (such as that used in space allocation). With the SQL
Trace facility enabled, TKPROF reports these resources twice. Avoid trying to tune the DML
statement if the resource is actually being consumed at a lower level of recursion."
5. CR, R, W в файлах и плане показывает число логических чтений на фазе выполнения и fetch данных. Не затрагивает фазу парсинга. Вывод этих чисел включается через
ALTER SYSTEM SET statistics_level=all
(хотя это надо еще проверить)
Подписаться на:
Сообщения (Atom)