traditional relational databases architecture

60
Group Technology and Operations Deutsche Bank Traditional relational databases architecture Dmitry Remizov

Upload: deutschebank

Post on 18-Dec-2014

470 views

Category:

Software


2 download

DESCRIPTION

Traditional relational databases architecture

TRANSCRIPT

Page 1: Traditional relational databases architecture

Group Technology and Operations Deutsche Bank

Traditional relational

databases architecture Dmitry Remizov

Page 2: Traditional relational databases architecture

Dmitry Remizov

14 August 2014 Deutsche Bank

Я собираюсь рассказать некоторые базовые вещи об архитектуре

традиционных баз данных на примере 2х наиболее ярких

представителей систем этого класса, а именно - Oracle и Microsoft

SQL. Выбор обусловлен тем, что это, во-первых, лидирующие

системы в своих сегментах, во-вторых, они исповедуют весьма

различные базовые идеологии. В основном по историческим

причинам.

Начнем, однако, с того, зачем нужны базы данных вообще. Почему

бы не писать просто в плоские файлы. Действительно есть класс

задач, для которого это вполне релевантный подход (логи и т.п.).

Однако довольно часто нам надо писать что-то консистентно и из

многих потоков одновременно.

И вот этим-то и занимаются реляционные базы данных.

Agenda

Page 3: Traditional relational databases architecture

Dmitry Remizov

14 August 2014 Deutsche Bank

Несмотря на все исторические различия, многие архитектурные

решения оказались весьма сходными. Хотя, конечно, есть и

существенные различия.

Начнем с того, что Oracle «версионник», а MSSQL «блокировочник».

Расшифруем немного этот жаргон:

•«Блокировочник» означает, что «писатель» может заблокировать

«читателей», 2 пишущие сессии должны логически лочить друг

друга, если имеют дело с одной и той же строкой (данными).

•«Версионник» вместо блокировки читателя возвращает клиенту

«предыдущую версию правды». На какой момент это отдельный

вопрос.

Два подхода

Page 4: Traditional relational databases architecture

Dmitry Remizov

14 August 2014 Deutsche Bank

Из чего состоит реляционная база данных:

•Процессы OS

•Структуры в памяти

•Файлы на файловой системе

На следующем слайде мы увидим некоторую обзорную картинку

основных компонентов Oracle и MSQL

Архитектура

Page 5: Traditional relational databases architecture

Dmitry Remizov

14 August 2014 Deutsche Bank

MSSQL

Buffer pool

TLogs

Memory structures and processes

Oracle

Buffer Cache

Online redo logs

MSSQL

Buffer Pool

TLogs

Page 6: Traditional relational databases architecture

Dmitry Remizov

14 August 2014 Deutsche Bank

MSSQL взаимодействие базы данных с клиентом

Page 7: Traditional relational databases architecture

Dmitry Remizov

14 August 2014 Deutsche Bank

Сравнение основных «фоновых» процессов

Page 8: Traditional relational databases architecture

Dmitry Remizov

14 August 2014 Deutsche Bank

Oracle MSSQL

Buffer Cache Buffer Pool

Redo log buffer Log cache

Shared Pool Procedural cache

Сравнение основных областей памяти

Page 9: Traditional relational databases architecture

Identifier Deutsche Bank Dmitry Remizov

14 August 2014

ACID

В незапамятные времена была определена некая модель, которой

должны удовлетворять все реляционные базы данных. Это 4

базовых принципа и по начальным буквам эта модель называется

ACID. Вкратце:

Atomicity – транзакция не может быть завершена частично.

Consistency – база данных консистентна в начале и конце каждой

транзакции

Isolation – транзакция не видит изменения произведенные другой

незавершенной транзакцией

Durability – закоммиченная транзакция «переживает» крах системы

Все реляционные базы в меру своих возможностей пытаются

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

низкоуровневые механизмы.

Page 10: Traditional relational databases architecture

Identifier Deutsche Bank Dmitry Remizov

14 August 2014

Transaction logs

Рассмотрим один из важнейших механизмов обеспечения ACID (а

именно A & D частей) - подсистема transaction log’ов. В MSSQL это

одна подсистема – TLOG + LogWriter, которая обепечивает

возможность commit/rollback (Atomicity) и восстанавливаемость

системы (Durability).

В Oracle немного сложнее - 2 тесно связанных подсистемы REDO

and UNDO. REDO для Durability и UNDO для Atomicity (и еще для

обеспечения много-версионного чтения).

Page 11: Traditional relational databases architecture

Identifier Deutsche Bank Dmitry Remizov

14 August 2014

WAL

Несколько слов зачем вообще нужны логи транзакций.

Современные базы данных - это в основном большие (иногда

распределенные кэши) с конкурентным доступом, и все, что вы

делаете с данными в основном происходит в оперативной памяти

(есть исключения), однако нам надо обеспечить механизм

восстановления данных при крахе системы.

Для этого все изменения в системе пишутся в отдельный лог,

который при commit’е синхронно сохраняется на файловую систему.

И в Oracle и в MSSQL реализован механизм т.н. WAL ( Write ahead

logging), т.е. все данные, которые вы записываете, сначала пишутся

в лог (точнее в лог буфер, который постоянно скидывается на диск)

и только в момент commit’a мы окончательно синхронизируем лог

буфер и лог файлы (на момент коммита). И только после того, как

мы записали лог, мы реально изменяем данные (сначала в памяти,

а потом когда-нибудь на диске).

Page 12: Traditional relational databases architecture

Identifier Deutsche Bank Dmitry Remizov

14 August 2014

MSSQL – transaction log

SQL Server помечает каждую запись в лог файле используя Logical

Sequence Number (LSN). Это монотонно возрастающее число,

более свежие записи имеют выше LSN. Log records связанные с

данной транзакцией пролинкованы в LSN chain. Log records

связаны в обратную цепочку (backword chained) – каждый log record

сохраняет ссылку на предыдущий в той же транзакции. Это

позволяет SQLServer делать rollback применяя каждый log record в

обратном порядке.

Важная концепция «active log». Начало active log’a - это старейший

LSN из всех открытых транзакций. Конец active log’a - это

наивысший записанный LSN в системе.

Page 13: Traditional relational databases architecture

Identifier Deutsche Bank Dmitry Remizov

14 August 2014

Rollback and recovery в MSSQL

В случае краха системы MSSQL последовательно накатывает

transaction log и затем откатывает незакоммиченные транзакции.

В случае rollback - использует «Log records связаны в обратную

цепочку (backword chained)» и применяет все log records в обратном

порядке.

Page 14: Traditional relational databases architecture

Identifier Deutsche Bank Dmitry Remizov

14 August 2014

В Oracle все немного сложнее

Любые изменения в блоке данных сразу же генерят инструкции по

их отмене, которые записываются в UNDO. И изменения в дата

блоках и в UNDO сегменте тут же записываются в REDO log.

На самом деле вначале записываются эти инструкции в REDO, а

затем изменения происходят в UNDO и дата блоке.

См. слайд.

Page 15: Traditional relational databases architecture

Identifier Deutsche Bank Dmitry Remizov

14 August 2014

Oracle: REDO and UNDO

1. Создаем «change vector» для UNDO record

2. Создаем «change vector» для Data block

3. Комбинируем эти 2 «change vector» в “redo record” и записываем в redo log (buffer).

4. Записываем «undo record» в UNDO block

5. Меняем data block.

Page 16: Traditional relational databases architecture

Identifier Deutsche Bank Dmitry Remizov

14 August 2014

Почему в Oracle 2 подсистемы, почему не только REDO

REDO нужен для обеспечения recoverability

Позволяет записывать только изменения в данных, избавляя от необходимости

синхронно записывать измененные дата блоки. Теоретически мы можем

прокрутить все изменения с момента создания «пустой» базы данных и получить

текущее состояние. Похожие подходы есть во многих (нереляционных в том

числе) базах данных, например KDB.

UNDO нужен для обеспечения согласованности по чтению и rollback’ов

Если бы мы пытались это сделать при помощи REDO, нам бы пришлось

иметь многосвязный REDO log. Сейчас это простой последовательный по времени

лог. Иначе возникла бы необходимость иметь связанность по:

• object_id – обьектам, чтобы обеспечить согласованное чтение;

• SCN – “номер транзакции” для обеспечения rollback.

В MSSQL, так как это изначально «блокировочник», согласованное чтение было не

очень актуально: читатели блокировались писателями, а rollback как раз

обеспечивается пролинковкой внутри TLOG’а (см. Log records связаны в обратную

цепочку (backward chained)).

А в новом режиме snapshot есть подобие UNDO, реализованное в tempDB для

обеспечения согласованного чтения.

16

Page 17: Traditional relational databases architecture

Identifier Deutsche Bank Dmitry Remizov

14 August 2014

Типичный “REDO record”

REDO RECORD - Thread:1 RBA: 0x00036f.00000005.008c LEN: 0x00f8 VLD: 0x01

SCN: 0x0000.03ee485a SUBSCN: 1 03/13/2011 17:43:01

CHANGE #1 TYP:0 CLS:36 AFN:2 DBA:0x0080009a SCN:0x0000.03ee485a SEQ: 4 OP:5.1

CHANGE #2 TYP:0 CLS: 1 AFN:11 DBA:0x02c0018a SCN:0x0000.03ee485a SEQ: 2 OP:11.5

Видно что типичный REDO состоит из пар инструкций по

изменению UNDO и data block’a.

Page 18: Traditional relational databases architecture

Identifier Deutsche Bank Dmitry Remizov

14 August 2014

UNDO record internal structure uba: 0x00c38375.04c4.2b ctl max scn: 0x0000.002b7cc5 prv tx scn: 0x0000.002b7cc6

txn start scn: scn: 0x0000.002b84d4 logon user: 47

prev brb: 12813167 prev bcl: 0

KDO undo record:

KTB Redo

op: 0x03 ver: 0x01

compat bit: 4 (post-11) padding: 1

op: Z

KDO Op code: URP row dependencies Disabled

xtype: XA flags: 0x00000000 bdba: 0x01800bb3 hdba: 0x01800bb2

itli: 2 ispac: 0 maxfr: 4858

tabn: 0 slot: 0(0x0) flag: 0x2c lock: 0 ckix: 12

ncol: 3 nnew: 1 size: 308

col 1: [311]

31 31 31 31 31 31 31 31 31 31 31 31 31 31 31 31 31 31 31 31 31 31 31 31 31

31 31 31 31 31 31 31 31 31 31 31 31 31 31 31 31 31 31 31 31 31 31 31 31 31

31 31 31 31 31 31 31 31 31 31 31 31 31 31 31 31 31 31 31 31 31 31 31 31 31

31 31 31 31 31 31 31 31 31 31 31 31 31 31 31 31 31 31 31 31 31 31 31 31 31

31 31 31 31 31 31 31 31 31 31 31 31 31 31 31 31 31 31 31 31 31 31 31 31 31

31 31 31 31 31 31 31 31 31 31 31 31 31 31 31 31 31 31 31 31 31 31 31 31 31

31 31 31 31 31 31 31 31 31 31 31 31 31 31 31 31 31 31 31 31 31 31 31 31 31

31 31 31 31 31 31 31 31 31 31 31 31 31 31 31 31 31 31 31 31 31 31 31 31 31

31 31 31 31 31 31 31 31 31 31 31 31 31 31 31 31 31 31 31 31 31 31 31 31 31

31 31 31 31 31 31 31 31 31 31 31 31 31 31 31 31 31 31 31 31 31 31 31 31 31

31 31 31 31 31 31 31 31 31 31 31 31 31 31 31 31 31 31 31 31 31 31 31 31 31

31 31 31 31 31 31 31 31 31 31 31 31 31 31 31 31 31 31 31 31 31 31 31 31 31

31 31 31 31 31 31 31 31 31 31 31

+++++++++++ Next block not in extent map - rollback segment has been shrunk.

+ WARNING + Block dba (file#, block#): 0,0x00000000

Я про’update’ил одно поле

в таблице, видно что

записывается только

операция по изменению, а

не “before image”

update FFF set f1='ZZZZZ'

where rownum =1;

Первоначальное

содержимое поля f1:

11111…1111 (ASCII code

31).

Page 19: Traditional relational databases architecture

Identifier Deutsche Bank Dmitry Remizov

14 August 2014 19

Некоторые коды операций (из презентации Julian Duke)

Row operations generate layer 11 redo

Opcodes include:

Opcode Mnemonic Description

11.2 IRP Insert Single Row

11.3 DRP Delete Single Row

11.4 LKR Lock Row

11.5 URP Update Row

11.6 ORP Chained Row

11.9 CKI Cluster key index

11.10 SKL Set cluster key pointers

11.11 QMI Insert Multiple Rows

11.12 QMD Delete Multiple Rows

Page 20: Traditional relational databases architecture

Identifier Deutsche Bank Dmitry Remizov

14 August 2014 20

Multi Row Update

Redo Statements

COMMIT 5.4

REDO #3

UNDO #3

11.5

5.1

UNDO #2

REDO #2

5.1

11.5

REDO #1

UNDO #1

HEADER

11.5

5.1

5.2 -- T1 contains 3 rows

UPDATE t1 SET c2 = c2 + 1;

COMMIT;

Page 21: Traditional relational databases architecture

Identifier Deutsche Bank Dmitry Remizov

14 August 2014 21

Global Temporary Tables

Redo Statements

COMMIT 5.4

REDO #3

UNDO #3

11.2

5.1

UNDO #2

REDO #2

5.1

11.2

UNDO #1

HEADER

REDO #1 11.2

5.1

5.2

COMMIT;

-- Statement #1

INSERT INTO t1 VALUES (1);

-- Statement #2

INSERT INTO t1 VALUES (2);

-- Statement #3

INSERT INTO t1 VALUES (3);

Page 22: Traditional relational databases architecture

Identifier Deutsche Bank Dmitry Remizov

14 August 2014

Различия Oracle и SQL Server

Oracle:

2 подсистемы: REDO & UNDO

REDO – очень простая, служит для восстановления

после сбоев, i.e. durability.

UNDO – гораздо сложнее, обеспечивает rollback’и,

согласованное чтение, i.e. atomicity, isolation

Page 23: Traditional relational databases architecture

Identifier Deutsche Bank Dmitry Remizov

14 August 2014

Как оптимизировать «recovery» или зачем нужен CheckPoint process

Как было сказано на предыдущем слайде, возможно получить текущее

состояние базы накатывая transaction логи (REDO логи) «с начала

времен», однако это не выглядит разумной стратегией.

И здесь вступает в действие другой процесс - checkpoint (называется

абсолютно одинаково и в Oracle и в MSSQL).

Однако осуществляет сheckpoint в основном DWR0-9 (database writer)

процесс, он записывает все грязные блоки в дата файлы.

Вспомогательный CKPT процесс обновляет заголовки дата файлов и

control file.

Задачей checkpoint процесса является «асинхронная» синхронизация

данных в памяти с данными в дата файлах на диске (в Oracle >10

разнообразных checkpoint процессов и каждый содержит свою цепочку

буферных блоков - checkpoint queue).

Page 24: Traditional relational databases architecture

Identifier Deutsche Bank Dmitry Remizov

14 August 2014

Checkpoint

Page 25: Traditional relational databases architecture

Identifier Deutsche Bank Dmitry Remizov

14 August 2014

Еще немного о checkpoint Изначально (до 8.0) существовали только так называемые «нормальные» контрольные

точки, задачей которых было записать «грязные блоки» при переключении online redo

log’ов, что ожидаемо приводило к всплеску активности DBWR в момент такого

переключения.

Поэтому было решено размазать эту активность по времени и ввести алгоритм

«инкрементальной контрольной» точки.

•По мере того, как блоки данных в буферном кэше претерпевают изменения и

становятся “грязными”, процесс DBWR формирует очередь (checkpoint queue) из

связанных в упорядоченный по возрастанию low RBA список этих блоков. Low RBA – это

redo-адрес первого изменения блока, сделавшего его “грязным”.

•В какой-то момент времени DBWR определяет, что один из параметров, управляющий

наступлением инкрементальной контрольной точки, превысил свое пороговое значение.

Начинается выполнение инкрементальной контрольной точки. DBWR

вычисляет target RBA – то значение, до которого он будет осуществлять запись блоков

из checkpoint queue. Этим значением не обязательно будет on disk RBA – то значение,

до которого DBWR сможет безопасно записывать “грязные” буфера из буферного кэша,

так как redo-информация, защищающая эти изменения, уже записана процессом LGWR

в журнальные файлы. DBWR выберет в качестве target RBAзначение, которое вернет

после выполнения инкрементальной контрольной точки значение параметра, ее

вызвавшее, в рамки допустимого. Названия(и суть) параметров довольно сильно

менялись от версии к версии.

Подробнее в замечательной статье Сергея Маркеленкова:

http://www.fors.ru/upload/magazine/03/http_texts/russia_chech_point.html

Page 26: Traditional relational databases architecture

Identifier Deutsche Bank Dmitry Remizov

14 August 2014

МИФ 1ый – Oracle, MSSQL, etc. “умный”

Поэтому может оптимизировать операцию типа:

update TSTLOG2 set …, f1=f1, f2=f2 WHERE rownum <100001;

Где «на всякий случай» перечислены все поля, меняли вы их или не

меняли. Простой экперимент покажет, что это неверно как с точки

зрения DBW, так и LGWR процессов.

С логической точки зрения это операция ровным счетом ничего не

делает (update поля само в себя):

SQL>

SQL> update TSTLOG2 set f1=f1 WHERE rownum

<100001;

100000 rows updated.

Elapsed: 00:00:28.22

SQL> commit;

Commit complete.

Elapsed: 00:00:00.55

SQL>

SQL> AlTER SYSTEM CHECKPOINT;

System altered.

Elapsed: 00:00:20.15

SQL>

Видно что UPDATE часть

выполняется довольно долго (и

генерит большое кол-во redo)

NAME VALUE

---------------------------------------------------------------- ----------

redo size 2894048836

CHECKPOINT тоже нашел большое

кол-во «грязных» блоков чтобы

сбросить их на диск.

Page 27: Traditional relational databases architecture

Identifier Deutsche Bank Dmitry Remizov

14 August 2014

Некоторые операции, которые также вызывают checkpoint или почему мой TRUNCATE длился полчаса. Некоторые операции для своего правильного выполнения должны

синхронизовать состояние buffer cache c datafiles на диске.

Это DROP/TRUNCATE/и direct path операции, проведем простой

экперимент

SQL> UPDATE tstlog set f1=f1;

100000 rows updated.

SQL> commit;

Commit complete.

SQL> select /*+ PARALLEL (t 4) */count(1) from TSTLOG t;

COUNT(1)

----------

100000

SQL> select event, time_waited/100 from v$session_event where sid =

(select sid from v$mystat where rownum=1)

2 order by time_waited desc;

EVENT TIME_WAITED/100

---------------------------------------------------------------- ---------------

SQL*Net message from client 159.6

enq: KO - fast object checkpoint 7.56

PX Deq: Execute Reply 2.85

resmgr:cpu quantum .02

PX Deq: Parse Reply 0

SQL*Net message to client 0

В 1ой сессии мы сгенерили

достаточно большое кол-во грязных

блоков.

Во 2ой провели параллельный

SELECT, к-рый приводит к direct path

read операции.

Видно что мы более 7 секунд ждали

выполнения контрольной точки (из 10

сек общего времени)

Page 28: Traditional relational databases architecture

Identifier Deutsche Bank Dmitry Remizov

14 August 2014

Еще немного о truncate/drop

Воспроизведу рассуждение Таннела Подера.

• Предположим, у нас есть большой буфферный кэш, и мы drop’аем

таблицу A без инициации контрольной точки для «грязных»

буферов.

• Сразу же после этого мы создаем таблицу B, которая

переиспользует только что освобожденное место.

• Через несколько секунд просыпается DBWR, находит «грязные»

буфера и радостно перезаписывает часть содержимого таблицы B.

Конечно, можно было бы предложить чтобы DBRW проверял какие

блоки он скидывает, тот ли это обьект и т.п., но это не слишком

естественно для такого низкоуровнего кода, который работает с

блоками а не обьектами базы данных.

http://blog.tanelpoder.com/2011/07/06/what-is-the-purpose-of-segment-level-checkpoint-

before-droptruncate-of-a-table/

Page 29: Traditional relational databases architecture

Identifier Deutsche Bank Dmitry Remizov

14 August 2014

Миф 2: база данных читает/обрабатывает данные построчно.

На самом деле Oracle и MSSQL обрабатывают данные по блокам:

В MSSQL - 8k блоки

В Oracle 2k,4k,8k.16k,32k блоки (стадартный тоже 8k)

Предположим, что мы решили ускорить наши SELECT’ы и прочитали в SQL

Bible или еще где-нибудь, что для этого надо сжать нашу таблицу. Звучит

разумно: SQL> CREATE TABLE FFF AS SELECT rownum+10000 id,

2 rpad(mod(rownum,3),311,mod(rownum,3)) f1,

3 rpad(mod(rownum,2),330,mod(rownum,2)) f2 from dual

4 connect by level<10001;

Table created.

SQL> CREATE TABLE CCC COMPRESS BASIC AS SELECT rownum+10000 id,

2 rpad(mod(rownum,3),311,mod(rownum,3)) f1,

3 rpad(mod(rownum,2),330,mod(rownum,2)) f2 from dual

4 connect by level<10001;

Table created.

SQL> begin

2 dbms_stats.gather_table_stats(USER,'CCC');

3 dbms_stats.gather_table_stats(USER,'FFF');

4 end;

5 /

SQL> select table_name, blocks from user_tab_statistics where table_name in ('FFF','CCC');

TABLE BLOCKS

----- ----------

CCC 23

FFF 934

Page 30: Traditional relational databases architecture

Identifier Deutsche Bank Dmitry Remizov

14 August 2014

Результаты экперимента

Видим, что данные ужались в 40 раз, ожидаем «взлет» производительности.

Однако произведем замер и увидим, что разница довольно «скромная»

SQL> set arraysize 10

SQL> set autot traceonly

SQL> SELECT * FROM FFF;

10000 rows selected.

Statistics

----------------------------------------------------------

1823 consistent gets

0 physical reads

6698273 bytes sent via SQL*Net to client

11352 bytes received via SQL*Net from client

1001 SQL*Net roundtrips to/from client

10000 rows processed

SQL>

SQL> SELECT * FROM CCC;

10000 rows selected.

Statistics

----------------------------------------------------------

1019 consistent gets

0 physical reads

6638309 bytes sent via SQL*Net to client

11352 bytes received via SQL*Net from client

1001 SQL*Net roundtrips to/from client

10000 rows processed

Page 31: Traditional relational databases architecture

Identifier Deutsche Bank Dmitry Remizov

14 August 2014

Анализ:

Вспоминаем, что база данных читает данные поблочно, и только клиент

запрашивает построчно. В JDBC интерфейсе это определяется параметром

defaultRowPrefetch по умолчанию 10, аналог в sqlplus – arraysize.

Попробуем увеличить arraysize/prefetch.

SQL> set arraysize 5000

SQL> set autot traceonly

SQL>

SQL> SELECT * FROM FFF;

10000 rows selected.

Statistics

----------------------------------------------------------

916 consistent gets

6610449 bytes sent via SQL*Net to client

374 bytes received via SQL*Net from client

3 SQL*Net roundtrips to/from client

10000 rows processed

SQL> SELECT * FROM CCC;

10000 rows selected.

Statistics

----------------------------------------------------------

23 consistent gets

6570445 bytes sent via SQL*Net to client

374 bytes received via SQL*Net from client

3 SQL*Net roundtrips to/from client

10000 rows processed

На этот раз разница в количестве

обработанных блоков

приблизительно соответствует

степени сжатия

Page 32: Traditional relational databases architecture

Identifier Deutsche Bank Dmitry Remizov

14 August 2014

Внутренняя механика обеспечения row level locking and “versioning” в Oracle

Page 33: Traditional relational databases architecture

Identifier Deutsche Bank Dmitry Remizov

14 August 2014

Детали read consistency/мульти-версионного чтения

Сессия, читая блок

обнаруживает, что

есть открытый ETL,

она проверяет статус

транзакции (читает

заголовок UNDO

сегмента и видит,

что транзакция

активна.

Это значит, сессия

должна откатить

изменения

сделанные активной

транзакцией до

момента первого

изменения. Она

создает копию блока

и применяет UNDO.

Page 34: Traditional relational databases architecture

Identifier Deutsche Bank Dmitry Remizov

14 August 2014

Детали блокировок.

Допустим сессия хочет

поменять строку

проапдейченную первой

транзакцией, эта сессия

видит open ITL, идет

проверяет статус

транзакции в Undo

segment, видит активную

транзакцию и встает в

ожидание на адресе:

usn#.slot#.wrap#

•номер сегмента

•номер слота

•порядковый номер

Page 35: Traditional relational databases architecture

Identifier Deutsche Bank Dmitry Remizov

14 August 2014

Page 36: Traditional relational databases architecture

Identifier Deutsche Bank Dmitry Remizov

14 August 2014

Relation engine

MSSQL steps

• Query parsing

• Algebrizer – semantic analyses

• The query optimizer

Oracle steps

Page 37: Traditional relational databases architecture

Identifier Deutsche Bank Dmitry Remizov

14 August 2014

Виды парсинга в Oracle

• hard parse – наиболее тяжелый, «дорогостоящий» вид парсинга,

нет никакого execution plan’a, и Oracle проходит через все стадии на

предыдущей картинке, включая оптимизацию/построение плана.

•soft parse – второй по стоимости, Oracle все еще должен провести

синтаксический и семантический разбор, провести поиск в Shared

Pool (Library Cache).

•soft-soft parse – наиболее загадочный, похоже работает только

внутри PLSQL (если есть несколько parse call внутри PLSQL то на

3ий раз, парсинг уже не происходит и инкрементится статистика

cursor authentications, зависит от session_cached_cursors)

•no parse – просто держит открытый курсор и выполняет его

несколько раз. (parse count (total) не увеличивается) Возможно в

JDBC либо явно, либо на уровне драйвера. Похоже не зависит от

“session_cached_cursors”.

См. http://docs.oracle.com/cd/E11882_01/java.112/e16548/stmtcach.htm

Page 38: Traditional relational databases architecture

Identifier Deutsche Bank Dmitry Remizov

14 August 2014

На сцену выходит Shared Pool

Это область памяти которая хранит

в том числе и execution plans

Nowadays, with realfree private memory

management, PGA, UGA and Callheaps are

completely separate top-level heaps (allocated

separately from OS using mmap) and UGA is

not physically inside PGA anymore.

Page 39: Traditional relational databases architecture

Identifier Deutsche Bank Dmitry Remizov

14 August 2014

Shared Pool management challenge

Управление shared pool существенно отличается от случая buffer

cache в сторону сложности.

Buffer cache - блоки стандартного размера.

Shared pool – блоки не могут быть одного размера (слишком

неээфективно), с другой стороны, находить блок нестандартного

размера нужно достаточно быстро, мы не можем долго искать блок

нужного размера, либо конструировать его на лету.

Page 40: Traditional relational databases architecture

Identifier Deutsche Bank Dmitry Remizov

14 August 2014

Shared pool – приблизительная схема

Free list организованы в цепочки блоков разного размера, начиная с 16

байт, затем 20, 24 и т.д.

Page 41: Traditional relational databases architecture

Identifier Deutsche Bank Dmitry Remizov

14 August 2014

Любите свой Shared pool, и он ответит вам взаимностью.

Page 42: Traditional relational databases architecture

Identifier Deutsche Bank Dmitry Remizov

14 August 2014

Как можно помочь shared pool’у

PreparedStatement ps = con.prepareStatement("INSERT INTO FFF VALUES (?,?,?)");

ps.setInt(1, 1);

ps.setString(2, "GGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGG");

ps.setString(3, "GGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGG");

ps.execute();

ps.setInt(1, 1);

ps.setString(2, "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM");

ps.setString(3, "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM");

ps.execute();

ps.setInt(1, 1);

ps.setString(2, "NNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNN");

ps.setString(3, "NNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNN");

ps.execute();

ps.setInt(1, 1);

ps.setString(2, "GGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGG");

ps.setString(3, "GGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGG");

ps.execute();

ps.setInt(1, 1);

ps.setString(2, "GGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGG");

ps.setString(3, "GGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGG");

ps.execute();

Переиспользуйте открытый курсор, JDBC драйвер может это сделать за вас, но

процесс лучше держать под контролем

Page 43: Traditional relational databases architecture

Dmitry Remizov

14 August 2014 Deutsche Bank

В начале

NAME VALUE

---------------------------------------------------------------- ----------

parse count (total) 7

parse count (hard) 0

parse count (failures) 0

parse count (describe) 0

Page 44: Traditional relational databases architecture

Dmitry Remizov

14 August 2014 Deutsche Bank

1st execution

NAME VALUE

---------------------------------------------------------------- ----------

parse count (total) 8

parse count (hard) 0

parse count (failures) 0

parse count (describe) 0

Page 45: Traditional relational databases architecture

Dmitry Remizov

14 August 2014 Deutsche Bank

2nd execution

NAME VALUE

---------------------------------------------------------------- ----------

parse count (total) 8

parse count (hard) 0

parse count (failures) 0

parse count (describe) 0

Page 46: Traditional relational databases architecture

Identifier Deutsche Bank Dmitry Remizov

14 August 2014

5-ый execution

NAME VALUE

---------------------------------------------------------------- ----------

parse count (total) 8

parse count (hard) 0

parse count (failures) 0

parse count (describe) 0

Page 47: Traditional relational databases architecture

Dmitry Remizov

14 August 2014 Deutsche Bank

NAME VALUE

---------------------------------------------------------------- ----------

parse count (total) 7

parse count (hard) 0

parse count (failures) 0

parse count (describe) 0

NAME VALUE

--------------------------------------------------------------- ----------

parse count (total) 8

parse count (hard) 0

parse count (failures) 0

parse count (describe) 0

NAME VALUE

---------------------------------------------------------------- ----------

parse count (total) 8

parse count (hard) 0

parse count (failures) 0

parse count (describe) 0

NAME VALUE

---------------------------------------------------------------- ----------

parse count (total) 8

parse count (hard) 0

parse count (failures) 0

parse count (describe) 0

NAME VALUE

---------------------------------------------------------------- ----------

parse count (total) 8

parse count (hard) 0

parse count (failures) 0

parse count (describe) 0

Общий результат

Page 48: Traditional relational databases architecture

Dmitry Remizov

14 August 2014 Deutsche Bank

Это довольно запутанный случай из нашей практики.

Однако вероятность столкнутся с ним довольно велика при

использовании Spring framework.

Два случая представленные ниже отличаются по времени

исполнения в 100 раз (обрабатывая точно тот же массив данных).

Так что эффект колоссальный.

Что бывает, когда не заботишься о Shared pool

Page 49: Traditional relational databases architecture

Dmitry Remizov

14 August 2014 Deutsche Bank

List<Map<String, Object>> batchArgs = new LinkedList<Map<String, Object>>();

for (int i = 1; i < 1000; i++) {

Map<String, Object> map = new HashMap<String, Object>();

map.put("f1", getRandomNumber()); --- see we don’t define data type here explicitrely

map.put("f2", getRandomString());

……………………

map.put("f8", getRandomString());

batchArgs.add(map);

}

simpleJdbcTemplate.batchUpdate("INSERT /* BatchIssueSpring */ INTO YYYTEST

(f1,f2,f3,f4,f5,f6,f7,f8) VALUES (:f1,:f2,:f3,:f4,:f5,:f6,:f7,:f8)", batchArgs.toArray(new Map[0]));

System.out.println("time " + ((double) (System.currentTimeMillis() - startTime))/1000);

A tricky case – “untyped nulls”

time 37.36

Page 50: Traditional relational databases architecture

Dmitry Remizov

14 August 2014 Deutsche Bank

List<MapSqlParameterSource> batchArgs = new LinkedList<MapSqlParameterSource>();

for (int i = 1; i < 1000; i++) {

MapSqlParameterSource source = new MapSqlParameterSource();

source.addValue("f1", getRandomNumber(), Types.NUMERIC);

source.addValue("f2", getRandomString(), Types.VARCHAR);

………………………………………….

source.addValue("f8", getRandomString(), Types.VARCHAR);

batchArgs.add(source);

}

simpleJdbcTemplate.batchUpdate("INSERT INTO YYYTEST

(f1,f2,f3,f4,f5,f6,f7,f8) VALUES (:f1,:f2,:f3,:f4,:f5,:f6,:f7,:f8);

batchArgs.toArray(new SqlParameterSource[0]));

System.out.println("time " + ((double) (System.currentTimeMillis() - startTime))/1000);

A tricky case 2 – let’s define “nulls” types

time 0.39

Moralite:

When something is provided for “free” try to find out the cost

Page 51: Traditional relational databases architecture

Dmitry Remizov

14 August 2014 Deutsche Bank

private static void setNull(PreparedStatement ps, int paramIndex, int sqlType, String typeName)

throws SQLException {

if (sqlType == SqlTypeValue.TYPE_UNKNOWN) {

boolean useSetObject = false;

sqlType = Types.NULL;

try {

DatabaseMetaData dbmd = ps.getConnection().getMetaData();

String databaseProductName = dbmd.getDatabaseProductName();

String jdbcDriverName = dbmd.getDriverName();

if (databaseProductName.startsWith("Informix") ||

jdbcDriverName.startsWith("Microsoft SQL Server")) {

useSetObject = true;

}

else if (databaseProductName.startsWith("DB2") ||

jdbcDriverName.startsWith("jConnect") ||

jdbcDriverName.startsWith("SQLServer")||

jdbcDriverName.startsWith("Apache Derby")) {

sqlType = Types.VARCHAR;

}

}

catch (Throwable ex) {

logger.debug("Could not check database or driver name", ex);

}

if (useSetObject) {

ps.setObject(paramIndex, null);

}

else {

ps.setNull(paramIndex, sqlType);

}

A root cause of the issue on Java(Spring) side:

Page 52: Traditional relational databases architecture

Dmitry Remizov

14 August 2014 Deutsche Bank

select sql_id, child_number, bind_mismatch, c.BIND_LENGTH_UPGRADEABLE from

v$sql_shared_cursor c where sql_id ='0ajsk0mu1sakr'

And from the database side

SQL_ID CHILD_NUMBER BIND_MISMATCH BIND_LENGTH_UPGRADEABLE

0ajsk0mu1sakr 0 N N

0ajsk0mu1sakr 1 Y N

0ajsk0mu1sakr 2 N Y

0ajsk0mu1sakr 3 Y N

0ajsk0mu1sakr 4 Y N

0ajsk0mu1sakr 5 N Y

0ajsk0mu1sakr 6 Y Y

0ajsk0mu1sakr 7 Y N

0ajsk0mu1sakr 8 N Y

0ajsk0mu1sakr 9 Y Y

0ajsk0mu1sakr 10 N Y

0ajsk0mu1sakr 11 Y Y

0ajsk0mu1sakr 12 Y Y

0ajsk0mu1sakr 13 Y N

.......................................................................................................

Incredible amount of child cursors: >300 (after 3-4 executions)

It could lead to:

• extreme slowness

• the session death

Page 53: Traditional relational databases architecture

Dmitry Remizov

14 August 2014 Deutsche Bank

Let’s compare ROWS/EXECUTIONS and other metrics:

SELECT y.sql_id,

y.rows_processed,

ROUND (y.rows_processed / NULLIF (y.elapsed_time, 0) * 1000000, 2) AS rows_per_sec,

ROUND (y.rows_processed / NULLIF (y.executions, 0), 2) AS rows_per_exec,

ROUND (y.elapsed_time / 1000000 / NULLIF (y.executions, 0), 2) AS sec_per_exec

FROM v$sql y

WHERE y.sql_id in ('0ajsk0mu1sakr','5twjz0zzm07z0')

ORDER BY y.sql_id desc;

Some SQL metrics for both cases

SQL_ID ROWS_PROCESSED ROWS_PER_SEC ROWS_PER_EXEC SEC_PER_EXEC

-- explicetely defined data type

5twjz0zzm07z0 999 16903.55 999 0.06

-- undefined data types

0ajsk0mu1sakr 54 1026.87 1.04 0

0ajsk0mu1sakr 14 1052.32 1.27 0

0ajsk0mu1sakr 14 1462.45 2 0

0ajsk0mu1sakr 12 859.05 1 0

0ajsk0mu1sakr 21 1513.08 1.91 0

0ajsk0mu1sakr 7 769.74 1.4 0

0ajsk0mu1sakr 19 1498.66 1.9 0

0ajsk0mu1sakr 515 3285.17 2.75 0

………………………………………………………………………………………………………………………………………………………

Page 54: Traditional relational databases architecture

Dmitry Remizov

14 August 2014 Deutsche Bank

Jonathan Lewis: Oracle Core Essentials for DBAs and Developers.

Delaney Kalin: Inside Microsoft SQL Server 2005 The Storage Engine

http://blog.tanelpoder.com/

http://technet.microsoft.com/en-us/library/cc280362(v=sql.105).aspx

http://jonathanlewis.wordpress.com/

Oracle 9i OpSem materials

Литература

Page 55: Traditional relational databases architecture

Identifier Deutsche Bank Dmitry Remizov

14 August 2014

Критика традиционных RDBMS

•Latching

•Locking

•Buffer pool

•Recovery

Сьедают до

95% времени

Page 56: Traditional relational databases architecture

Identifier Deutsche Bank Dmitry Remizov

14 August 2014

Traditional Overheads

Page 57: Traditional relational databases architecture

Identifier Deutsche Bank Dmitry Remizov

14 August 2014

Traditional Overheads 2

Page 58: Traditional relational databases architecture

Identifier Deutsche Bank Dmitry Remizov

14 August 2014

Traditional Overheads 3

Page 59: Traditional relational databases architecture

Identifier Deutsche Bank Dmitry Remizov

14 August 2014

Traditional Overheads 4

Page 60: Traditional relational databases architecture

Identifier Deutsche Bank Dmitry Remizov

14 August 2014

Критика критики

На самом деле 95% преувеличение, но процентов 70-80% есть.

В отдельных случаях вы можете отказатся от части сервисов

RDBMS, например, NOLOGGING операции в data warehousing.

Использование субсекционирования, чтобы уменьшить

конкуренцию почти до 0, каждый поток льет в свой отдельный

сегмент и т.д.