SlideShare a Scribd company logo
1 of 60
Download to read offline
Group Technology and Operations
Deutsche Bank
Traditional relational
databases architecture
Dmitry Remizov
Dmitry Remizov
14 August 2014
Deutsche Bank
Я собираюсь рассказать некоторые базовые вещи об архитектуре
традиционных баз данных на примере 2х наиболее ярких
представителей систем этого класса, а именно - Oracle и Microsoft
SQL. Выбор обусловлен тем, что это, во-первых, лидирующие
системы в своих сегментах, во-вторых, они исповедуют весьма
различные базовые идеологии. В основном по историческим
причинам.
Начнем, однако, с того, зачем нужны базы данных вообще. Почему
бы не писать просто в плоские файлы. Действительно есть класс
задач, для которого это вполне релевантный подход (логи и т.п.).
Однако довольно часто нам надо писать что-то консистентно и из
многих потоков одновременно.
И вот этим-то и занимаются реляционные базы данных.
Agenda
Dmitry Remizov
14 August 2014
Deutsche Bank
Несмотря на все исторические различия, многие архитектурные
решения оказались весьма сходными. Хотя, конечно, есть и
существенные различия.
Начнем с того, что Oracle «версионник», а MSSQL «блокировочник».
Расшифруем немного этот жаргон:
•«Блокировочник» означает, что «писатель» может заблокировать
«читателей», 2 пишущие сессии должны логически лочить друг
друга, если имеют дело с одной и той же строкой (данными).
•«Версионник» вместо блокировки читателя возвращает клиенту
«предыдущую версию правды». На какой момент это отдельный
вопрос.
Два подхода
Dmitry Remizov
14 August 2014
Deutsche Bank
Из чего состоит реляционная база данных:
•Процессы OS
•Структуры в памяти
•Файлы на файловой системе
На следующем слайде мы увидим некоторую обзорную картинку
основных компонентов Oracle и MSQL
Архитектура
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
Dmitry Remizov
14 August 2014
Deutsche Bank
MSSQL взаимодействие базы данных
с клиентом
Dmitry Remizov
14 August 2014
Deutsche Bank
Сравнение основных «фоновых»
процессов
Dmitry Remizov
14 August 2014
Deutsche Bank
Oracle MSSQL
Buffer Cache Buffer Pool
Redo log buffer Log cache
Shared Pool Procedural cache
Сравнение основных областей
памяти
Identifier
Deutsche Bank Dmitry Remizov
14 August 2014
ACID
В незапамятные времена была определена некая модель, которой
должны удовлетворять все реляционные базы данных. Это 4
базовых принципа и по начальным буквам эта модель называется
ACID. Вкратце:
Atomicity – транзакция не может быть завершена частично.
Consistency – база данных консистентна в начале и конце каждой
транзакции
Isolation – транзакция не видит изменения произведенные другой
незавершенной транзакцией
Durability – закоммиченная транзакция «переживает» крах системы
Все реляционные базы в меру своих возможностей пытаются
удовлетворить ACID принципам и соответственно для этого нужны
низкоуровневые механизмы.
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 (и еще для
обеспечения много-версионного чтения).
Identifier
Deutsche Bank Dmitry Remizov
14 August 2014
WAL
Несколько слов зачем вообще нужны логи транзакций.
Современные базы данных - это в основном большие (иногда
распределенные кэши) с конкурентным доступом, и все, что вы
делаете с данными в основном происходит в оперативной памяти
(есть исключения), однако нам надо обеспечить механизм
восстановления данных при крахе системы.
Для этого все изменения в системе пишутся в отдельный лог,
который при commit’е синхронно сохраняется на файловую систему.
И в Oracle и в MSSQL реализован механизм т.н. WAL ( Write ahead
logging), т.е. все данные, которые вы записываете, сначала пишутся
в лог (точнее в лог буфер, который постоянно скидывается на диск)
и только в момент commit’a мы окончательно синхронизируем лог
буфер и лог файлы (на момент коммита). И только после того, как
мы записали лог, мы реально изменяем данные (сначала в памяти,
а потом когда-нибудь на диске).
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 в системе.
Identifier
Deutsche Bank Dmitry Remizov
14 August 2014
Rollback and recovery в MSSQL
В случае краха системы MSSQL последовательно накатывает
transaction log и затем откатывает незакоммиченные транзакции.
В случае rollback - использует «Log records связаны в обратную
цепочку (backword chained)» и применяет все log records в обратном
порядке.
Identifier
Deutsche Bank Dmitry Remizov
14 August 2014
В Oracle все немного сложнее
Любые изменения в блоке данных сразу же генерят инструкции по
их отмене, которые записываются в UNDO. И изменения в дата
блоках и в UNDO сегменте тут же записываются в REDO log.
На самом деле вначале записываются эти инструкции в REDO, а
затем изменения происходят в UNDO и дата блоке.
См. слайд.
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.
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
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.
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).
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
Identifier
Deutsche Bank Dmitry Remizov
14 August 2014 20
Multi Row Update
RedoStatements
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;
Identifier
Deutsche Bank Dmitry Remizov
14 August 2014 21
Global Temporary Tables
RedoStatements
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);
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
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).
Identifier
Deutsche Bank Dmitry Remizov
14 August 2014
Checkpoint
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
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 тоже нашел большое
кол-во «грязных» блоков чтобы
сбросить их на диск.
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
сек общего времени)
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/
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
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
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
На этот раз разница в количестве
обработанных блоков
приблизительно соответствует
степени сжатия
Identifier
Deutsche Bank Dmitry Remizov
14 August 2014
Внутренняя механика обеспечения row level
locking and “versioning” в Oracle
Identifier
Deutsche Bank Dmitry Remizov
14 August 2014
Детали read consistency/мульти-
версионного чтения
Сессия, читая блок
обнаруживает, что
есть открытый ETL,
она проверяет статус
транзакции (читает
заголовок UNDO
сегмента и видит,
что транзакция
активна.
Это значит, сессия
должна откатить
изменения
сделанные активной
транзакцией до
момента первого
изменения. Она
создает копию блока
и применяет UNDO.
Identifier
Deutsche Bank Dmitry Remizov
14 August 2014
Детали блокировок.
Допустим сессия хочет
поменять строку
проапдейченную первой
транзакцией, эта сессия
видит open ITL, идет
проверяет статус
транзакции в Undo
segment, видит активную
транзакцию и встает в
ожидание на адресе:
usn#.slot#.wrap#
•номер сегмента
•номер слота
•порядковый номер
Identifier
Deutsche Bank Dmitry Remizov
14 August 2014
Identifier
Deutsche Bank Dmitry Remizov
14 August 2014
Relation engine
MSSQL steps
• Query parsing
• Algebrizer – semantic analyses
• The query optimizer
Oracle steps
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
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.
Identifier
Deutsche Bank Dmitry Remizov
14 August 2014
Shared Pool management challenge
Управление shared pool существенно отличается от случая buffer
cache в сторону сложности.
Buffer cache - блоки стандартного размера.
Shared pool – блоки не могут быть одного размера (слишком
неээфективно), с другой стороны, находить блок нестандартного
размера нужно достаточно быстро, мы не можем долго искать блок
нужного размера, либо конструировать его на лету.
Identifier
Deutsche Bank Dmitry Remizov
14 August 2014
Shared pool – приблизительная схема
Free list организованы в цепочки блоков разного размера, начиная с 16
байт, затем 20, 24 и т.д.
Identifier
Deutsche Bank Dmitry Remizov
14 August 2014
Любите свой Shared pool, и он ответит вам
взаимностью.
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 драйвер может это сделать за вас, но
процесс лучше держать под контролем
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
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
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
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
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
Общий результат
Dmitry Remizov
14 August 2014
Deutsche Bank
Это довольно запутанный случай из нашей практики.
Однако вероятность столкнутся с ним довольно велика при
использовании Spring framework.
Два случая представленные ниже отличаются по времени
исполнения в 100 раз (обрабатывая точно тот же массив данных).
Так что эффект колоссальный.
Что бывает, когда не заботишься о
Shared pool
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
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
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);
}
Aroot cause of the issue on Java(Spring) side:
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
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
………………………………………………………………………………………………………………………………………………………
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
Литература
Identifier
Deutsche Bank Dmitry Remizov
14 August 2014
Критика традиционных RDBMS
•Latching
•Locking
•Buffer pool
•Recovery
Сьедают до
95% времени
Identifier
Deutsche Bank Dmitry Remizov
14 August 2014
Traditional Overheads
Identifier
Deutsche Bank Dmitry Remizov
14 August 2014
Traditional Overheads 2
Identifier
Deutsche Bank Dmitry Remizov
14 August 2014
Traditional Overheads 3
Identifier
Deutsche Bank Dmitry Remizov
14 August 2014
Traditional Overheads 4
Identifier
Deutsche Bank Dmitry Remizov
14 August 2014
Критика критики
На самом деле 95% преувеличение, но процентов 70-80% есть.
В отдельных случаях вы можете отказатся от части сервисов
RDBMS, например, NOLOGGING операции в data warehousing.
Использование субсекционирования, чтобы уменьшить
конкуренцию почти до 0, каждый поток льет в свой отдельный
сегмент и т.д.

More Related Content

What's hot

Usage concurrence in java
Usage concurrence in javaUsage concurrence in java
Usage concurrence in java
Asya Dudnik
 
Aleksey Mashanov Rit
Aleksey  Mashanov RitAleksey  Mashanov Rit
Aleksey Mashanov Rit
rit2010
 
"YT — новая платформа распределённых вычислений". Максим Бабенко, Яндекс.
"YT — новая платформа распределённых вычислений". Максим Бабенко, Яндекс. "YT — новая платформа распределённых вычислений". Максим Бабенко, Яндекс.
"YT — новая платформа распределённых вычислений". Максим Бабенко, Яндекс.
Yandex
 
Операционные системы
Операционные системыОперационные системы
Операционные системы
yaevents
 
Software Transactional Memory
Software Transactional MemorySoftware Transactional Memory
Software Transactional Memory
Vadim Tsesko
 
FreeRTOS
FreeRTOSFreeRTOS
FreeRTOS
quakke
 

What's hot (20)

Usage concurrence in java
Usage concurrence in javaUsage concurrence in java
Usage concurrence in java
 
Aleksey Mashanov Rit
Aleksey  Mashanov RitAleksey  Mashanov Rit
Aleksey Mashanov Rit
 
Введение в сетевые технологии
Введение в сетевые технологииВведение в сетевые технологии
Введение в сетевые технологии
 
МАИ, Сети ЭВМ, Лекция №3
МАИ, Сети ЭВМ, Лекция №3МАИ, Сети ЭВМ, Лекция №3
МАИ, Сети ЭВМ, Лекция №3
 
Базы данных лекция №9
Базы данных лекция №9Базы данных лекция №9
Базы данных лекция №9
 
Сергей Париев - "обработка дедлоков в MySql"
Сергей Париев - "обработка дедлоков в MySql"Сергей Париев - "обработка дедлоков в MySql"
Сергей Париев - "обработка дедлоков в MySql"
 
"YT — новая платформа распределённых вычислений". Максим Бабенко, Яндекс.
"YT — новая платформа распределённых вычислений". Максим Бабенко, Яндекс. "YT — новая платформа распределённых вычислений". Максим Бабенко, Яндекс.
"YT — новая платформа распределённых вычислений". Максим Бабенко, Яндекс.
 
Multimaster2
Multimaster2Multimaster2
Multimaster2
 
"Мультимастер для PostgreSQL" Кельвич Станислав, Книжник Константин, PostgresPro
"Мультимастер для PostgreSQL" Кельвич Станислав, Книжник Константин, PostgresPro"Мультимастер для PostgreSQL" Кельвич Станислав, Книжник Константин, PostgresPro
"Мультимастер для PostgreSQL" Кельвич Станислав, Книжник Константин, PostgresPro
 
МАИ, Сети ЭВМ, Лекция №6
МАИ, Сети ЭВМ, Лекция №6МАИ, Сети ЭВМ, Лекция №6
МАИ, Сети ЭВМ, Лекция №6
 
О.В.Сухорослов "MapReduce"
О.В.Сухорослов "MapReduce"О.В.Сухорослов "MapReduce"
О.В.Сухорослов "MapReduce"
 
Синие против красных
Синие против красныхСиние против красных
Синие против красных
 
Операционные системы
Операционные системыОперационные системы
Операционные системы
 
Software Transactional Memory
Software Transactional MemorySoftware Transactional Memory
Software Transactional Memory
 
итерация и рекурсия
итерация и рекурсияитерация и рекурсия
итерация и рекурсия
 
Лекция 10. Apache Mahout
Лекция 10. Apache MahoutЛекция 10. Apache Mahout
Лекция 10. Apache Mahout
 
C++ Базовый. Занятие 13.
C++ Базовый. Занятие 13.C++ Базовый. Занятие 13.
C++ Базовый. Занятие 13.
 
Протокол HTTP. Клиент-серверная модель взаимодействия. Servlet API
Протокол HTTP. Клиент-серверная модель взаимодействия. Servlet APIПротокол HTTP. Клиент-серверная модель взаимодействия. Servlet API
Протокол HTTP. Клиент-серверная модель взаимодействия. Servlet API
 
Базы данных. Hash & Cache
Базы данных. Hash & CacheБазы данных. Hash & Cache
Базы данных. Hash & Cache
 
FreeRTOS
FreeRTOSFreeRTOS
FreeRTOS
 

Viewers also liked

Аспектно-ориентированное программирование в распределенных системах для java ...
Аспектно-ориентированное программирование в распределенных системах для java ...Аспектно-ориентированное программирование в распределенных системах для java ...
Аспектно-ориентированное программирование в распределенных системах для java ...
Igor Suhorukov
 
визит представителя к врачу
визит представителя к врачувизит представителя к врачу
визит представителя к врачу
medpred. org.ua
 
Ермолай Солженицын. Пленарное заседание «Город и глобальная экономика: место ...
Ермолай Солженицын. Пленарное заседание «Город и глобальная экономика: место ...Ермолай Солженицын. Пленарное заседание «Город и глобальная экономика: место ...
Ермолай Солженицын. Пленарное заседание «Город и глобальная экономика: место ...
Moscow Urban Forum
 
Подход McKinsey к развитию бренда работодателя в социальных сетях
Подход McKinsey к развитию бренда работодателя в социальных сетяхПодход McKinsey к развитию бренда работодателя в социальных сетях
Подход McKinsey к развитию бренда работодателя в социальных сетях
FutureToday
 

Viewers also liked (11)

Deutsche bank
Deutsche bankDeutsche bank
Deutsche bank
 
Building a Purposeful Social Network by Deutsche Bank - BDI 11/15/12 Financia...
Building a Purposeful Social Network by Deutsche Bank - BDI 11/15/12 Financia...Building a Purposeful Social Network by Deutsche Bank - BDI 11/15/12 Financia...
Building a Purposeful Social Network by Deutsche Bank - BDI 11/15/12 Financia...
 
Аспектно-ориентированное программирование в распределенных системах для java ...
Аспектно-ориентированное программирование в распределенных системах для java ...Аспектно-ориентированное программирование в распределенных системах для java ...
Аспектно-ориентированное программирование в распределенных системах для java ...
 
визит представителя к врачу
визит представителя к врачувизит представителя к врачу
визит представителя к врачу
 
SAP ERP - система для управления бизнесом
SAP ERP - система для управления бизнесомSAP ERP - система для управления бизнесом
SAP ERP - система для управления бизнесом
 
Презентация Pfizer "Обучение медпредставителей"
Презентация Pfizer "Обучение медпредставителей"Презентация Pfizer "Обучение медпредставителей"
Презентация Pfizer "Обучение медпредставителей"
 
Mc kinsey belov_energyefficiency
Mc kinsey belov_energyefficiencyMc kinsey belov_energyefficiency
Mc kinsey belov_energyefficiency
 
Deutsche Bank - NOAH16 Berlin
Deutsche Bank - NOAH16 BerlinDeutsche Bank - NOAH16 Berlin
Deutsche Bank - NOAH16 Berlin
 
Ермолай Солженицын. Пленарное заседание «Город и глобальная экономика: место ...
Ермолай Солженицын. Пленарное заседание «Город и глобальная экономика: место ...Ермолай Солженицын. Пленарное заседание «Город и глобальная экономика: место ...
Ермолай Солженицын. Пленарное заседание «Город и глобальная экономика: место ...
 
Подход McKinsey к развитию бренда работодателя в социальных сетях
Подход McKinsey к развитию бренда работодателя в социальных сетяхПодход McKinsey к развитию бренда работодателя в социальных сетях
Подход McKinsey к развитию бренда работодателя в социальных сетях
 
What Would Steve Do? 10 Lessons from the World's Most Captivating Presenters
What Would Steve Do? 10 Lessons from the World's Most Captivating PresentersWhat Would Steve Do? 10 Lessons from the World's Most Captivating Presenters
What Would Steve Do? 10 Lessons from the World's Most Captivating Presenters
 

Similar to Traditional relational databases architecture

High Load 2009 Dimaa Rus Ready
High Load 2009 Dimaa Rus ReadyHigh Load 2009 Dimaa Rus Ready
High Load 2009 Dimaa Rus Ready
HighLoad2009
 
Evgeny Rybak Presentation
Evgeny Rybak PresentationEvgeny Rybak Presentation
Evgeny Rybak Presentation
sef2009
 
Лекция №5 Организация ЭВМ и систем
Лекция №5 Организация ЭВМ и системЛекция №5 Организация ЭВМ и систем
Лекция №5 Организация ЭВМ и систем
pianist2317
 
Как построить высокопроизводительный Front-end сервер (Александр Крижановский)
Как построить высокопроизводительный Front-end сервер (Александр Крижановский) Как построить высокопроизводительный Front-end сервер (Александр Крижановский)
Как построить высокопроизводительный Front-end сервер (Александр Крижановский)
Ontico
 
JS Fest 2019. Игорь Березин и Николай Крещенко. Эволюция архитектуры многогра...
JS Fest 2019. Игорь Березин и Николай Крещенко. Эволюция архитектуры многогра...JS Fest 2019. Игорь Березин и Николай Крещенко. Эволюция архитектуры многогра...
JS Fest 2019. Игорь Березин и Николай Крещенко. Эволюция архитектуры многогра...
JSFestUA
 
Apache Cassandra. Ещё одно NoSQL хранилище (Владимир Климонтович)
Apache Cassandra. Ещё одно NoSQL хранилище (Владимир Климонтович)Apache Cassandra. Ещё одно NoSQL хранилище (Владимир Климонтович)
Apache Cassandra. Ещё одно NoSQL хранилище (Владимир Климонтович)
Ontico
 
Транзакции и блокировки в MySql. Теория и практика
Транзакции и блокировки в MySql. Теория и практикаТранзакции и блокировки в MySql. Теория и практика
Транзакции и блокировки в MySql. Теория и практика
Nikolay Gondin
 
2014.12.23 Александр Андреев, Parallels
2014.12.23 Александр Андреев, Parallels2014.12.23 Александр Андреев, Parallels
2014.12.23 Александр Андреев, Parallels
Nikolay Samokhvalov
 

Similar to Traditional relational databases architecture (20)

Что особенного в СУБД для данных в оперативной памяти / Константин Осипов (Ta...
Что особенного в СУБД для данных в оперативной памяти / Константин Осипов (Ta...Что особенного в СУБД для данных в оперативной памяти / Константин Осипов (Ta...
Что особенного в СУБД для данных в оперативной памяти / Константин Осипов (Ta...
 
Константин Осипов
Константин ОсиповКонстантин Осипов
Константин Осипов
 
Евгений Лазин. Неизменяемая структура данных HAMT для создания БД в памяти
Евгений Лазин. Неизменяемая структура данных HAMT для создания БД в памятиЕвгений Лазин. Неизменяемая структура данных HAMT для создания БД в памяти
Евгений Лазин. Неизменяемая структура данных HAMT для создания БД в памяти
 
Purely practical data structures
Purely practical data structuresPurely practical data structures
Purely practical data structures
 
High Load 2009 Dimaa Rus Ready
High Load 2009 Dimaa Rus ReadyHigh Load 2009 Dimaa Rus Ready
High Load 2009 Dimaa Rus Ready
 
Dynamic Language Runtime
Dynamic Language RuntimeDynamic Language Runtime
Dynamic Language Runtime
 
Evgeny Rybak Presentation
Evgeny Rybak PresentationEvgeny Rybak Presentation
Evgeny Rybak Presentation
 
Максим Богук. Postgres-XC
Максим Богук. Postgres-XCМаксим Богук. Postgres-XC
Максим Богук. Postgres-XC
 
User Aggs In As
User Aggs In AsUser Aggs In As
User Aggs In As
 
Лекция №5 Организация ЭВМ и систем
Лекция №5 Организация ЭВМ и системЛекция №5 Организация ЭВМ и систем
Лекция №5 Организация ЭВМ и систем
 
Лекция №5 Организация ЭВМ и систем
Лекция №5 Организация ЭВМ и системЛекция №5 Организация ЭВМ и систем
Лекция №5 Организация ЭВМ и систем
 
Как построить высокопроизводительный Front-end сервер (Александр Крижановский)
Как построить высокопроизводительный Front-end сервер (Александр Крижановский) Как построить высокопроизводительный Front-end сервер (Александр Крижановский)
Как построить высокопроизводительный Front-end сервер (Александр Крижановский)
 
supercluster
superclustersupercluster
supercluster
 
JS Fest 2019. Игорь Березин и Николай Крещенко. Эволюция архитектуры многогра...
JS Fest 2019. Игорь Березин и Николай Крещенко. Эволюция архитектуры многогра...JS Fest 2019. Игорь Березин и Николай Крещенко. Эволюция архитектуры многогра...
JS Fest 2019. Игорь Березин и Николай Крещенко. Эволюция архитектуры многогра...
 
Tfs reports customization
Tfs reports customizationTfs reports customization
Tfs reports customization
 
Apache Cassandra. Ещё одно NoSQL хранилище (Владимир Климонтович)
Apache Cassandra. Ещё одно NoSQL хранилище (Владимир Климонтович)Apache Cassandra. Ещё одно NoSQL хранилище (Владимир Климонтович)
Apache Cassandra. Ещё одно NoSQL хранилище (Владимир Климонтович)
 
Для чего мы делали свой акторный фреймворк и что из этого вышло?
Для чего мы делали свой акторный фреймворк и что из этого вышло?Для чего мы делали свой акторный фреймворк и что из этого вышло?
Для чего мы делали свой акторный фреймворк и что из этого вышло?
 
Транзакции и блокировки в MySql. Теория и практика
Транзакции и блокировки в MySql. Теория и практикаТранзакции и блокировки в MySql. Теория и практика
Транзакции и блокировки в MySql. Теория и практика
 
2014.12.23 Александр Андреев, Parallels
2014.12.23 Александр Андреев, Parallels2014.12.23 Александр Андреев, Parallels
2014.12.23 Александр Андреев, Parallels
 
DBMS Benchmarks in a Nutshell
DBMS Benchmarks in a Nutshell DBMS Benchmarks in a Nutshell
DBMS Benchmarks in a Nutshell
 

Traditional relational databases architecture

  • 1. Group Technology and Operations Deutsche Bank Traditional relational databases architecture Dmitry Remizov
  • 2. Dmitry Remizov 14 August 2014 Deutsche Bank Я собираюсь рассказать некоторые базовые вещи об архитектуре традиционных баз данных на примере 2х наиболее ярких представителей систем этого класса, а именно - Oracle и Microsoft SQL. Выбор обусловлен тем, что это, во-первых, лидирующие системы в своих сегментах, во-вторых, они исповедуют весьма различные базовые идеологии. В основном по историческим причинам. Начнем, однако, с того, зачем нужны базы данных вообще. Почему бы не писать просто в плоские файлы. Действительно есть класс задач, для которого это вполне релевантный подход (логи и т.п.). Однако довольно часто нам надо писать что-то консистентно и из многих потоков одновременно. И вот этим-то и занимаются реляционные базы данных. Agenda
  • 3. Dmitry Remizov 14 August 2014 Deutsche Bank Несмотря на все исторические различия, многие архитектурные решения оказались весьма сходными. Хотя, конечно, есть и существенные различия. Начнем с того, что Oracle «версионник», а MSSQL «блокировочник». Расшифруем немного этот жаргон: •«Блокировочник» означает, что «писатель» может заблокировать «читателей», 2 пишущие сессии должны логически лочить друг друга, если имеют дело с одной и той же строкой (данными). •«Версионник» вместо блокировки читателя возвращает клиенту «предыдущую версию правды». На какой момент это отдельный вопрос. Два подхода
  • 4. Dmitry Remizov 14 August 2014 Deutsche Bank Из чего состоит реляционная база данных: •Процессы OS •Структуры в памяти •Файлы на файловой системе На следующем слайде мы увидим некоторую обзорную картинку основных компонентов Oracle и MSQL Архитектура
  • 5. 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
  • 6. Dmitry Remizov 14 August 2014 Deutsche Bank MSSQL взаимодействие базы данных с клиентом
  • 7. Dmitry Remizov 14 August 2014 Deutsche Bank Сравнение основных «фоновых» процессов
  • 8. Dmitry Remizov 14 August 2014 Deutsche Bank Oracle MSSQL Buffer Cache Buffer Pool Redo log buffer Log cache Shared Pool Procedural cache Сравнение основных областей памяти
  • 9. Identifier Deutsche Bank Dmitry Remizov 14 August 2014 ACID В незапамятные времена была определена некая модель, которой должны удовлетворять все реляционные базы данных. Это 4 базовых принципа и по начальным буквам эта модель называется ACID. Вкратце: Atomicity – транзакция не может быть завершена частично. Consistency – база данных консистентна в начале и конце каждой транзакции Isolation – транзакция не видит изменения произведенные другой незавершенной транзакцией Durability – закоммиченная транзакция «переживает» крах системы Все реляционные базы в меру своих возможностей пытаются удовлетворить ACID принципам и соответственно для этого нужны низкоуровневые механизмы.
  • 10. 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 (и еще для обеспечения много-версионного чтения).
  • 11. Identifier Deutsche Bank Dmitry Remizov 14 August 2014 WAL Несколько слов зачем вообще нужны логи транзакций. Современные базы данных - это в основном большие (иногда распределенные кэши) с конкурентным доступом, и все, что вы делаете с данными в основном происходит в оперативной памяти (есть исключения), однако нам надо обеспечить механизм восстановления данных при крахе системы. Для этого все изменения в системе пишутся в отдельный лог, который при commit’е синхронно сохраняется на файловую систему. И в Oracle и в MSSQL реализован механизм т.н. WAL ( Write ahead logging), т.е. все данные, которые вы записываете, сначала пишутся в лог (точнее в лог буфер, который постоянно скидывается на диск) и только в момент commit’a мы окончательно синхронизируем лог буфер и лог файлы (на момент коммита). И только после того, как мы записали лог, мы реально изменяем данные (сначала в памяти, а потом когда-нибудь на диске).
  • 12. 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 в системе.
  • 13. Identifier Deutsche Bank Dmitry Remizov 14 August 2014 Rollback and recovery в MSSQL В случае краха системы MSSQL последовательно накатывает transaction log и затем откатывает незакоммиченные транзакции. В случае rollback - использует «Log records связаны в обратную цепочку (backword chained)» и применяет все log records в обратном порядке.
  • 14. Identifier Deutsche Bank Dmitry Remizov 14 August 2014 В Oracle все немного сложнее Любые изменения в блоке данных сразу же генерят инструкции по их отмене, которые записываются в UNDO. И изменения в дата блоках и в UNDO сегменте тут же записываются в REDO log. На самом деле вначале записываются эти инструкции в REDO, а затем изменения происходят в UNDO и дата блоке. См. слайд.
  • 15. 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.
  • 16. 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
  • 17. 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.
  • 18. 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).
  • 19. 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
  • 20. Identifier Deutsche Bank Dmitry Remizov 14 August 2014 20 Multi Row Update RedoStatements 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;
  • 21. Identifier Deutsche Bank Dmitry Remizov 14 August 2014 21 Global Temporary Tables RedoStatements 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);
  • 22. 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
  • 23. 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).
  • 24. Identifier Deutsche Bank Dmitry Remizov 14 August 2014 Checkpoint
  • 25. 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
  • 26. 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 тоже нашел большое кол-во «грязных» блоков чтобы сбросить их на диск.
  • 27. 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 сек общего времени)
  • 28. 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/
  • 29. 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
  • 30. 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
  • 31. 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 На этот раз разница в количестве обработанных блоков приблизительно соответствует степени сжатия
  • 32. Identifier Deutsche Bank Dmitry Remizov 14 August 2014 Внутренняя механика обеспечения row level locking and “versioning” в Oracle
  • 33. Identifier Deutsche Bank Dmitry Remizov 14 August 2014 Детали read consistency/мульти- версионного чтения Сессия, читая блок обнаруживает, что есть открытый ETL, она проверяет статус транзакции (читает заголовок UNDO сегмента и видит, что транзакция активна. Это значит, сессия должна откатить изменения сделанные активной транзакцией до момента первого изменения. Она создает копию блока и применяет UNDO.
  • 34. Identifier Deutsche Bank Dmitry Remizov 14 August 2014 Детали блокировок. Допустим сессия хочет поменять строку проапдейченную первой транзакцией, эта сессия видит open ITL, идет проверяет статус транзакции в Undo segment, видит активную транзакцию и встает в ожидание на адресе: usn#.slot#.wrap# •номер сегмента •номер слота •порядковый номер
  • 35. Identifier Deutsche Bank Dmitry Remizov 14 August 2014
  • 36. Identifier Deutsche Bank Dmitry Remizov 14 August 2014 Relation engine MSSQL steps • Query parsing • Algebrizer – semantic analyses • The query optimizer Oracle steps
  • 37. 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
  • 38. 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.
  • 39. Identifier Deutsche Bank Dmitry Remizov 14 August 2014 Shared Pool management challenge Управление shared pool существенно отличается от случая buffer cache в сторону сложности. Buffer cache - блоки стандартного размера. Shared pool – блоки не могут быть одного размера (слишком неээфективно), с другой стороны, находить блок нестандартного размера нужно достаточно быстро, мы не можем долго искать блок нужного размера, либо конструировать его на лету.
  • 40. Identifier Deutsche Bank Dmitry Remizov 14 August 2014 Shared pool – приблизительная схема Free list организованы в цепочки блоков разного размера, начиная с 16 байт, затем 20, 24 и т.д.
  • 41. Identifier Deutsche Bank Dmitry Remizov 14 August 2014 Любите свой Shared pool, и он ответит вам взаимностью.
  • 42. 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 драйвер может это сделать за вас, но процесс лучше держать под контролем
  • 43. 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
  • 44. 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
  • 45. 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
  • 46. 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
  • 47. 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 Общий результат
  • 48. Dmitry Remizov 14 August 2014 Deutsche Bank Это довольно запутанный случай из нашей практики. Однако вероятность столкнутся с ним довольно велика при использовании Spring framework. Два случая представленные ниже отличаются по времени исполнения в 100 раз (обрабатывая точно тот же массив данных). Так что эффект колоссальный. Что бывает, когда не заботишься о Shared pool
  • 49. 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
  • 50. 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
  • 51. 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); } Aroot cause of the issue on Java(Spring) side:
  • 52. 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
  • 53. 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 ………………………………………………………………………………………………………………………………………………………
  • 54. 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 Литература
  • 55. Identifier Deutsche Bank Dmitry Remizov 14 August 2014 Критика традиционных RDBMS •Latching •Locking •Buffer pool •Recovery Сьедают до 95% времени
  • 56. Identifier Deutsche Bank Dmitry Remizov 14 August 2014 Traditional Overheads
  • 57. Identifier Deutsche Bank Dmitry Remizov 14 August 2014 Traditional Overheads 2
  • 58. Identifier Deutsche Bank Dmitry Remizov 14 August 2014 Traditional Overheads 3
  • 59. Identifier Deutsche Bank Dmitry Remizov 14 August 2014 Traditional Overheads 4
  • 60. Identifier Deutsche Bank Dmitry Remizov 14 August 2014 Критика критики На самом деле 95% преувеличение, но процентов 70-80% есть. В отдельных случаях вы можете отказатся от части сервисов RDBMS, например, NOLOGGING операции в data warehousing. Использование субсекционирования, чтобы уменьшить конкуренцию почти до 0, каждый поток льет в свой отдельный сегмент и т.д.