21 декабря 2011 г.

oracle: Выполнить запрос в pl/sql коде

Выполнить запрос в pl/sql коде:

DECLARE
     pc_id           number := 1;
BEGIN
          DBMS_OUTPUT.PUT_LINE('pc_id: '||pc_id);
          insert into GUPPI.DEPT(DEPTNO,DNAME,LOC) values (pc_id, 'TEST', 'TEST_LOC');
          commit;

              EXCEPTION
              WHEN OTHERS THEN
              pc_id:= 0;
              DBMS_OUTPUT.PUT_LINE('Error pc_id: '||pc_id);
           
END;
/

20 декабря 2011 г.

oracle: Мониторинг отката транзакции

Если по какой то причине сделали rollback транзакции, то интересно как долго он будет выполнятся. Оценить это можно сделав запросы к v$transaction.

В этом представлении есть два поля USED_UREC и USED_UBLK.
USED_UREC - Number of undo records used
USED_UBLK - Number of undo blocks used

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

Запросы для мониторинга:

select * from v$transaction;

-- конкрето поля USED_UREC и USED_UBLK
SELECT a.sid, a.username, b.xidusn, b.used_urec, b.used_ublk
  FROM v$session a, v$transaction b
  WHERE a.saddr = b.ses_addr;

16 ноября 2011 г.

CPU Info

Platform Command(s)
AIX lparstat -i
FreeBSD sysctl hw.model
HP/UX ioscan -fnC processor
Linux cat /proc/cpuinfo
Mac OS X system_profiler SPHardwareDataType
SCO OpenServer 5 hw
uname -X
SCO Unixware 7 psrinfo -v
Solaris SPARC kstat > /tmp/kstat.output
Solaris x86 uname -X
Tru64 psrinfo -v

31 октября 2011 г.

blogger: гаджет "Поиск" аналогичный поиску в навигационной панели

Поиск по блогу организуется путем добавления гаджета HTML/JavaScript. На странице настроек гаджета название меняем, например, на «Поиск в блоге», а в поле «Содержание» пишем:


<nobr><form id="searchthis" method="get" action="/search" style="display:inline;"><input id="search-box" name="q" type="text" size="20"/> <input id="search-btn" type="submit" value="Поиск"/></form></nobr> 
 

Получается функция поиска, полностью аналогичная той, что была в навигационной панели.

18 октября 2011 г.

vmstat

1. vmstat в реальном времени

(число идущее после vmstat означает сколько раз вывести информацию)
# vmstat 1

System configuration: lcpu=2 mem=3920MB

kthr    memory                page              faults          cpu
-----  -----------    ------------------------ ------------  -----------
r  b    avm   fre    re  pi  po  fr   sr  cy  in   sy  cs   us sy id wa
0  0  229367 332745   0   0   0   0    0   0   3  198  69    0  0 99  0
0  0  229367 332745   0   0   0   0    0   0   3   33  66    0  0 99  0
0  0  229367 332745   0   0   0   0    0   0   2   33  68    0  0 99  0
0  0  229367 332745   0   0   0   0    0   0  80  306 100    0  1 97  1
0  0  229367 332745   0   0   0   0    0   0   1   20  68    0  0 99  0
0  0  229367 332745   0   0   0   0    0   0   2   36  64    0  0 99  0

*  r -- Среднее число выполняемых ядром потоков за временной интервал, который Вы выбрали.
*  b -- Среднее число потоков, которые ждут своей очереди на выполнение в виртуальной памяти в течение заданного Вами промежутка времени. r всегда должен быть выше чем b; если нет, то в обычном случае это означает то, что слабым местом, давшим сбой, является центральный процессор.
* fre -- размер свободной памяти. Не волнуйтесь, если он окажется маленьким короткий. Главное - определить, происходит ли разбиение этой небольшой свободной памяти на страницы.
* pi -- Страницы, подкачанные в физическую память из виртуальной.
* po -- Страницы, откачанные из физической памяти в виртуальную.
* CPU сегменты:
    *   us -- время пользователя
    * sy -- системное время
    * id -- время простоя
    * wa --ожидание ввода/вывода

2. Различная статистика
$ vmstat -v
              2031616 memory pages
              1974804 lruable pages
               549549 free pages
                    1 memory pools
               141346 pinned pages
                 80.1 maxpin percentage
                 20.0 minperm percentage
                 80.0 maxperm percentage
                 30.7 numperm percentage
               608228 file pages
                  0.0 compressed percentage
                    0 compressed pages
                 26.9 numclient percentage
                 80.0 maxclient percentage
               531937 client pages
                    0 remote pageouts scheduled
                17011 pending disk I/Os blocked with no pbuf
                    0 paging space I/Os blocked with no psbuf
                 4849 filesystem I/Os blocked with no fsbuf
                    0 client filesystem I/Os blocked with no fsbuf
                    3 external pager filesystem I/Os blocked with no fsbuf

aix: top processes by memory usage

1. Процессы, уоторые отъедают больше всего памяти
Выводит список процессов отсортированных по использованию памяти(2й столбец vsz)

ps -ef -o pid,vsz,comm |sort -nr +1

vsz - объём памяти в кб

1 сентября 2011 г.

bash: специальные параметры

Специальные параметры

Параметр    Правила замены

*    Заменяется позиционными параметрами, начиная с первого. Если замена производится внутри двойных кавычек, то этот параметр заменяется на одно единственное слово, составленное из всех позиционных параметров, разделенных первым символом специальной переменной IFS (о ней будет сказано ниже). То есть ``$*'' эквивалентно ``$1c$2c...'', где c - первый символ в значении переменной IFS. Если IFS присвоено пустое значение или ее значение не установлено, параметры разделяются пробелами

@    Заменяется позиционными параметрами, начиная с первого. Если замена производится внутри двойных кавычек, то каждый параметр заменяется отдельным словом. Так, ''$@'' эквивалентно ''$1'' ''$2'' ... Если позиционных параметров нет, то значение не присваивается (параметр @ просто удаляется)

#    Заменяется десятичным значением числа позиционных параметров

?    Заменяется статусом выхода последнего из выполнявшихся на переднем плане программных каналов

-(дефис)    Заменяется текущим набором значений флагов, установленных с помощью встроенной команды set или при запуске самой оболочки

$    Заменяется идентификатором процесса (PID) оболочки

!    Заменяется идентификатором процесса (PID) последней из выполняющихся фоновых (асинхронно выполнявшихся) команд

0    Заменяется именем оболочки или запускаемого скрипта. Если bash запускается для выполнения командного файла, $0 равно имени этого файла. В противном случае это значение равно полному пути к оболочке

bash: условные выражения

# -a file
Верно, если файл с именем file существует.

# -b file
Верно, если file существует и является специальным файлом блочного устройства.

# -c file
Верно, если file существует и является специальным файлом символьного устройства.

# -d file
Верно, если file существует и является каталогом.

# -e file
Верно, если файл с именем file существует.

# -f file
Верно, если файл с именем file существует и является обычным файлом.

# -g file
Верно, если файл с именем file существует и для него установлен бит смены группы.

# -h file или -L file
Верно, если файл с именем file существует и является символической ссылкой.

# -k file
Верно, если файл с именем file существует и для него установлен "sticky'' bit.

# -p file
Верно, если файл с именем file существует и является именованным каналом (FIFO).

# -r file
Верно, если файл с именем file существует и для него установлено право на чтение

# -s file
Верно, если файл с именем file существует и его размер больше нуля.

# -t fd
Верно, если дескриптор файла fd открыт и указывает на терминал.

# -u file
Верно, если файл с именем file существует и для него установлен бит смены пользователя.

# -w file
Верно, если файл с именем file существует и для него установлено право на запись.

# -x file
Верно, если файл с именем file существует и является исполняемым.

# -O file
Верно, если файл с именем file существует и его владельцем является пользователь, на которого указывает эффективный идентификатор пользователя.

# -G file
Верно, если файл с именем file существует и принадлежит группе, определяемой эффективным идентификатором группы.

# -S file
Верно, если файл с именем file существует и является сокетом.

# -N file
Верно, если файл с именем file существует и изменялся с тех пор, как был последний раз прочитан.

# file1 -nt file2
Верно, если файл file1 имеет более позднее время модификации, чем file2.

# file1 -ot file2
Верно, если файл file1 старше, чем file2.

# file1 -ef file2
Верно, если файлы file1 и file2 имеют одинаковые номера устройств и индексных дескрипторов (inode).

# -o optname
Верно, если задействована опция оболочки optname. Пояснения см. на странице man bash.

# -z string
Верно, если длина строки равна нулю.

# -n string
Верно, если длина строки не равна нулю.

# string1 == string2
Верно, если строки совпадают. Вместо == может использоваться =.

# string1 !== string2
Верно, если строки не совпадают.

# string1 < string2
Верно, если строка string1 лексикографически предшествует строке string2 (для текущей локали).

# string1 > string2
Верно, если строка string1 лексикографически стоит после строки string2 (для текущей локали).

# arg1 OP arg2
Здесь OP - это одна из операций арифметического сравнения: -eq (равно), -ne (не равно), -lt (меньше чем), -le (меньше или равно), -gt (больше), -ge (больше или равно). В качестве аргументов могут использоваться положительные или отрицательные целые.

# !(expression)
Булевский оператор отрицания.

# expression1 -a expression2
Булевский оператор AND (И). Верен, если верны оба выражения.

# expression1 -o expression2
Булевский оператор OR (ИЛИ). Верен, если верно любое из двух выражений.
 

4 августа 2011 г.

oracle: Транзакции

Transactions

Выдержки из Тома Кайта.

Транзакции в Oracle удовлетворяют всем требуемым характеристикам  ACID.
Аббревиатура ACID   означает:
•   атомарность (atomicity) — выполняется либо вся транзакция целиком, либо она целиком не выполняется;
•   согласованность (consistency) — транзакция переводит базу данных из одного согласованного состояния в другое;
•   изоляция (isolation) — эффект от транзакции не виден другим транзакциям до тех пор, пока она не будет зафиксирована;
•   устойчивость (durability) — как только транзакция зафиксирована, она остается постоянной.



Атомарность

Рассмотрим пример:
Создадим таблицы T(вставляем сюда строки) и T2(содержит счётчик строк в таблице T), и триггер, который при вставке строки в T, увеличивает значение счётчика в Т2, при удалении - уменьшает.

26 июля 2011 г.

oracle: простая схема выполнения sql запроса

SQL execution

oracle: library cache

Library cache - часть shared pool, область памяти, которая содержит распарсенные выражения.

Парсинг включает в себя проверку синтаксиса выражения, проверку объектов, и проверку привелегий пользователя на эти объекты.

После Oracle проверяет есть ли уже такое же выражение, в library cache.

Soft parse - если выражение уже есть в library cache, то Oracle использует его оптимизированный вариант, его план выполнения.
Hard parse - если выражения нет в library cache, то Oracle оптимизирует выражение, строит новый план выполнения.

Соответсвенно, soft parse лучше чем hard parse с точки зрения производительности.



Посмотреть какие запросы находятся в library cache можно с помощью v$sql.

Пример. Выполним 3 вроде бы одинаковых запроса 

select * from emp where deptno=10;
SELECT * FROM emp WHERE deptno = 10;
select /*comment*/ * from emp where deptno=10;

-- посмотрим что в library cache
select sql_text, hash_value, address, executions from v$sql where upper(sql_text) like '%EMP%';

--результат
SQL_TEXT HASH_VALUE ADDRESS EXECUTIONS
select * from emp where deptno=10 508465132 070000002C193B50 1
SELECT * FROM emp WHERE deptno = 10 1243201595 070000002C14A328 1
select /*comment*/ * from emp where deptno=10 330949115 070000002C143260 1

Получилось 3 разных разобранных запроса.
Это получилось из-за того, что хоть запросы логически выглядят одинаково, но из-за различий в регистре и из-за комментария, Oracle распознал их как 3 разных запроса.




oracle: Instance and database diagram


Схема архитектуры Oracle

25 июля 2011 г.

oracle: DELETE

1. Удалить все записи, где sal < 1000, можно двумя вариантами:

-- можно так
delete from (select * from emp where sal< 1000);

-- или "классический"
delete from emp where sal < 1000;

14 июля 2011 г.

oracle: Нумерация строк в запросе

Источник: Нумерация строк в запросе

Есть таблица.
Нужно последовательно вывести записи вместе с порядковым номером:

SELECT ROWNUM, pole1, pole2, pole3
  FROM my_table;

Однако если перед выводом нужно записи отсортировать (ORDER BY) по полям, тогда такой запрос не проходит, так как Оракл сначала формирует ROWNUM, и лишь потом сортирует записи.

Поэтому будем оракл обманывать таким образом:

SELECT ROWNUM, pole1, pole2, pole3
  FROM (SELECT   pole1, pole2, pole3
            FROM my_table
        ORDER BY pole1, pole2, pole3);

Ну а для гурманов смотреть здесь «аналитические функции»

13 июля 2011 г.

oracle: db file parallel read

db file parallel read

Кроме recovery, операция используется при buffer prefetching [опережающем чтении блоков данных] как оптимизация I/O (заменяя несколько одноблочных чтений (single-block reads))

oracle: log file switch

log file switch

Ожидание переключения лог файлов по причине незаконченной операции checkpoint – записи процессом DBWR модифицированных блоков бд из кэша (buffer cache) на диск

oracle: log file switch completion

log file switch completion

Ожидание завершения процесса переключения лог файлов (online redo logs), вероятная причина – неправильный (малый) размер online лог файлов (redo logs), недостаточное количество групп лог файлов (redo log groups)

oracle: log file sync

log file sync

Пользовательский сессия (foreground process) ожидает совершения системным процессом (background process) LGWR операции записи модифицированных данных из лог буфера в redo log файл во время выполнения пользовательской сессией операции завершения транзакции COMMIT / ROLLBACK.

Ожидание может быть заметно в случае низкой скорости записи процессом LGWR или высокой конкуренции за системные ресурсы (диск, процессор). Типичные причины: неудачное размещение и [коственно] малый размер лог файлов (online redo logs), низкая производительность и/или неудачная конфигурация подсистемы ввода-вывода*), либо высокая (возможно, избыточная?) интенсивность операций COMMIT / ROLLBACK**.
Нормальное время ожидания не должно превышать нескольких миллисекунд для OLTP систем

*) Пример: несколько копий лог файлов (для «надёжности») на одном небыстром разделе RAID5 либо RAID6 (для «экономии»). Время ожидания может легко превышать и 20, и 30, и 80 ms. Oracle категорически не рекомендует RAID5 для размещения online redo log файлов

**) При невозможности изменить приложение с целью уменьшить частоту транзакций, для буферизации и выбора асинхронного режима можно рассмотреть изменение параметров COMMIT_WRITE (начиная с Oracle 10g) или COMMIT_LOGGING, COMMIT_WAIT (начиная с 11g)




WAITEVENT: «log file sync» Reference Note [ID 34592.1]:
 Ожидание log file sync может состоит из следующих компонент:
1. сессия пользователя посылает вызов системному процессу LGWR, который начинает обработку запроса, если не занят обработкой др.вызовов
2. LGWR собирает/готовит необходимые для записи redo данные и вызывает операцию ввода/вывода
3. операция записи log write
4. обработка результатов записи процессом LGWR
5. LGWR посылает сообщение пользовательской сессии сообщение о выполнении операции записи
6. сессия пользователя продолжает работу
Шаги 2 и 3 суммируются в статистике redo write time
Шаг 3 соответствует системному событию ожидания (Background Wait Events) log file parallel write
Шаги 5 и 6 могут занимать значительное время при увеличенной системной загрузке (load average) … после посылки сообщения пользовательскому процессу о завершении выполнения операции, ОС может потребоваться время до очередного запуска пользовательского процесса на выполнение…

oracle: direct path write / direct path write temp

direct path write / direct path write temp

Ожидание выполнения операции записи (write call) возникает, когда пользовательский процесс пишет блоки данных данные напрямую (directly) из PGA (в отличие от DBWR, пишущего на диск из buffer cache).

Direct path writes выполняется при след.операциях: дисковые сортировки (direct path write temp), параллельные DML, direct-path INSERTs, параллельные create table as select и некоторые операции с LOB

Аналогично direct path reads, количество ожиданий не обязательно совпадает с кол-вом запросов на запись в асинхронном режиме»

Соответствующая ожиданию статистика physical write direct

oracle: direct path read / direct path read temp

Источник: Oracle mechanics
direct path read / direct path read temp

«Возникает при чтении пользовательским процессом данных с диска напрямую  в PGA (в отличие от чтения в buffer cache SGA)

В синхронном режиме ввода-вывода каждое ожидание соответствует запросу на физическое чтение. При использовании асинхронного ввода-вывода, [пользовательский] процесс Oracle способен совмещать генерацию запросов на чтение данных с обработкой блоков, уже находящихся в PGA. [И только] когда процесс пытается получить доступ к блоку, который ещё не был прочитан с диска в PGA, генерируется вызов (wait call) и обновляется статистика этого события. Таким образом, количество ожиданий не обязательно совпадает с кол-вом запросов на чтение (в отличие от ожиданий db file scattered read и db file sequential read)


Типичные ситуации возникновения ожидания:
  • Сортировка большого (по сравнению с размером PGA или sort_area_size) объёма данных, после записи во временный сегмент, данные считываются с использованием операций direct path read temp
  • Использование параллельные процессами (parallel slaves)
  • Пользовательский серверный процесс обрабатывает данные в PGA быстрее, чем система ввода-вывода может считывать очередные блоки данных (buffers). Может быть индикатором недостаточной производительности ввода-вывода»
Scattered Read, Sequential Read, and Direct Path Read
Scattered Read, Sequential Read, and Direct Path Read
Операция direct path read применяется при непараллельном сканировании больших таблиц – см. High ‘direct path read’ waits in 11g [ID 793845.1]: «Начиная с Oracle 11g произошли изменения правил при выборе между операциями direct path reads и чтением через buffer cache (ожидание db file scattered read) при сканировании таблиц [full table scan].

В версии 10g, сканирование «больших» таблиц выполнялось через буферный кэш (по умолчанию). В 11g, решение о выполнении чтения данных с использованием direct path или через буферный кэш основывается на размере таблицы, размере буферного кэша и др.статистиках.

Direct path reads быстрее, чем scattered reads и меньше влияет на производительность др.процессов, т.к. исключает конкуренцию за latches

Документ How does Oracle load data into the buffer cache for table scans ? [ID 787373.1] описывает правила выбора метода сканирования «больших» таблиц (или разделения таблиц на большие и маленькие -  smallness logic):
  • Если кол-во блоков меньше или равно параметру _small_table_threshold Oracle сканирует объект через buffer cache,  считая это более эффективным, чем использование direct read
  • Любой объект (таблица) размером менее 2% буферного кэша будет сканироваться через buffer cache без использования direct load
В блоге Alex’а Fatkulin 11G adaptive direct path reads — what is the cached/dirty blocks threshold? можно найти исследование некоторых параметров, которые берутся в расчёт Oracle при выборе использования direct path read:
  • размер (в блоках) таблицы ~ _small_table_threshold умноженный на 5
  • cached blocks threshold – кол-во блоков таблицы, уже находящихся в буферном кэше SGA
  • dirty blocks threshold- кол-во изменённых блоков таблицы, находящихся в буферном кэше SGA, не сброшенных на диск процессом DBWR
imho, по умолчанию, при старте инстанса параметр _small_table_threshold устанавливается ~ 1.9-2 % от размера буферного кэша [__]db_cache_size / db_block_size

Для форсированного включения direct path read в документах поддержки упоминается установка параметра _serial_direct_read=TRUE (доступно на уровне сессии, значение по умолчанию FALSE)

Для отключения Dion Cho Disabling direct path read for the serial full table scan– 11g нашёл и описал событие 10949:
$ oerr 10949
  "Disable autotune direct path read for full table scan"
// *Cause:
// *Action:  Disable autotune direct path read for serial full table scan.
//
SQL> alter session set events '10949 trace name context forever, level 1';

Соответствующая ожиданию статистика physical reads direct

oracle: read by other session

Сессия ожидает блок данных, который в настоящий момент считывается в буферный кэш (buffer cache) другой сессией. До версии 10g событие учитывалось в группе ожиданий buffer busy wait.

Может случаться, например, когда две сессии делают full table scan  в одно и то же время.

Алгоритм:
- блок не найден в буферном кэше
- читаем блок с диска
- выясняем что другая сессия уже читает блок с диска
- ждём пока другая сессия закончит чтение

oracle: Ожидания, статистики, коэффициенты

12 июля 2011 г.

oracle: Outer Joins

http://aguppi.blogspot.com/2011/05/oracle-join.html
Outer Joins (Oracle docs)

oracle: Cartesian Joins

http://aguppi.blogspot.com/2011/07/oracle-table-joins.html
cbo-access-path

«… используется в случае, когда одна или несколько таблиц не имеют никаких условий (join conditions) для соединения с другими таблицами запроса. Оптимизатор соединяет каждую строку первого источника данных с каждой строкой другого, создавая картезианское произведение (Cartesian product) двух наборов данных»
SQL> select job, dname from emp cross join dept;
SQL> select job, dname from emp, dept;

-----------------------------------------------------------------------------
| Id  | Operation            | Name | Rows  | Bytes | Cost (%CPU)| Time     |
-----------------------------------------------------------------------------
|   0 | SELECT STATEMENT     |      |    56 |  1008 |    10   (0)| 00:00:01 |
|   1 |  MERGE JOIN CARTESIAN|      |    56 |  1008 |    10   (0)| 00:00:01 |
|   2 |   TABLE ACCESS FULL  | DEPT |     4 |    40 |     3   (0)| 00:00:01 |
|   3 |   BUFFER SORT        |      |    14 |   112 |     7   (0)| 00:00:01 |
|   4 |    TABLE ACCESS FULL | EMP  |    14 |   112 |     2   (0)| 00:00:01 |
-----------------------------------------------------------------------------

SQL> select /*+ ORDERED*/ * from dept d, bonus b, emp e
 2  where d.deptno = e.deptno
 3  and b.ename = e.ename;

-------------------------------------------------------------------------------
| Id  | Operation             | Name  | Rows  | Bytes | Cost (%CPU)| Time     |
-------------------------------------------------------------------------------
|   0 | SELECT STATEMENT      |       |     1 |    96 |    10  (10)| 00:00:01 |
|*  1 |  HASH JOIN            |       |     1 |    96 |    10  (10)| 00:00:01 |
|   2 |   MERGE JOIN CARTESIAN|       |     1 |    59 |     6   (0)| 00:00:01 |
|   3 |    TABLE ACCESS FULL  | DEPT  |     4 |    80 |     3   (0)| 00:00:01 |
|   4 |    BUFFER SORT        |       |     1 |    39 |     3   (0)| 00:00:01 |
|   5 |     TABLE ACCESS FULL | BONUS |     1 |    39 |     1   (0)| 00:00:01 |
|   6 |   TABLE ACCESS FULL   | EMP   |    14 |   518 |     3   (0)| 00:00:01 |
-------------------------------------------------------------------------------
В последнем примере благодаря подсказке ORDERED оптимизатор первым делом соединяет таблицы DEPT и BONUS, не имеющих по условиям запроса никаких условий для соединения (join keys), следовательно, единственной возможной операцией оказывается Join Cartesian.
В случае, когда две небольшие таблицы (DEPT и BONUS) соединяются через условия d.deptno = e.deptno and b.ename = e.ename к «большой» таблице EMP и имеются дополнительные условия на столбцы небольших таблиц (фильтры dept.loc = ‘CHICAGO’ and bonus.comm > 30), оптимизатор по соображениям избирательности (selectivity) без всяких подсказок выбирает Merge Join Cartesian небольших таблиц с последующим соединением (Hash join) с большой таблицей:
SQL> exec dbms_stats.set_table_stats(ownname => 'SCOTT',tabname => 'EMP', numrows => 100000);

PL/SQL procedure successfully completed.

SQL> select * from dept d, bonus b, emp e
 2  where d.deptno = e.deptno and d.loc = 'CHICAGO'
 3  and b.ename = e.ename and b.comm > 30;

Execution Plan
-------------------------------------------------------------------------------
| Id  | Operation             | Name  | Rows  | Bytes | Cost (%CPU)| Time     |
-------------------------------------------------------------------------------
|   0 | SELECT STATEMENT      |       |  2381 |   174K|    16  (44)| 00:00:01 |
|*  1 |  HASH JOIN            |       |  2381 |   174K|    16  (44)| 00:00:01 |
|   2 |   MERGE JOIN CARTESIAN|       |     1 |    38 |     6   (0)| 00:00:01 |
|*  3 |    TABLE ACCESS FULL  | DEPT  |     1 |    18 |     3   (0)| 00:00:01 |
|   4 |    BUFFER SORT        |       |     1 |    20 |     3   (0)| 00:00:01 |
|*  5 |     TABLE ACCESS FULL | BONUS |     1 |    20 |     3   (0)| 00:00:01 |
|   6 |   TABLE ACCESS FULL   | EMP   |   100K|  3613K|     8  (63)| 00:00:01 |
-------------------------------------------------------------------------------

Predicate Information (identified by operation id):
---------------------------------------------------
 1 - access("D"."DEPTNO"="E"."DEPTNO" AND "B"."ENAME"="E"."ENAME")
 3 - filter("D"."LOC"='CHICAGO')
 5 - filter("B"."COMM">30)


Хинты
Можно использовать ORDERED

oracle: Sort Merge Joins

http://aguppi.blogspot.com/2011/07/oracle-table-joins.html
Sort Merge Joins (Oracle docs)
cbo-access-path

Sort merge joins используются для объединения строк из 2х независимых таблиц.

Sort merge joins успешно используется, когда в условиях соединения двух таблиц присутствуют операторы сравнения: <, <=, >, или >= , но не для операторов равества/неравества. Производительность sort merge joins лучше, чем у nested loop joins для больших наборов данных (data sets). [Также следует обратить внимание на то, что ] вы не можете использовать [более производительные операции] hash joins для соединения таблиц, если условия соединения отличаются от равенства (equality condition).

Sort merge joins лучше Hash Joins если:
  • строки уже отсортированы
  • операция сортировки не должна выполняться
При выполнении операции merge join отсутствует концепция ведущей (driving table) / ведомой таблицы.
    Sort merge joins состоит из 2х шагов:
    • Sort join: Оба источника входных данных / таблицы сортируются по ключу соединения (join key).
    • Merge join: Совместная обработка / объдинение (merging) отсортированных списков.
    Sort merge joins может использоваться для соединений с условиями отличными от равенства ( <, <=, >, >= , но не для операторов равества/неравества ), чего не позволяет Hash Joins.


    Например, при использовании оператора сравнения «>» несвязанных столцов видим по одной операции SORT JOIN для каждой таблицы и объединённую операцию MERGE JOIN:

    SQL> select * from emp e, dept d where e.empno > d.deptno;

    Execution Plan
    ----------------------------------------------------------------------------------------
    | Id  | Operation                     | Name   | Rows  | Bytes | Cost (%CPU)| Time     |
    ----------------------------------------------------------------------------------------
    |   0 | SELECT STATEMENT              |        |    56 |  3192 |     6  (17)| 00:00:01 |
    |   1 |  MERGE JOIN                   |        |    56 |  3192 |     6  (17)| 00:00:01 |
    |   2 |   SORT JOIN                   |        |    14 |   518 |     2   (0)| 00:00:01 |
    |   3 |    TABLE ACCESS BY INDEX ROWID| EMP    |    14 |   518 |     2   (0)| 00:00:01 |
    |   4 |     INDEX FULL SCAN           | PK_EMP |    14 |       |     1   (0)| 00:00:01 |
    |*  5 |   SORT JOIN                   |        |     4 |    80 |     4  (25)| 00:00:01 |
    |   6 |    TABLE ACCESS FULL          | DEPT   |     4 |    80 |     3   (0)| 00:00:01 |
    ----------------------------------------------------------------------------------------
    Predicate Information (identified by operation id):
    ---------------------------------------------------
    5 - access(INTERNAL_FUNCTION("E"."EMPNO")>INTERNAL_FUNCTION("D"."DEPTNO"))
    filter(INTERNAL_FUNCTION("E"."EMPNO")>INTERNAL_FUNCTION("D"."DEPTNO"))

    В случае с отсортироваными значениями одна из операций SORT JOIN исключается за ненадобностью:

    SQL> select * from
    2  (select empno from emp order by 1) e,
    3  (select deptno from dept order by 1) d
    4  where e.empno > d.deptno;

    Execution Plan
    ------------------------------------------------------------------------------
    | Id  | Operation          | Name    | Rows  | Bytes | Cost (%CPU)| Time     |
    ------------------------------------------------------------------------------
    |   0 | SELECT STATEMENT   |         |    56 |   896 |     3  (34)| 00:00:01 |
    |   1 |  MERGE JOIN        |         |    56 |   896 |     3  (34)| 00:00:01 |
    |   2 |   INDEX FULL SCAN  | PK_DEPT |     4 |    12 |     1   (0)| 00:00:01 |
    |*  3 |   SORT JOIN        |         |    14 |   182 |     2  (50)| 00:00:01 |
    |   4 |    VIEW            |         |    14 |   182 |     1   (0)| 00:00:01 |
    |   5 |     INDEX FULL SCAN| PK_EMP  |    14 |    56 |     1   (0)| 00:00:01 |
    ------------------------------------------------------------------------------
    Predicate Information (identified by operation id):
    ---------------------------------------------------
    3 - access("E"."EMPNO">"DEPTNO")
    filter("E"."EMPNO">"DEPTNO")

    Хинты
    /*+ USE_MERGE( tab1 tab2) */

    11 июля 2011 г.

    oracle: hash Joins

    http://aguppi.blogspot.com/2011/07/oracle-table-joins.html
    Hash Joins (Oracle docs)

    Hash Joins используются для объединения больших наборов данных. 
    Оптимизатор выбирает меньшую таблицу и создает хеш-таблицу для ключа объединения в памяти. Затем он просматривает другую таблицу(большую) и проверяет хеш таблицу в памяти на совпадения с ней.

    Hash Join Hint
    /*+ USE_HASH(tab1 tab2)*/

    SELECT /*+use_hash(employees departments)*/ * 
    FROM employees, departments 
    WHERE employees.department_id = departments.department_id; 

    8 июля 2011 г.

    oracle: Nested Loop Joins

    http://aguppi.blogspot.com/2011/07/oracle-table-joins.html
    Nested Loop Joins (Oracle docs)

    Nested Loops (объединения с вложенными циклами) - читает строку из 1й таблицы(ведущая таблица - outer table), и затем сравнивает всю 2ю таблицу(ведомая таблица - inner table) на совпадение, затем берёт следующую строку из 1й таблицы и опять сравнивает всю 2ю таблицу на совпадение и т.д.


    Nested Loops hint
    Используем хинт /*+ USE_NL*/, можно в связке с ORDERED, чтобы гарантировать нужный порядок обращения к таблицам.

    SELECT /*+ ORDERED USE_NL(customers) to get first row faster */
        accounts.balance, customers.last_name, customers.first_name
    FROM accounts, customers
    WHERE accounts.customer_id = customers.customer_id;
     
    SELECT /*+ USE_NL(l h) */ h.customer_id, l.unit_price * l.quantity
      FROM orders h ,order_items l
     WHERE l.order_id = h.order_id; 


    Nested Loops быстро извлекают 1е несколько строк результирующего множества, но по общему времени выполнения Hash Joins быстрее. Этим свойством можно воспользоваться, когда пользователю нужно быстро получить 1е несколько строк, не дожидаясь всего результата.

    В плане выполнения сначала идёт цикл по 1й таблице(outer loop) , а потом по 2й (inner loop)
    NESTED LOOPS
      outer_loop
      inner_loop
    ...
    |   2 |   NESTED LOOPS                |              |     3 |   141 |     7  (15)|
    |*  3 |    TABLE ACCESS FULL          | EMPLOYEES    |     3 |    60 |     4  (25)|
    |   4 |    TABLE ACCESS BY INDEX ROWID| JOBS         |    19 |   513 |     2  (50)|
    |*  5 |     INDEX UNIQUE SCAN         | JOB_ID_PK    |     1 |       |            |
    ... 

    В этом примере outer loop сначала получает все строки из таблицы EMPLOYEES, а затем для каждого сотрудника inner loop получает соответствующие строки из таблицы JOBS.


    Nested Loops идеален, если 1я таблица маленькая, и объединённые столбцы проиндексированы  уникально или этот индекс высоко избирательный.
    Строка из 1й таблицы обычно получается из index scan или full table scan, а из 2й таблицы было бы идеально, чтобы строка выбиралась с помощью index scan.

    oracle: Избирательность индекса

    В представлении USER_INDEXES есть столбец distinct_keys, который содержит кол-во уникальных ключей для этого индекса. Сравнение  distinct_keys и числа строк в таблице позволяет определить избирательность индекса. Чем ближе distinct_keys к числу строк в таблице, тем более избирательный индекс, запрос с использованием этого индекса вернёт меньшее кол-во строк, сообтветсвенно быстрее отработает запрос. Но при использовании дополнительных индексов (сложные/сцепленные индексы) в запросе издержки могут превысить выгоду.

    6 июля 2011 г.

    oracle: sga_target

    SGA_TARGET

    Property Description
    Parameter type Big integer
    Syntax SGA_TARGET = integer [K | M | G]
    Default value 0 (SGA autotuning is disabled)
    Modifiable ALTER SYSTEM
    Range of values 64 to operating system-dependent
    Basic Yes
    SGA_TARGET specifies the total size of all SGA components. If SGA_TARGET is specified, then the following memory pools are automatically sized:
    • Buffer cache (DB_CACHE_SIZE)
    • Shared pool (SHARED_POOL_SIZE)
    • Large pool (LARGE_POOL_SIZE)
    • Java pool (JAVA_POOL_SIZE)
    • Streams pool (STREAMS_POOL_SIZE)
    If these automatically tuned memory pools are set to non-zero values, then those values are used as minimum levels by Automatic Shared Memory Management. You would set minimum values if an application component needs a minimum amount of memory to function properly.
    The following pools are manually sized components and are not affected by Automatic Shared Memory Management:
    • Log buffer
    • Other buffer caches, such as KEEP, RECYCLE, and other block sizes
    • Fixed SGA and other internal allocations
    The memory allocated to these pools is deducted from the total available for SGA_TARGET when Automatic Shared Memory Management computes the values of the automatically tuned memory pools.

    oracle: sga_max_size

    SGA_MAX_SIZE

    Property Description
    Parameter type Big integer
    Syntax SGA_MAX_SIZE = integer [K | M | G]
    Default value Initial size of SGA at startup, dependent on the sizes of different pools in the SGA, such as buffer cache, shared pool, large pool, and so on.
    Modifiable No
    Range of values 0 to operating system-dependent
    SGA_MAX_SIZE specifies the maximum size of the SGA for the lifetime of the instance.

    5 июля 2011 г.

    oracle: sql условие EXISTS

    Условие EXISTS и проверка существования набора значений в ORACLE SQL

    Условие EXISTS используется только в одной ситуации — когда вы используете в запросе и подзапрос и хотите проверить, возвращает ли подзапрос записи. Если подзапрос возвращает хотя бы одну запись, то условие EXISTS вернет True, если нет — то False.

    Пример применения этого условия может выглядеть так:

    SELECT * FROM departments d WHERE EXISTS
    (SELECT * FROM employees e WHERE d.department_id = e.department_id);

    В этом примере мы возвращаем информацию о всех департаментах, для которых в таблице employees есть сотрудники.

    Этот запрос можно переписать с помощью конструкции IN:
    SELECT *
      FROM users
     WHERE users.ID IN (SELECT users_id
                          FROM users_res
                         WHERE users.ID = users_res.users_id AND users_res.ID > 1);



    Как обычно, это условие EXISTS можно обращать при помощи NOT:

    SELECT * FROM departments d WHERE NOT EXISTS
    (SELECT * FROM employees e WHERE d.department_id = e.department_id);

    Те же возможности предусмотрены и для Microsoft  SQL Server.

    wget

    Нужно скачать много файлов шаблона file_NNN.ext с одного места.

    На perl пишем скрипт:

    open (MYFILE, '>>files.txt');
    for ($count = 500; $count < 600; $count++) {
        print MYFILE "http://www.url.net/files/".$count.".ext\n" ;
    }
    close (MYFILE);

    Получаем файл со ссылками files.txt

    Далее тянем их при помощи wget:

    wget -c -i files.ext


    oracle: Tables Joins (объединения таблиц)

    Из Oracle9i Database Performance Tuning Guide and Reference Release 2 (9.2) Understanding Joins
    CBO access path


    Виды соединений:
    Nested Loop Joins
    Hash Joins
    Sort Merge Joins
    Cartesian Joins
    Outer Joins


    Как оптимизатор выбирает метод соединения
    Оптимизатор оценивает стоимость каждого метода и выбирает самый дешёвый из них.

    • Nested Loop Joins обычно не эффективен при соединении большого кол-ва строк (обычно более 10 000 строк уже много). Стоимость Nested Loop Joins рассчитывается по формуле:
      cost= access cost of A + (access cost of B * number of rows from A)
    •  Hash Joins эффективны для большого кол-ва строк. Стоимость Hash Joins рассчитывается по формуле:
      cost= (access cost of A * number of hash partitions of B) + access cost of B
    • При использовании RBO оптимизатора эффективны Merge Joins. Стоимость Merge Joins рассчитывается по формуле:
      cost= access cost of A + access cost of B +(sort cost of A + sort cost of B)
      Если данные уже отсортированы, то стоимость сортировки равна нулю.


    Как оптимизатор выбирает Execution Plan (план выполнения)

    Оптимизатор должен решить в каком порядке соединять таблицы, т.е. какая таблица будет 1й, 2й и т.д.
    Если нужно указать порядок соединения вручную, то используется хинт ORDERED (/*+ ORDERED */), тогда соединение осуществляется в том порядке, в котором указаны таблицы после from.
    Например: select /*+ ORDERED*/ col1, col2, col3, col4 from t1, t2, t3


    Это одинаково для CBO и RBO:
    •  Оптимизатор определяет какая из таблиц вернёт не более чем одну строку основываясь на ограничениях UNIQUE и PRIMARY KEY для таблицы. Если такая ситуация действительна, то оптимизатор ставит эту таблицу на первое место в соединении
    • For join statements with outer join conditions, the table with the outer join operator must come after the other table in the condition in the join order. The optimizer does not consider join orders that violate this rule. 

    With the CBO, the optimizer generates a set of execution plans, according to possible join orders, join methods, and available access paths. The optimizer then estimates the cost of each plan and chooses the one with the lowest cost. The optimizer estimates costs in the following ways:
    • The cost of a nested loops operation is based on the cost of reading each selected row of the outer table and each of its matching rows of the inner table into memory. The optimizer estimates these costs using the statistics in the data dictionary.
    • The cost of a sort merge join is based largely on the cost of reading all the sources into memory and sorting them.

    oracle: Sample Table Scans

    http://aguppi.blogspot.com/2011/06/oracle-access-path.html

    A sample table scan retrieves a random sample of data from a table. This access path is used when a statement's FROM clause includes the SAMPLE clause or the SAMPLE BLOCK clause. To perform a sample table scan when sampling by rows (the SAMPLE clause), Oracle reads a specified percentage of rows in the table. To perform a sample table scan when sampling by blocks (the SAMPLE BLOCK clause), Oracle reads a specified percentage of table blocks.

    Oracle does not support sample table scans when the query involves a join or a remote table. However, you can perform an equivalent operation by using a CREATE TABLE AS SELECT query to materialize a sample of an underlying table. You then rewrite the original query to refer to the newly created table sample. Additional queries can be written to materialize samples for other tables. Sample table scans require the CBO.

    Example 1-13 uses a sample table scan to access 1% of the employees table, sampling by blocks.

    Example 1-13 Sample Table Scan

    SELECT * 
        FROM employees SAMPLE BLOCK (1); 
    
    

    The EXPLAIN PLAN output for this statement might look like this:
    -------------------------------------------------------------------------
    | Id  | Operation            |  Name       | Rows  | Bytes | Cost (%CPU)|
    -------------------------------------------------------------------------
    |   0 | SELECT STATEMENT     |             |     1 |    68 |     3  (34)|
    |   1 |  TABLE ACCESS SAMPLE | EMPLOYEES   |     1 |    68 |     3  (34)|
    -------------------------------------------------------------------------
    

    oracle: Hash Scans

    http://aguppi.blogspot.com/2011/06/oracle-access-path.html

     A hash scan is used to locate rows in a hash cluster, based on a hash value. In a hash cluster, all rows with the same hash value are stored in the same data block. To perform a hash scan, Oracle first obtains the hash value by applying a hash function to a cluster key value specified by the statement. Oracle then scans the data blocks containing rows with that hash value.

    oracle: Cluster Scans

    http://aguppi.blogspot.com/2011/06/oracle-access-path.html

    A cluster scan is used to retrieve, from a table stored in an indexed cluster, all rows that have the same cluster key value. In an indexed cluster, all rows with the same cluster key value are stored in the same data block. To perform a cluster scan, Oracle first obtains the rowid of one of the selected rows by scanning the cluster index. Oracle then locates the rows based on this rowid.

    27 июня 2011 г.

    windows: hotkeys

    Ctrl+Shift+Esc - Диспетчер задач

    Win+Up - Развернуть окно
    Win+Down - Восстановить / Минимизировать окно
    Win+Left - Прикрепить окно к левому краю экрана
    Win+Right - Прикрепить окно к правому краю экрана
    Win+Shift+Left - Переключиться на левый монитор
    Win+Shift+Right - Переключиться на правый монитор
    Win+Home - Минимизировать / Восстановить все окна
    Win+Т - Выбрать первый элемент в панели задач (Повторное нажатие переключает на следующий элемент, Win+Shift+T - прокручивает в обратном порядке)
    Win+Space - Показать рабочий стол
    Win+G - Отобразить гаджеты поверх всех окон
    Win+P - Отобразить дополнительные опции дисплея (расширить рабочий стол на 2 монитор и т.п.)
    Win+X - Запустить Mobility Center
    Win+ цифра- Запустить приложение с панели задач (Win+1 запускает первое приложения слева, Win+2, второе, и т.к.)
    Win + "+" - Увеличить масштаб
    Win + "-" - Уменьшить мастшаб

    Windows Explorer

    Alt+P - Показать / Скрыть панель предпросмотра

    Панель задач

    Shift + щелчок на иконке - Открыть новое окно приложения
    Ctrl + Shift + щелчок по иконке - Открыть новое окно приложения с привилегиями администратора
    Shift + щелчок правой кнопкой на иконке - Показать меню приложения
    Shift + щелчок правой кнопкой на группе иконок - Показать меню, восстановить все / cвернуть все / Закрыть все
    Ctrl + щелчок по группе икнонок - Развернуть все окна группы

    10 июня 2011 г.

    oracle: Слияние свободных экстентов в табличном пространстве

    Это относится к табличным пространствам управляемых по словарю.

    В процессе работы БД бывает такое, что несколько свободных экстентов идут друг за другом в таком случае их можно слить в один с помощью ALTER TABLESPACE tbs_name COALESCE

    -- оценить фрагментацию

    -- Если FSFI около 100 - фрагментации  нет
    -- Если FSFI ближе к 0 - фрагментация есть
    SELECT TABLESPACE_NAME,
         SQRT(MAX(BLOCKS)/SUM(BLOCKS))+
         (100/SQRT(SQRT(COUNT(BLOCKS)))) FSFI
        FROM DBA_FREE_SPACE
        GROUP BY TABLESPACE_NAME
        ORDER BY 1;

    -- Посмотреть фрагментацию табличного пространства USERS (вариант 1)
    SELECT   'free space' owner, '   ' OBJECT, file_id, block_id, blocks
        FROM dba_free_space
       WHERE tablespace_name = 'USERS'
    UNION
    SELECT   SUBSTR (owner, 1, 20), SUBSTR (segment_name, 1, 32), file_id,
             block_id, blocks
        FROM dba_extents
       WHERE tablespace_name = 'USERS'
    ORDER BY 3, 4; 

    -- Посмотреть фрагментацию табличного пространства USERS (вариант 2)
    SELECT a.tablespace_name, a.file_id, a.block_id, a.blocks, b.block_id
      FROM dba_free_space a, dba_free_space b
     WHERE a.tablespace_name = 'USERS'
       AND b.tablespace_name = 'USERS'
       AND a.tablespace_name = b.tablespace_name
       AND a.file_id = b.file_id
       AND a.block_id + a.blocks = b.block_id;


    -- выполнить слияние свободных экстентов
    alter tablespace users coalesce;

    9 июня 2011 г.

    oracle: Index Scans

    http://aguppi.blogspot.com/2011/06/oracle-access-path.html
    Что такое индекс oracle: Index

    Типы Index Scans:

    • Index Unique Scans
    • Index Range Scans
    • Index Range Scans Descending
    • Index Skip Scans
    • Full Scans
    • Fast Full Index Scans
    • Index Joins
    • Bitmap Joins


    Index Unique Scans

    Возвращает один rowid.
    Происходит, если выражение использует индекс, который содержит ограничение UNIQUE или PRIMARY KEY, которые гарантирую что будет возвращена только одна строка.

    Hints
    /*+ INDEX( tab_name idx1_name idx2_name ...) */

    Этот хинт указывает оптимизатору использывать индекс, но не определённый путь индексного доступа.
    Обычно не нужно указывать хинт для Index Unique Scans. Но если используем db link или таблица мала и оптимизатор выбирает Full Table Scan, то можно указать хинт.

    oracle: Rowid Scans

    http://aguppi.blogspot.com/2011/06/oracle-access-path.html


    • Rowid определяет datafile и block, который содержит выбранную строку.
    • Это быстрейший способ получить строку, поскольку rowid прямо указывает на расположение строки.
    • Oracle получает rowid из выбранных с помощью конструкции WHERE либо с помощью index scan строк. Далее находит каждую выбранную строку таблицы с помощью rowid.

    Когда оптимизатор выбирает Rowid Scans

    Обычно Rowid Scans это второй шаг после получения rowid из индекса.
    Но если индекс содержит все столбцы возвращаемые выражением, то Rowid Scans не выполняется, т.к. все нужные данные уже находятся после index scan.

    oracle: HWM

    High Water Mark (HWM)


    • Отметка для таблицы максимального уровня блоков, которые были когда либо заполнены.
    • Ниже HWM находятся блоки. которые имеют данные или когда то имели их.
    • Выше HWM находятся никогда не использовавшиеся блоки.
    • HWM хранится в DBA_TABLES.BLOCKS.
    • HWM используется как конечный маркер(блок), который нужно прочитать при Full Table Scans.
    • HWM сбрасывается когда таблица dropped или truncate.

    For example, consider a table that had a large number of rows in the past. Most of the rows have been deleted, and now most of the blocks under the high water mark are empty. A full table scan on this table exhibits poor performance because all the blocks under the high water mark are scanned.

    oracle: Full Table Scans

    http://aguppi.blogspot.com/2011/06/oracle-access-path.html
    • Читает все строки таблицы ниже HWM .
    • Оптимален для получения большого количества данных из таблицы.
    • Блоки читаются последовательно, поэтому можно настроить I/O, чтобы за раз считывалось несколько блоков. Настраиваем параметр инициализации DB_FILE_MULTIBLOCK_READ_COUNT.
    • Каждый блок читается только один раз.
    • Если есть условия, то запрос отбрасывает строки не попадающие под условия.
    Когда оптимизатор использует Full Table Scans

    • Отсутствие индекса, когда нет подходящего для запроса индекса.
    • Большое кол-во данных, когда оптимизатор предполагает, что запрос вернёт большинство строк таблицы.
    • Маленькая таблица, если дешевле прочитать всю таблицу, чем использовать индекс.
    • High Degree of Parallelism. A high degree of parallelism for a table skews the optimizer toward full table scans over range scans. Examine the DEGREE column in ALL_TABLES for the table to determine the degree of parallelism.
    Hints
    Чтобы принудительно использовать Full Table Scans используются хинты.
    /*+ FULL(tab_name) */

    SELECT /*+ FULL(e) */ employee_id, last_name
      FROM employees e
      WHERE last_name LIKE :b1;


    2 июня 2011 г.

    oracle: access path (путь доступа)

    The access path determines the number of units of work required to get data from a base table. The access path can be a table scan, a fast full index scan, or an index scan.

    Full Table Scans
    Rowid Scans
    Index Scans
    Cluster Scans
    Hash Scans
    Sample Table Scans 

    oracle: Селективность

    Selectivity


    The first measure, selectivity, represents a fraction of rows from a row set. The row set can be a base table, a view, or the result of a join or a GROUP BY operator. The selectivity is tied to a query predicate, such as last_name = 'Smith', or a combination of predicates, such as last_name = 'Smith' AND job_type = 'Clerk'. A predicate acts as a filter that filters a certain number of rows from a row set. Therefore, the selectivity of a predicate indicates how many rows from a row set will pass the predicate test. Selectivity lies in a value range from 0.0 to 1.0. A selectivity of 0.0 means that no rows will be selected from a row set, and a selectivity of 1.0 means that all rows will be selected.


    The estimator uses an internal default value for selectivity, if no statistics are available. Different internal defaults are used, depending on the predicate type. For example, the internal default for an equality predicate (last_name = 'Smith') is lower than the internal default for a range predicate (last_name > 'Smith'). The estimator makes this assumption because an equality predicate is expected to return a smaller fraction of rows than a range predicate.


    When statistics are available, the estimator uses them to estimate selectivity. For example, for an equality predicate (last_name = 'Smith'), selectivity is set to the reciprocal of the number n of distinct values of last_name, because the query selects rows that all contain one out of n distinct values. If a histogram is available on the last_name column, then the estimator uses it instead of the number of distinct values. The histogram captures the distribution of different values in a column, so it yields better selectivity estimates. Having histograms on columns that contain skewed data (in other words, values with large variations in number of duplicates) greatly helps the CBO generate good selectivity estimates.

    1 июня 2011 г.

    oracle: OPTIMIZER_MODE (режим оптимизации)

    OPTIMIZER_MODE Initialization Parameter

    The OPTIMIZER_MODE initialization parameter establishes the default behavior for choosing an optimization approach for the instance. The possible values and description are listed in Table 1-2.
    Table 1-2  OPTIMIZER_MODE Parameter Values
    Value Description
    CHOOSE
    The optimizer chooses between a cost-based approach and a rule-based approach, depending on whether statistics are available. This is the default value.
    • If the data dictionary contains statistics for at least one of the accessed tables, then the optimizer uses a cost-based approach and optimizes with a goal of best throughput.
    • If the data dictionary contains only some statistics, then the cost-based approach is still used, but the optimizer must guess the statistics for the subjects without any statistics. This can result in suboptimal execution plans.
    • If the data dictionary contains no statistics for any of the accessed tables, then the optimizer uses a rule-based approach.
    ALL_ROWS
    The optimizer uses a cost-based approach for all SQL statements in the session regardless of the presence of statistics and optimizes with a goal of best throughput (minimum resource use to complete the entire statement).
    FIRST_ROWS_n
    The optimizer uses a cost-based approach, regardless of the presence of statistics, and optimizes with a goal of best response time to return the first n number of rows; n can equal 1, 10, 100, or 1000.
    FIRST_ROWS
    The optimizer uses a mix of cost and heuristics to find a best plan for fast delivery of the first few rows.
    Note: Using heuristics sometimes leads the CBO to generate a plan with a cost that is significantly larger than the cost of a plan without applying the heuristic. FIRST_ROWS is available for backward compatibility and plan stability.
    RULE
    The optimizer chooses a rule-based approach for all SQL statements regardless of the presence of statistics.

    27 мая 2011 г.

    oracle: users (пользователи)

    1. Назначить default and temporary tablespace
    alter user guppi default tablespace users
    temporary tablespace temp;


    2. Создать пользователя
    CREATE USER user_name
      IDENTIFIED by password
      DEFAULT TABLESPACE tbs_user
      TEMPORARY TABLESPACE TEMP;


    19 мая 2011 г.

    oracle: сессии (V$SESSION, V$SESS_IO, V$ACCESS, V$SESSTAT)


    --
    -- SQL-команды, выполняемые в каждом сеансе
    -- v$session, v$sqltext
    --
    select a.sid,
           a.username,
           s.sql_text
    from v$session a, v$sqltext s
    where a.sql_hash_value = s.hash_value
       and a.sql_address    = s.address
       and a.username is not null
    order by a.username, a.sid, s.piece;

    oracle: объекты закреплённые/незакреплённые в library cache

    V$DB_OBJECT_CACHE

    select * from v$db_object_cache;

    kept = "YES" - объект закреплён в памяти
    kept = "NO"  - объект не закреплён в памяти

    18 мая 2011 г.

    oracle: % попадания в library cache

    % попадания SQL запросов и PL/SQL в library cache:

    select * from v$librarycache;

    pinhitratio - % попаданий при выполнении (95%)
    reload hit ratio - % попаданий при загрузке (99%). Т.е. число повторных загрузок не должно превышать 1%. Под повторной загрузкой подразумевается ситуация, когда команда уже была разобрана ранее, но не удержалась в памяти из-за загрузки других команд. Тогда тело команды выкидывается, заголовок остаётся. То же самое происходит, когда меняется план выполнения команды.

    oracle: % попадания в кэш словаря

    Чтобы узнать насколько часто запросы к данным словаря удовлетворяются из кэша, нужно использовать представление V$ROWCACHE .

    select * from v$rowcache;
    select sum(gets), sum(getmisses), (1 - (sum(getmisses)/ (sum(gets) + sum(getmisses))))*100 hit_rate from v$rowcache;

    oracle: использование V$DB_CACHE_ADVICE

    Прогнозирует как изменение размера кэша данных скажется на проценте попадания в кэш:

    select * from v$db_cache_advice;

    Чтобы это работало параметр DB_CACHE_ADVICE дожнен иметь значение ON.

    oracle: посмотреть лицензионные ограничения базы данных

    select * from v$license;

    если 0 - ограничений нет


    oracle: посмотреть версию базы данных

    select * from v$version;

    BANNER
    ================================================
    Oracle9i Enterprise Edition Release 9.2.0.5.0 - 64bit Production
    PL/SQL Release 9.2.0.5.0 - Production
    CORE    9.2.0.6.0    Production
    TNS for IBM/AIX RISC System/6000: Version 9.2.0.5.0 - Production
    NLSRTL Version 9.2.0.5.0 - Production
     

    oracle: посмотреть запросы, по которым строятся V$ и DBA представления

    Список представлений:

    select * from dict;
    select * from v$fixed_table;

    Текст запроса, по которым строятся представления:

    select * from dba_views;
    select * from v$fixed_view_definition;

    oracle: список установленных компонентов

    Если надо узнать поддерживает ли инстанс партицирование, RAC и другие фичи,
    делаем селект:

    select * from v$option;

    15 мая 2011 г.

    oracle: Индексы по внешним ключам

    Внешние ключи нужно индексировать.
    Не проиндексированные внешние ключи являются, как правило, наиболее частой причиной возникновения взаимных блокировок, поскольку изменение в главной таблице ( UPDATE по всем столбцам строки, такие апдейты любят делать средства автоматической генерации SQL) или удаление записи из главной таблицы приводит в этом случае к блокированию всей подчиненной таблицы (никакие изменения в таблице внешнего ключа будут невозможны, пока транзакция не завершится). При этом блокируется намного больше строк, чем нужно, и снижается параллелизм.

    Не проиндексированный внешний ключ плох еще и в следующих случаях:

    - При наличии конструкции ON DELETE CASCADE. Например, таблица ЕМР является подчиненной для таблицы DEPT. Оператор DELETE FROM DEPT WHERE DEPTNO = 10 должен вызвать каскадное удаление в таблице ЕМР. Если столбец DEPTNO в таблице ЕМР не проиндексирован, для этого придется выполнить полный просмотр таблицы ЕМР. Этот полный просмотр нежелателен; кроме того, при удалении большого количества строк из главной таблицы подчиненная будет каждый раз полностью просматриваться.

    - При выполнении запроса от главной таблицы к подчиненной. Рассмотрим пример с таблицами EMP/DEPT еще раз. Очень часто таблица ЕМР запрашивается с условием по столбцу DEPTNO. Если приходится часто выполнять запрос:
    select * from dept, emp
    where emp.deptno = dept.deptno
    and dept.dname = :X;
    для генерации отчета или других целей, окажется, что отсутствие индекса существенно замедляет выполнение запросов.

    oracle: Synonym (Синонимы)

    Синоним (Synonym) – это альтернативное имя (псевдоним) для объекта схемы. Если для какого либо объекта базы данных Oracle существует синоним, то к объекту из SQL запроса можно обращаться либо по его настоящему имени, либо по синониму. Так же они обеспечивают некоторый уровень безопасности, поскольку скрывают имя объекта и его владельца, а так же делают прозрачным местоположение удаленных объектов распределенных баз данных.

    Синонимы позволяют переименовывать и перемещать базовые объекты. При том переопределяется только синоним, а приложение не требует никаких модификаций.

    Различают два типа синонимов:

        Частный (PRIVATE)- синонимы содержаться в схеме конкретного пользователя и доступны только самому пользователю, и тем, кому он предоставил соответствующие права доступа.
        Общий (PUBLIC)- этими синонимами владеет специальная группа пользователей – PUBLIC, в результате чего эти синонимы доступны всем пользователям базы данных.

    14 мая 2011 г.

    oracle: Мониторинг использования пространства индексами

    Со временем эффективность использования пространства индексом может быть утрачена. Особенно это касается при интенсивной работе с данными, частых процедурах вставки, удаления или изменения.

    Можно провести анализ используемого индексом пространства. 
    Для этого анализируется структура индекса, с помощью SQL оператора ANALYZE INDEX … VALIDATE STRUCTURE, а затем запрашивается представление INDEX_STATS:

    -- анализируем (dbms_stats не подходит)
    ANALYZE INDEX object_id_idx  VALIDATE STRUCTURE;
    -- смотрим
    SELECT PCT_USED FROM INDEX_STATS WHERE NAME = 'имя_индекса';

    Note: ANALYZE INDEX … VALIDATE STRUCTURE ставит блокировку на таблицу, по которой построен индекс.

    oracle: Мониторинг использования индексов

    В Oracle существует возможность мониторинга использования индексов.
    Это необходимо для определения его использования. В результате можно удалить неиспользуемые индексы и сократить расход ресурсов.

    -- Пример начала мониторинга индекса:
    ALTER INDEX ALL_ORACLE_EVENT_NO MONITORING USAGE;

    -- Для прекращения мониторинга указывается NOMONITORING, как показано ниже:
    ALTER INDEX ALL_ORACLE_EVENT_NO NOMONITORING USAGE;

    Кроме того, можно выполнить запрос к представлению V$OBJECT_USAGE, чтобы узнать, использовался требуемый индекс или нет. В представлении есть столбец USED, который принимает значение YES или NO, в зависимости от того, использовался ли индекс во время проведения мониторинга. Еще представлен столбец времени начала и окончания мониторинга и столбец указывающий состояние мониторинга, проводиться он на данный момент или нет, это столбец MONITORING, принимающий значение YES или NO.

    Каждый раз при указании MONITORING USAGE или NOMONITORING USAGE, значения столбцов в представлении V$OBJECT_USAGE изменяются для соответствующего индекса. Информация о предыдущих запусках удаляется или сбрасывается. При указании NOMONITORING USAGE записывается время окончания.

    oracle: Удаление индексов

    Чтобы иметь возможность удалять индексы, индекс должен находиться в вашей схеме, или если он находить в другой схеме, то пользователю необходима системная привилегия – DROP ANY INDEX.

    Основные причины удаления индекса:

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

    После удаления индекса все экстенты его сегмента возвращаются в табличное пространство и становятся доступными для использования другими объектами.

    В зависимости от способа создания индекса, создан ли он явно оператором CREATE INDEX, или неявно при определении ограничений целостности, зависит и способ его удаления. 

    Если индекс создан через CREATE INDEX, его можно удалить, используя команду DROP INDEX, как показано в примере:

    DROP INDEX EVENT_NO;

    Для удаления индекса связанного с ограничением целостности необходимо удалить само ограничение или отключить его. 

    Нельзя удалить индексы, связанные с ограничением целостности – UNIQUE или PRIMARY KEY.

    oracle: Перестройка индексов

    При перестройке индекса существующий индекс используется в качестве источника данных. Такое повторное создание индекса позволяет изменить параметры хранения индекса или перемещать его в новое табличное пространство. Такая перестройка позволяет попутно устранить фрагментацию внутри блока. По сравнению с удалением индекса и повторным созданием, используя CREATE INDEX, повторное создание существующего индекса обеспечивает большую производительность.

    -- перестроим индекс:
    ALTER INDEX EVENT_NO REBUILD;

    Предложение REBUILD должно следовать непосредственно за именем индекса, предваряя все другие параметры. Его нельзя использовать вместе с DEALLOCATE UNUSED.

    -- перестроим индекс в оперативном режиме:
    ALTER INDEX EVENT_NO REBUILD ONLINE;

    Такое перестроение можно делать только в том случае, если есть такая возможность. Если вдруг случается, что необходимого пространства для перестроения индекса, то можно произвести слияние данных в индексных группах. Слияние можно выполнять в оперативном режиме.

    oracle: Создание больших индексов

    При создании очень большого индекса стоит подумать о выделении временного табличного пространства большого размера для создания индекса. Далее опишем процедуру создания большого индекса:
    1. Создайте временное табличное пространство, используя конструкцию CREATE TABLESPACE или CREATE TEMPORARY TABLESPACE.
    2. С помощью параметра TEMPORARY TABLESPACE конструкции ALTER USER назначьте созданное табличное пространство как новое временное табличное пространство.
    3. Создайте индекс с помощью CREATE INDEX.
    4. Верните временное табличное пространство пользователю, выполнив ALTER USER … TEMPORARY TABLESPACE. И затем удалите ненужное табличное пространство, выполнив DROP TABLESPACE.
    Возникает вопрос, а почему нельзя было использовать уже существующее табличное пространство, и как следствие избежать создания, удаления, модификации пользователя?
    Описанная выше процедура может помочь избежать проблем с расширением обычного, и как правило, разделяемого временного табличного пространства до слишком большого размера, что может сказаться на производительности системы.

    oracle: Создание индексов связанных с ограничением целостности

    Oracle обеспечивает выполнение ограничения целостности UNIQUE или PRIMARY KEY для таблицы, создавая уникальный индекс для уникального или первичного ключа. Этот индекс создается автоматически, когда включается ограничение целостности. Когда выполняется CREATE TABLE или ALTER TABLE, для создания индекса не надо предпринимать никаких действий, но при желании можно указать предложение USING INDEX, чтобы контролировать его создание.
    Чтобы включить ограничение целостности UNIQUE или PRIMARY KEY, создавая таким образом связанный с ним индекс, владелец таблицы должен иметь квоту табличного пространства, где будет храниться этот индекс, или системную привилегию UNLIMITED TABLESPACE. Индекс связанный с ограничением целостности всегда получает имя этого ограничения, если вы не укажете иное.

    oracle: Уникальные и неуникальные индексы

    Индексы могут быть уникальными или неуникальными.

    Уникальные индексы гарантируют отсутствие двух строк в таблице с одинаковыми значениями в ключевом столбце или столбцах.

    Неуникальные индексы не накладывают никаких ограничений на значения столбцов.

    -- Для создания уникального индекса используется SQL оператор – CREATE UNIQUE INDEX.
    CREATE UNIQUE INDEX ANIKNAME_UNIQUE_IDX ON ALL_ORACLE_ADMIN (ANIKNAME)
        TABLESPACE ALL_ORACLE_IDX;

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

    oracle: Выбор столбцов для индексирования

    Существует ряд рекомендаций по выбору столбцов которые стоит индексировать:
    • Создавать индекс рекомендуется, если часто выбираются данные, составляющие примерно 15% от данных таблицы. Этот процент может значительно варьироваться в зависимости от относительной скорости просмотра таблицы и от степени кластеризации данных строки по отношению к ключу индекса. Чем быстрее просматривается таблица, тем ниже процент. Чем больше кластеризация данных строки, тем процент выше.
    • Для повышения производительности соединений нескольких таблиц индексируйте столбцы, которые используются в соединении.
      Заметка: Для первичных и уникальных ключей индексы создаются автоматически, но при желании можно создать индексы и для внешних ключей.
    • Для маленьких таблиц индексы не требуются. Если запрос занимает долгое время, то возможно количество данных в таблице значительно возросло.

    oracle: Indexes and NULL

    Индексы и NULL

    Индексы на основе В*-дерева, кроме индекса кластера, не содержат записей для NULL, а индексы на основе битовых карт и индекс кластера - имеют.

    Чтобы запрос select * from T where x is null; использовал индекс нужно, чтобы хотя бы один столбец в индексе имел ограничение NOT NULL.

    Например:
    -- создаём таблицу
    create table t (x int, у int NOT NULL);
    -- создаём индекс
    create unique index t_idx on t(x,y);
    -- выполняем запрос, он будет использовать индекс, т.к. у int NOT NULL 
    select * from t where x is null;

    oracle: Indexes and Views

    Индексы и представления

    Чтобы проиндексировать представление, надо просто проиндексировать базовые таблицы.

    Представление -  это сохраненный запрос. Сервер Oracle будет подставлять в текст запроса к представлению определение самого представления. Представления обеспечивают удобство для конечных пользователей, оптимизатор же работает с запросом к базовым таблицам. Любые индексы, которые могли бы использоваться в запросе, непосредственно обращающемся к базовым таблицам, будут учтены при использовании представления.