Se ha denunciado esta presentación.
Utilizamos tu perfil de LinkedIn y tus datos de actividad para personalizar los anuncios y mostrarte publicidad más relevante. Puedes cambiar tus preferencias de publicidad en cualquier momento.

Traditional relational databases architecture

1.051 visualizaciones

Publicado el

Traditional relational databases architecture

Publicado en: Software
  • Sé el primero en comentar

Traditional relational databases architecture

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

×