вторник, 5 января 2016 г.

Oracle: разные заметки

Небольшая рубрика с заметками по Oracle за конец 2015 года, каждой из которых в отдельности недостаточно для полной статьи.

Row SCN
https://docs.oracle.com/cd/B19306_01/server.102/b14200/pseudocolumns007.htm
Интересный способ выявление изменений в ичтонике без применения триггеров/cdc/golden gate.
При включеном flash back recovery у каждой строки таблицы сохраняется номер SCN, который обновляется при update/insert.
Сохраняя его можно вытащить из истоничка изменения за определенный пеиод.
Минусы:
* SCN сохраняется для блока, т.е. если в блок помещается более 1 строки, то в выборку попадут лишние данные.
* не выявить удаленные строки

Смещение high water mark
/*+append*/ - увеличивает HWM на размер вставки (даже если свободное место есть)
delete не смещает HWM Обратно вниз, что может существенно увеличить время чтения даже небольшой таблицы с диска.
Смещаем обратно:
* ALTER TABLE имя_таблицы SHRINK SPACE [COMPACT] [CASCADE];
должно быть включено ENABLE ROW MOVE на таблице, т.к. данные переносятся физически
* truncate table

Возможные pragma в pl-sql
* автономная транзакция: PRAGMA AUTONOMOUS_TRANSACTION
* инициализация exception: PRAGMA EXCEPTION_INIT
* сброс переменных сессии на поумолчанию: PRAGMA SERIALLY_REUSABLE
* inline вызов функции: PRAGMA INLINE
* уровни строгости функции: RESTRICT_REFERENCES

Последний пункт позволяет решить проблему: при добавлении функции в запрос, он перестает паралелиться
Запрос с функцией может параллелиться, если уровень строгости функции установлен в константный:
http://docs.oracle.com/cd/B28359_01/appdev.111/b28370/restrictreferences_pragma.htm
RESTRICT_REFERENCES
* RNDS - не читает бд
* WNDS - не пишет в бд
* RNPS - не читает переменные пакета

Рандомный доступ к данным
* получить 0,01% рандомных записей из таблицы:
SELECT * FROM src_ship sample (0.01)
* приблизительный count
SELECT COUNT(*) * 1000 FROM sometable SAMPLE (0.1);

_optimizer_max_permutations - максимальное количество перестановок для оптимального плана
При большом числе таблиц в join проявляется важнос правильно выставления последовательности их в запросе, т.к. уже при 15 таблицах требуется перебрать 1 трлн возможных перестановок таблиц (15!). Что в реальности никогда не будет достигнуто, т.к. 80000 - максимальное значение (9 таблиц)
Так что на первый план выходит:
* Сохранение оптимальных планов.
* Машинное обучение, замен полного перебора
* Ручно хинтование и правильно выстраивание таблиц в запросах

attribute clustering и zone map (Oracle 12)
* attribute clustering - когда связанные данные лежат рядом на диске (какие данные должны лежать рядом указывается при создании таблицы, также правила могут устанавливать связанные таблицы)
* zone map - аналог index, но он не построчный, а по группе строк. Самостоятельное описание распределения данных в cell для exadata.

Oracle in-memory
* колоночное хранение таблиц, как следствие быстрый доступ к части столбцов при ful table scan.
* различия в степенях сжатия (for dml - частый доступ /query low - обычный доступ, capacity high - редкий доступ)
* отдельную партицию можно сделать inmemory
* разница в скорости вставки в колоночную таблицу и в обычную (при условии отсутствия индексов)
* преимущество только в скорости чтения с диска (и фильтра), т.е. join/агрегация/сортировка и т.д. будет работать также

insert all
работает медленней, чем последовательные insert, т.к. данные вставляются построчно, а не все сразу (executions в статистике)

Партиционирование без Oracle Enterprise
http://docs.oracle.com/cd/A57673_01/DOC/server/doc/A48506/partview.htm
партиционированные вью: union all + таблицы с непересекающимися частями, на которых есть check constraint

развернутый sql (oracle 12)
Полуичть результирующий преобразованный sql запрос без обработки событий:
dbms_sql2.expand_sql_text(m_sql_in, m_sql_out);

keep pool: таблица всегда будет в кэше
alter table etl_abonent storage (BUFFER_POOL KEEP);
alter table etl_abonent cache;

PIPE-line функции
https://oracle-base.com/articles/misc/pipelined-table-functions
Функция возвращающая табличные данные, преимещуства перед обычным курсором:
* данные возвращаются по мере выборки построчно, что снижает потребление pga и не надо ждать полного выполнения
(мало значимо, если нужна сортировка над результирующим запросом)
* можно параллерить внутри другого запроса, в отличии от курсоров (надо указывать при создании функции по какому столбцу можно параллелить)
* можно задавать кардинальность, иначе поумолчанию = 0 (у курсоров только хинтом)

over RANGE fn(t_timekey) PRECEDING
размер окна можно задавать функцией, а не тольк строго числом в скрипте

partition join outer
* нужен для вытаскивания фактов по 2 несвязанным измерениям, включая все данные этих 2 измерений
 ** сначала делается left join 1го измереняи с фактом, потом parition join и right join второго измерения

типы блокировок
https://jonathanlewis.wordpress.com/2010/06/21/locks/
DML блокировки:
* Row share - строка заблоклирована для DML (+ select for update), но таблицу и строку можно читать
* Row exclusive - строка заблоклирована для DML (+ select for update), но таблицу , кроме этой строки, можно читать
* Share lock - полная блокировка таблицы на DML, но можно select (чаще всего FK без индекса или перестройка BM index)
* Share lock exclusive - можно читать таблицу, но не разрешен никакой DML (удаление cascade по FK)
* Exclusive - полная блокировка: index, insert append
DDL блокировки:
* полная блокировка таблицы
* разделяемая, при создании процедур/вью на основе таблицы

Виды изоляций в oracle
* read commited - есть фантомные чтения,
* serializble - последовательный доступ,
* read only - тоже самое, что serializble, но без прав записи