Oracle Database Flash Cache - производительность для пользователя

THE HOLY BIBLE - King James Version - БИБЛИЯ в Синодальном переводе
"Нас Атакуют!" Изобличи козни лукавого, запрети диаволу

Oracle 11g Database Flash Cache - производительность для пользователя

Базы данных Оракл предлагают конечному пользователю значительные выгоды от использования мощных современных многоядерных процессоров, больших объёмов оперативной памяти и дисковых массивов высокой производительности. В то же время, своевременное обновление аппаратных средств зачастую становится невозможным из-за необходимости покупки дополнительных дорогостоящих лицензий на продукты Оракл, невозможности установки новых модулей памяти на устаревшую материнскую плату и достижения максимального числа установленных жёстких дисков. Как результат, сервер базы данных не может удовлетворить постоянно возрастающие требования пользователей.

Предлагаемая читателю заметка рассказывает о моём опыте использования твёрдотельных флэш-модулей для значительного увеличения производительности сервера базы данных Oracle 11g без необходимости обновления остальных аппаратных компонентов (CPU, RAM, диски).

Прежде чем мы продолжим, я хотел бы привести строки из Евангелия:



......... == Первое послание к Коринфянам святого апостола Павла == ............
=== Глава 13, Стих 4 ===
4 Любовь долготерпит, милосердствует, любовь не завидует, любовь не
 превозносится, не гордится,
5 не бесчинствует, не ищет своего, не раздражается, не мыслит зла,
6 не радуется неправде, а сорадуется истине;
7 все покрывает, всему верит, всего надеется, все переносит.
8 Любовь никогда не перестает, хотя и пророчества прекратятся, и языки
 умолкнут, и знание упразднится.

Лично для вас благая весть - Единородный Сын Божий Иисус Христос любит вас, Он взошёл на крест за ваши грехи, был распят и на третий день воскрес, сел одесную Бога и открыл нам дорогу в Царствие Небесное.

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

Но Иисус ясно говорит нам, что без любви к ближнему нету для нас спасения и все наши усилия тщетны (1 Кор.,13:1-3). Как бы тяжело нам ни приходилось в жизни - Иисус учит нас любить всех людей вокруг нас, милосердно прощать и благословлять наших обидчиков, как Он сам просил Бога о прощении для распинавших Его. Только любя других людей мы можем достичь спасения для себя самих.

Покайтесь, примите Иисуса как вашего Спасителя, ибо наступают последние времена и время близко - стоит Судья у ворот.

Пожалуйста, в своих каждодневных трудах, какими бы занятыми вы себе ни казались - находите время для Бога, Его заповедей и Библии.

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


Вернёмся к нашим техническим деталям.

Рассмотрим простой пример, демонстрирующий получение прироста производительности для OLTP приложений как следствие использования Database Flash Cache - новой возможности Oracle EE 11g. В качестве операционной системы необходимо использовать Oracle OUL 5 или 6. Флэш-кэш базы данных работает только в Oracle Enterprise Edition. В соответствии с выводами, полученными мной в предыдущей заметке "Флеш-память, твердотельные и жёсткие диски - производительность для пользователя", я выбрал Sun Flash Accelerator F20 PCIe Card как твердотельный флэш-накопитель.

Основные тесты будут проводиться с помощью программы Swingbench, имитирующей транзакции бизнес-пользователей. Два типа транзакций будут участвовать в следующих тестовых сценариях:

  • Warehouse Orders Query - без использования Flash Cache;
  • Sales Report Query - без использования Flash Cache;
  • Warehouse Orders Query - с использованием Flash Cache;
  • Sales Report Query - с использованием Flash Cache.

    Для начала каждый из сценариев будет проверен с использованием только одной сессии пользователя, без применения генераторов транзакций. Затем две 10-минутных сессии программы Swingbench будут имитировать 20 пользователей, одновременно запускающих Warehouse Orders и Sales Reports. В одной из 10-минутных сессий будет использоваться Flash Cache.

    Тестирование будет производиться на сравнительно небольших объёмах данных (схема SOE имеет размер около 30 Гигабайт), при этом размер Database Buffer Cache будет искусственно занижен до 180 Мегабайт, при общем размере SGA равном 600 Мб. Такой подход необходим для имитации сервера базы данных с очень ограниченными аппаратными ресурсами. Для тестирования используется компьютер с единственным двух-ядерным процессором, 8 Гб оперативной памяти и единственным SATA диском.

    Запуск экземпляра Оракл и подготовка к "одиночным" тестам

    Проверим доступные ресурсы нашего компьютера:

    ............... == Книга Премудрости Иисуса, сына Сирахова == ..................
    === Глава 28, Стих 3 ===
    3 Человек  питает   гнев   к   человеку,   а   у   Господа   просит    прощения;
    4 к подобному себе человеку не имеет  милосердия,  и  молится  о  грехах  своих;
    5 сам,   будучи   плотию,   питает   злобу:    кто    очистит    грехи      его?
    6 Помни последнее и перестань враждовать; помни истление  и  смерть  и  соблюдай
    заповеди;
    7 помни      заповеди      и      не      злобствуй      на            ближнего;
    8 помни      завет      Всевышнего       и       презирай            невежество.
    
    (b+/b-, c+/c-, +/-, *) >
    
    [oracle@OUL ft]$ grep Total /proc/meminfo
    MemTotal:        8188996 kB
    HugePages_Total:       0
    [oracle@OUL ft]$
    [oracle@OUL ft]$ grep "model name" /proc/cpuinfo
    model name      : AMD Athlon(tm) 64 X2 Dual Core Processor 3800+
    model name      : AMD Athlon(tm) 64 X2 Dual Core Processor 3800+
    [oracle@OUL ft]$
    

    Очевидно, что от системы с такими характеристиками не приходится ожидать выдающихся результатов. Запустим базу данных.

    07:46:27 SQL> startup
    ORACLE instance started.
    
    Total System Global Area  626327552 bytes
    Fixed Size                  2230952 bytes
    Variable Size             432014680 bytes
    Database Buffers          184549376 bytes
    Redo Buffers                7532544 bytes
    Database mounted.
    Database opened.
    07:46:42 SQL> show parameter flash
    
    NAME                                 TYPE        VALUE
    ------------------------------------ ----------- ------------------------------
    db_flash_cache_file                  string
    db_flash_cache_size                  big integer 0
    db_flashback_retention_target        integer     1440
    07:47:20 SQL> show parameter shared_pool
    
    NAME                                 TYPE        VALUE
    ------------------------------------ ----------- ------------------------------
    shared_pool_reserved_size            big integer 100M
    shared_pool_size                     big integer 400M
    07:47:31 SQL>
    

    Как видно, параметр "db_flash_cache_file" не определён и наша база данных будет иметь всего две возможности кэшировать данные - используя кэш файловой системы ext3 на уровне ОС (около 6 Гб) и буфер базы данных (менее 200 Мб).

    В этом примере я не использую асинхронный или непосредственный ввод-вывод, параметр базы данных FILESYSTEMIO_OPTIONS установлен в NONE.

    Проверим размер схемы SOE, используемой для тестов:

    ..................... == Книга Премудрости Соломона == .........................
    === Глава 17, Стих 10 ===
    9 И хотя  никакие  устрашения  не  тревожили  их,  но,  преследуемые  брожениями
    ядовитых зверей и свистами  пресмыкающихся,  они  исчезали  от  страха,  боясь
    взглянуть даже на воздух, от которого никуда нельзя убежать,
    10 ибо   осуждаемое   собственным   свидетельством    нечестие    боязливо    и,
    преследуемое совестью, всегда придумывает ужасы.
    
    (b+/b-, c+/c-, +/-, *) >
    
    [oracle@OUL ft]$ sqlplus / as sysdba
    ...
    07:50:12 SQL> l
    1  select segment_type, count(*), sum(bytes) bytes
    2  from dba_segments
    3  where owner = 'SOE'
    4  group by segment_type
    5* order by segment_type, count(*)
    07:50:12 SQL> /
    
    SEGMENT_TYPE         COUNT(*)                    BYTES
    ------------------ ---------- ------------------------
    INDEX                      23           17,411,604,480
    TABLE                       9           10,388,242,432
    
    2 rows selected.
    
    Elapsed: 00:00:00.22
    07:50:13 SQL>
    

    Размер схемы подобран так, чтобы несколько ограничить кэширование данных файловой системой. Таблицы ORDERS и ORDER_ITEMS (и их индексы) не имеют секций и не помещаются в ext3 кэш полностью.

    "Одиночные" тесты запросов

    Рассмотрим как база данных выполняет запросы поодиночке. Для этого индивидуальный SQL будет выполняться из единственной SQL*Plus сессии пользователя SOE.

    Warehouse Orders Query, без использования Flash Cache

    ........... == Первое соборное послание святого апостола Петра == ..............
    === Глава 2, Стих 12 ===
    11 Возлюбленные!  прошу  вас,  как  пришельцев  и   странников,   удаляться   от
    плотских похотей, восстающих на душу,
    12 и провождать добродетельную жизнь  между  язычниками,  дабы  они  за  то,  за
    что злословят вас, как злодеев, увидя добрые дела  ваши,  прославили  Бога  в
    день посещения.
    
    (b+/b-, c+/c-, +/-, *) >
    
    [oracle@OUL ft]$ sqlplus
    ...
    08:10:54 SQL> show user
    USER is "SOE"
    08:11:16 SQL> set autotrace traceonly explain statistics
    08:11:39 SQL> l
    1  SELECT ORDER_MODE, ORDERS.WAREHOUSE_ID, SUM(ORDER_TOTAL), COUNT(1)
    2  FROM ORDERS, WAREHOUSES
    3  WHERE ORDERS.WAREHOUSE_ID = WAREHOUSES.WAREHOUSE_ID
    4  AND WAREHOUSES.WAREHOUSE_ID = 1 -- :B1
    5* GROUP BY CUBE(ORDERS.ORDER_MODE, ORDERS.WAREHOUSE_ID)
    08:11:40 SQL> /
    
    8 rows selected.
    
    Elapsed: 00:00:01.43
    
    Execution Plan
    ----------------------------------------------------------
    Plan hash value: 2868093223
    
    ----------------------------------------------------------------------------------------------------
    | Id  | Operation                       | Name             | Rows  | Bytes | Cost (%CPU)| Time     |
    ----------------------------------------------------------------------------------------------------
    |   0 | SELECT STATEMENT                |                  |     2 |    38 | 46938   (1)| 00:09:24 |
    |   1 |  SORT GROUP BY                  |                  |     2 |    38 | 46938   (1)| 00:09:24 |
    |   2 |   GENERATE CUBE                 |                  |     2 |    38 | 46938   (1)| 00:09:24 |
    |   3 |    SORT GROUP BY                |                  |     2 |    38 | 46938   (1)| 00:09:24 |
    |   4 |     NESTED LOOPS                |                  | 45045 |   835K| 46935   (1)| 00:09:24 |
    |*  5 |      INDEX UNIQUE SCAN          | WAREHOUSES_PK    |     1 |     4 |     1   (0)| 00:00:01 |
    |   6 |      TABLE ACCESS BY INDEX ROWID| ORDERS           | 45045 |   659K| 46934   (1)| 00:09:24 |
    |*  7 |       INDEX RANGE SCAN          | ORD_WAREHOUSE_IX | 47130 |       |   120   (1)| 00:00:02 |
    ----------------------------------------------------------------------------------------------------
    
    Predicate Information (identified by operation id):
    ---------------------------------------------------
    
    5 - access("WAREHOUSES"."WAREHOUSE_ID"=1)
    7 - access("ORDERS"."WAREHOUSE_ID"=1)
    
    
    Statistics
    ----------------------------------------------------------
    0  recursive calls
    0  db block gets
    44916  consistent gets
    42181  physical reads
    0  redo size
    925  bytes sent via SQL*Net to client
    524  bytes received via SQL*Net from client
    2  SQL*Net roundtrips to/from client
    2  sorts (memory)
    0  sorts (disk)
    8  rows processed
    
    08:11:44 SQL>
    

    Как видим, ничего неожиданного не происходит - запрос выполняется около 2х секунд, использует индексы и практически не использует буфер кэш базы данных (ввиду его мизерного размера).

    Sales Report Query, без использования Flash Cache

    ............ == Послание к Римлянам святого апостола Павла == .................
    === Глава 13, Стих 14 ===
    13 Как днем, будем вести  себя  благочинно,  не  _предаваясь_  ни  пированиям  и
    пьянству, ни сладострастию и распутству, ни ссорам и зависти;
    14 но облекитесь в  Господа  нашего  Иисуса  Христа,  и  попечения  о  плоти  не
    превращайте в похоти.
    
    (b+/b-, c+/c-, +/-, *) >
    
    [oracle@OUL ft]$ sqlplus
    ...
    08:34:03 SQL> l
    1  SELECT TT.ORDER_TOTAL, TT.SALES_REP_ID, TT.ORDER_DATE,
    2   CUSTOMERS.CUST_FIRST_NAME, CUSTOMERS.CUST_LAST_NAME
    3  FROM (
    4   SELECT ORDERS.ORDER_TOTAL, ORDERS.SALES_REP_ID, ORDERS.ORDER_DATE,
    5    ORDERS.CUSTOMER_ID, RANK()
    6     OVER (ORDER BY ORDERS.ORDER_TOTAL DESC) SAL_RANK
    7   FROM ORDERS
    8   WHERE ORDERS.SALES_REP_ID = 268 -- :B1
    9  ) TT,
    10  CUSTOMERS
    11  WHERE TT.SAL_RANK <= 10
    12* AND CUSTOMERS.CUSTOMER_ID = TT.CUSTOMER_ID
    08:34:04 SQL> /
    
    10 rows selected.
    
    Elapsed: 00:00:00.97
    
    Execution Plan
    ----------------------------------------------------------
    Plan hash value: 4228977748
    
    ------------------------------------------------------------------------------------------------------------
    | Id  | Operation                       | Name             | Rows  | Bytes |TempSpc| Cost (%CPU)| Time     |
    ------------------------------------------------------------------------------------------------------------
    |   0 | SELECT STATEMENT                |                  | 45045 |  3783K|       |   132K  (1)| 00:26:35 |
    |   1 |  NESTED LOOPS                   |                  |       |       |       |            |          |
    |   2 |   NESTED LOOPS                  |                  | 45045 |  3783K|       |   132K  (1)| 00:26:35 |
    |*  3 |    VIEW                         |                  | 45045 |  2859K|       | 42763   (1)| 00:08:34 |
    |*  4 |     WINDOW SORT PUSHED RANK     |                  | 45045 |  1143K|  1776K| 42763   (1)| 00:08:34 |
    |   5 |      TABLE ACCESS BY INDEX ROWID| ORDERS           | 45045 |  1143K|       | 42426   (1)| 00:08:30 |
    |*  6 |       INDEX RANGE SCAN          | ORD_SALES_REP_IX | 45045 |       |       |    97   (2)| 00:00:02 |
    |*  7 |    INDEX UNIQUE SCAN            | CUSTOMERS_PK     |     1 |       |       |     1   (0)| 00:00:01 |
    |   8 |   TABLE ACCESS BY INDEX ROWID   | CUSTOMERS        |     1 |    21 |       |     2   (0)| 00:00:01 |
    ------------------------------------------------------------------------------------------------------------
    
    Predicate Information (identified by operation id):
    ---------------------------------------------------
    
    3 - filter("TT"."SAL_RANK"<=10)
    4 - filter(RANK() OVER ( ORDER BY INTERNAL_FUNCTION("ORDERS"."ORDER_TOTAL") DESC )<=10)
    6 - access("ORDERS"."SALES_REP_ID"=268)
    7 - access("CUSTOMERS"."CUSTOMER_ID"="TT"."CUSTOMER_ID")
    
    
    Statistics
    ----------------------------------------------------------
    0  recursive calls
    0  db block gets
    43043  consistent gets
    42480  physical reads
    0  redo size
    1226  bytes sent via SQL*Net to client
    524  bytes received via SQL*Net from client
    2  SQL*Net roundtrips to/from client
    1  sorts (memory)
    0  sorts (disk)
    10  rows processed
    
    08:34:05 SQL>
    

    Для выполнения этого запроса, использующего аналитическую функцию, Оракл создал "на лету" динамическое представление. Используются индексы и физическое чтение с диска.

    Тесты с использованием Flash Cache

    Теперь задействуем Database Flash Cache и повторим запросы, проверяя статистику сессии нашего пользователя SOE.

    ..................... == Книга Премудрости Соломона == .........................
    === Глава 7, Стих 8 ===
    8 Я  предпочел  ее  скипетрам  и  престолам  и  богатство  почитал  за  ничто  в
    сравнении с нею;
    9 драгоценного камня я не сравнил с нею, потому  что  перед  нею  все  золото  -
    ничтожный песок, а серебро - грязь в сравнении с нею.
    
    (b+/b-, c+/c-, +/-, *) >
    
    [oracle@OUL ft]$ sqlplus / as sysdba
    ...
    08:41:19 SQL> alter system set db_flash_cache_file='/flash/oracle/flashfile.dbf' scope=spfile;
    
    System altered.
    
    Elapsed: 00:00:00.01
    08:41:34 SQL>
    08:42:10 SQL>  alter system set db_flash_cache_size=10G scope=spfile;
    
    System altered.
    
    Elapsed: 00:00:00.01
    08:42:21 SQL> startup force
    ORACLE instance started.
    
    Total System Global Area  626327552 bytes
    Fixed Size                  2230952 bytes
    Variable Size             432014680 bytes
    Database Buffers          184549376 bytes
    Redo Buffers                7532544 bytes
    Database mounted.
    Database opened.
    08:43:00 SQL> show parameter flash
    
    NAME                                 TYPE        VALUE
    ------------------------------------ ----------- ------------------------------
    db_flash_cache_file                  string      /flash/oracle/flashfile.dbf
    db_flash_cache_size                  big integer 10G
    db_flashback_retention_target        integer     1440
    08:43:15 SQL>
    

    Сейчас наш database buffer cache получил серьёзную "подпитку" - 10 Гб "вторичного" кэша на быстром RAID0 массиве, созданном "поверх" 4х твёрдотельных флэш модулей Sun Flash Accelerator F20. Заметьте что для простоты я задействую файловую систему ext3 и монтирую её как "/flash". Такой подход имеет свои недостатки. Производительность системы возрастёт если мы будем использовать Oracle ASM вместо файловой системы (т.е. параметр "db_flash_cache_file" получит значение '+FLASH', например).

    Повторим тесты с дополнительными 10 Гб "вторичного" кэша базы данных (который, тем не менее, медленнее чем RAM).

    Warehouse Orders Query, используя Flash Cache

    08:44:00 SQL> set autotrace traceonly explain statistics
    08:45:11 SQL> l
    1  SELECT ORDER_MODE, ORDERS.WAREHOUSE_ID, SUM(ORDER_TOTAL), COUNT(1)
    2  FROM ORDERS, WAREHOUSES
    3  WHERE ORDERS.WAREHOUSE_ID = WAREHOUSES.WAREHOUSE_ID
    4  AND WAREHOUSES.WAREHOUSE_ID = 1 -- :B1
    5* GROUP BY CUBE(ORDERS.ORDER_MODE, ORDERS.WAREHOUSE_ID)
    08:45:18 SQL> /
    
    8 rows selected.
    
    Elapsed: 00:00:01.90
    
    Execution Plan
    ----------------------------------------------------------
    Plan hash value: 2868093223
    
    ----------------------------------------------------------------------------------------------------
    | Id  | Operation                       | Name             | Rows  | Bytes | Cost (%CPU)| Time     |
    ----------------------------------------------------------------------------------------------------
    |   0 | SELECT STATEMENT                |                  |     2 |    38 | 46938   (1)| 00:09:24 |
    |   1 |  SORT GROUP BY                  |                  |     2 |    38 | 46938   (1)| 00:09:24 |
    |   2 |   GENERATE CUBE                 |                  |     2 |    38 | 46938   (1)| 00:09:24 |
    |   3 |    SORT GROUP BY                |                  |     2 |    38 | 46938   (1)| 00:09:24 |
    |   4 |     NESTED LOOPS                |                  | 45045 |   835K| 46935   (1)| 00:09:24 |
    |*  5 |      INDEX UNIQUE SCAN          | WAREHOUSES_PK    |     1 |     4 |     1   (0)| 00:00:01 |
    |   6 |      TABLE ACCESS BY INDEX ROWID| ORDERS           | 45045 |   659K| 46934   (1)| 00:09:24 |
    |*  7 |       INDEX RANGE SCAN          | ORD_WAREHOUSE_IX | 47130 |       |   120   (1)| 00:00:02 |
    ----------------------------------------------------------------------------------------------------
    
    Predicate Information (identified by operation id):
    ---------------------------------------------------
    
    5 - access("WAREHOUSES"."WAREHOUSE_ID"=1)
    7 - access("ORDERS"."WAREHOUSE_ID"=1)
    
    
    Statistics
    ----------------------------------------------------------
    1  recursive calls
    0  db block gets
    44916  consistent gets
    44627  physical reads
    0  redo size
    925  bytes sent via SQL*Net to client
    523  bytes received via SQL*Net from client
    2  SQL*Net roundtrips to/from client
    2  sorts (memory)
    0  sorts (disk)
    8  rows processed
    
    08:45:21 SQL>
    
    -- Проверим значения статистик этой сессии пользователя:
    consistent gets                                                       45241
    consistent gets - examination                                           134
    consistent gets from cache                                            45241
    consistent gets from cache (fastpath)                                   477
    flash cache insert skip: exists                                         996
    flash cache insert skip: not useful                                       2
    physical read IO requests                                             44635
    physical read bytes                                               345432064
    physical read flash cache hits                                         2468
    physical read requests optimized                                       2468
    physical read total IO requests                                       44635
    physical read total bytes                                         365649920
    physical read total bytes optimized                                20217856
    physical reads                                                        44635
    physical reads cache                                                  44635
    table fetch by rowid                                                  45352
    

    Обратите внимание - план выполнения не изменился, а статистика сессии показывает, что мы прочли всего лишь 5% данных из flash cache и количество физических чтений с диска возросло. Это может быть связано с тем, что наш flash cache был только что создан и не содержит нужных данных. По мере выполнения запросов наполнение кэша улучшится и больше данных сможет быть прочитано из флэш-памяти.

    Но как объяснить увеличение времени выполнения запроса на 470 ms? Кроме того, наша сессия прочла из датафайла "soe.dbf" менее 200 тысяч раз, а время синхронного чтения одиночного блока из этого файла уже исчисляется не миллисекундами, а единицами микросекунд. Очевидно, что перед нами результат работы кэша файловой системы ext3, что существенно улучшило время чтения с диска и косвенно восполнило недостатки малого database buffer cache.

    Тем не менее, работа кэша файловой системы не объясняет увеличения времени выполнения запроса. Очевидно, что дополнительное время ушло на чтение / обновление flash cache, что делает эту технологию непривлекательной для быстрых одиночных запросов на малых объёмах данных. В таких случаях предпочтение должно быть отдано увеличению размера оперативной памяти (а значит и database buffer cache), для достижения эффекта максимального кэширования данных в RAM.

    Проверим работу второго запроса с включённым flash cache.

    Sales Report Query, используя Flash Cache

    09:10:49 SQL> set autotrace traceonly explain statistics
    09:11:29 SQL> l
    1  SELECT TT.ORDER_TOTAL, TT.SALES_REP_ID, TT.ORDER_DATE,
    2   CUSTOMERS.CUST_FIRST_NAME, CUSTOMERS.CUST_LAST_NAME
    3  FROM (
    4   SELECT ORDERS.ORDER_TOTAL, ORDERS.SALES_REP_ID, ORDERS.ORDER_DATE,
    5    ORDERS.CUSTOMER_ID, RANK()
    6     OVER (ORDER BY ORDERS.ORDER_TOTAL DESC) SAL_RANK
    7   FROM ORDERS
    8   WHERE ORDERS.SALES_REP_ID = 268 -- :B1
    9  ) TT,
    10  CUSTOMERS
    11  WHERE TT.SAL_RANK <= 10
    12* AND CUSTOMERS.CUSTOMER_ID = TT.CUSTOMER_ID
    09:11:30 SQL> /
    
    10 rows selected.
    
    Elapsed: 00:00:01.06
    
    Execution Plan
    ----------------------------------------------------------
    Plan hash value: 4228977748
    
    ------------------------------------------------------------------------------------------------------------
    | Id  | Operation                       | Name             | Rows  | Bytes |TempSpc| Cost (%CPU)| Time     |
    ------------------------------------------------------------------------------------------------------------
    |   0 | SELECT STATEMENT                |                  | 45045 |  3783K|       |   132K  (1)| 00:26:35 |
    |   1 |  NESTED LOOPS                   |                  |       |       |       |            |          |
    |   2 |   NESTED LOOPS                  |                  | 45045 |  3783K|       |   132K  (1)| 00:26:35 |
    |*  3 |    VIEW                         |                  | 45045 |  2859K|       | 42763   (1)| 00:08:34 |
    |*  4 |     WINDOW SORT PUSHED RANK     |                  | 45045 |  1143K|  1776K| 42763   (1)| 00:08:34 |
    |   5 |      TABLE ACCESS BY INDEX ROWID| ORDERS           | 45045 |  1143K|       | 42426   (1)| 00:08:30 |
    |*  6 |       INDEX RANGE SCAN          | ORD_SALES_REP_IX | 45045 |       |       |    97   (2)| 00:00:02 |
    |*  7 |    INDEX UNIQUE SCAN            | CUSTOMERS_PK     |     1 |       |       |     1   (0)| 00:00:01 |
    |   8 |   TABLE ACCESS BY INDEX ROWID   | CUSTOMERS        |     1 |    21 |       |     2   (0)| 00:00:01 |
    ------------------------------------------------------------------------------------------------------------
    
    Predicate Information (identified by operation id):
    ---------------------------------------------------
    
    3 - filter("TT"."SAL_RANK"<=10)
    4 - filter(RANK() OVER ( ORDER BY INTERNAL_FUNCTION("ORDERS"."ORDER_TOTAL") DESC )<=10)
    6 - access("ORDERS"."SALES_REP_ID"=268)
    7 - access("CUSTOMERS"."CUSTOMER_ID"="TT"."CUSTOMER_ID")
    
    
    Statistics
    ----------------------------------------------------------
    160  recursive calls
    0  db block gets
    43043  consistent gets
    43034  physical reads
    0  redo size
    1226  bytes sent via SQL*Net to client
    523  bytes received via SQL*Net from client
    2  SQL*Net roundtrips to/from client
    46  sorts (memory)
    0  sorts (disk)
    10  rows processed
    
    09:11:32 SQL>
    
    Запрос выполнялся на 90 ms дольше и потребовал дополнительных чтений с диска.
    Статистика сессии показывает, что flash cache использовался даже менее
    эффективно, чем в первом запросе (total bytes / total bytes optimized).
    
    consistent gets                                              43150
    consistent gets - examination                                   55
    consistent gets from cache                                   43150
    consistent gets from cache (fastpath)                           92
    flash cache insert skip: exists                                 13
    flash cache insert skip: not useful                              1
    physical read IO requests                                    43035
    physical read bytes                                      342704128
    physical read flash cache hits                                1201
    physical read requests optimized                              1201
    physical read total IO requests                              43035
    physical read total bytes                                352542720
    physical read total bytes optimized                        9838592
    physical reads                                               43035
    physical reads cache                                         43035
    table fetch by rowid                                         45714
    

    Опять план выполнения остался тем же а время исполнения запроса увеличилось. Похоже что преимущества технологии Database Flash Cache проявляются только на больших наборах данных, значительно превышающих размер физической памяти сервера и под интенсивной нагрузкой OLTP транзакций, выполняемых одновременно большим количеством пользователей.

    Настало время использовать Swingbench для имитации именно такой нагрузки.

    Комплексные тесты запросов

    Начнём опять с проведения тестов без flash cache. Изменим необходимые параметры и перезапустим экземпляр базы данных.

    09:32:59 SQL> alter system reset db_flash_cache_file scope=spfile;
    
    System altered.
    
    Elapsed: 00:00:00.01
    09:33:12 SQL> c/db_flash_cache_file/db_flash_cache_size
    1* alter system reset db_flash_cache_size scope=spfile
    09:33:18 SQL> /
    
    System altered.
    
    Elapsed: 00:00:00.00
    09:33:19 SQL> startup force
    ORACLE instance started.
    
    Total System Global Area  626327552 bytes
    Fixed Size                  2230952 bytes
    Variable Size             432014680 bytes
    Database Buffers          184549376 bytes
    Redo Buffers                7532544 bytes
    Database mounted.
    Database opened.
    09:33:42 SQL> show parameter flash
    
    NAME                                 TYPE        VALUE
    ------------------------------------ ----------- ------------------------------
    db_flash_cache_file                  string
    db_flash_cache_size                  big integer 0
    db_flashback_retention_target        integer     1440
    09:33:46 SQL>
    

    При тестировании обратите внимание на Alert log базы данных - там не должно появляться сообщение "Active Session History (ASH) performed an emergency flush". При появлении таких сообщений увеличьте размер SGA и повторите тесты с меньшим числом swingbench пользователей - ASH emergency flush существенно замедляет систему.

    Параметры тестов

    Характеристики тестов задаются в файле "swingconfig.xml". Ниже приведены важные фрагменты моей конфигурации. Запуская тесты, используйте графический модуль "swingbench" и устанавливайте в его окне отметки "сохранять статистику" и "генерировать AWR snapshot" - позже это позволит вам легко определить интервал для AWR report.

    .............. == Соборное послание святого апостола Иакова == .................
    === Глава 4, Стих 4 ===
    4 Прелюбодеи и прелюбодейцы! не знаете  ли,  что  дружба  с  миром  есть  вражда
    против Бога? Итак, кто хочет быть другом миру, тот становится врагом Богу.
    
    (b+/b-, c+/c-, +/-, *) >
    
    [oracle@OUL ft]$ cat swingconfig.xml
    ...
    <Name>"Order Entry (PLSQL)"</Name>
    <Comment>""</Comment>
    <Connection>
    <UserName>soe</UserName>
    <Password>soe</Password>
    <ConnectString>//OUL/DB</ConnectString>
    <DriverType>Oracle jdbc Driver</DriverType>
    <Properties>
    <Property Key="TcpNoDelay">true</Property>
    <Property Key="StatementCaching">0</Property>
    </Properties>
    </Connection>
    <Load>
    <NumberOfUsers>20</NumberOfUsers>
    <MinDelay>100</MinDelay>
    <MaxDelay>200</MaxDelay>
    <QueryTimeout>120</QueryTimeout>
    <MaxTransactions>-1</MaxTransactions>
    <RunTime>00:10</RunTime>
    <LogonGroupCount>1</LogonGroupCount>
    <LogonDelay>0</LogonDelay>
    <LogOutPostTransaction>false</LogOutPostTransaction>
    <WaitTillAllLogon>true</WaitTillAllLogon>
    <StatsCollectionStart>0:0</StatsCollectionStart>
    <StatsCollectionEnd>0:0</StatsCollectionEnd>
    <ConnectionRefresh>0</ConnectionRefresh>
    <TransactionList>
    <Transaction>
    <Id>Sales Rep Query</Id>
    <ShortName>SQ</ShortName>
    <ClassName>com.dom.benchmarking.swingbench.plsqltransactions.SalesRepsOrdersQuery</ClassName>
    <Weight>50</Weight>
    <Enabled>true</Enabled>
    </Transaction>
    <Transaction>
    <Id>Warehouse Query</Id>
    <ShortName>WQ</ShortName>
    <ClassName>com.dom.benchmarking.swingbench.plsqltransactions.WarehouseOrdersQuery</ClassName>
    <Weight>50</Weight>
    <Enabled>true</Enabled>
    </Transaction>
    </TransactionList>
    <EnvironmentVariables>
    <Variable Key="SOE_NAMESDATA_LOC">data/names.txt</Variable>
    <Variable Key="SOE_PRODUCTSDATA_LOC">data/productids.txt</Variable>
    <Variable Key="SOE_NLSDATA_LOC">data/nls.txt</Variable>
    </EnvironmentVariables>
    </Load>
    ...
    

    Комплексный тест, без использования Flash Cache

    Проводить такое тестирование значительно проще - всё, что требуется - это запустить программу "swingbench", проверить конфигурацию, прочитанную из XML файла, поставить флажки для сбора статистики и AWR snapshots и нажать кнопку "play" в левом верхнем углу окна программы.

    После того, как все пользователи подключатся к базе данных, начнётся выполнение тестов - каждая сессия будет последовательно выполнять оба запроса - Warehouse Orders Query и Sales Report Query, без использования database flash cache функции. Как мы помним, время выполнения каждого из этих запросов поодиночке не превышало 2х секунд. Дадим программе стабилизироваться и посмотрим на экран выполнения тестов.

    Мы видим, что время отклика транзакций увеличилось до 37 секунд, при этом в самом начале теста первые транзакции выполнялись около 5 минут. Некоторые транзакции выполняются быстрее (около 9 секунд), некоторые дольше (до минуты). Большой скачок времени отклика в начале теста (с 341 секунды до 38 секунд) объясним работой всё того же кэша файловой системы ext3. Но даже при эффективной работе файловой системы среднее время транзакции составило 22 секунды:

    <Overview>
    <BenchmarkName>"Order Entry (PLSQL)"</BenchmarkName>
    <Comment>""</Comment>
    <TimeOfRun>Jul 13, 2012 1:25:57 PM</TimeOfRun>
    <TotalRunTime>0:10:09</TotalRunTime>
    <TotalLogonTime>0:00:00</TotalLogonTime>
    <TotalCompletedTransactions>556</TotalCompletedTransactions>
    <TotalFailedTransactions>0</TotalFailedTransactions>
    <AverageTransactionsPerSecond>0.91</AverageTransactionsPerSecond>
    <MaximumTransactionRate>131</MaximumTransactionRate>
    </Overview>
    <Configuration>
    <NumberOfUsers>20</NumberOfUsers>
    <MinimumThinkTime>100</MinimumThinkTime>
    <MaximumThinkTime>200</MaximumThinkTime>
    <ConnectString>//OUL/DB</ConnectString>
    <TimingsIn>milliseconds</TimingsIn>
    </Configuration>
    <DMLResults>
    <SelectStatements>0</SelectStatements>
    <InsertStatements>0</InsertStatements>
    <UpdateStatements>0</UpdateStatements>
    <DeleteStatements>0</DeleteStatements>
    <CommitStatements>0</CommitStatements>
    <RollbackStatements>0</RollbackStatements>
    </DMLResults>
    <TransactionResults>
    <Result id="Sales Rep Query">
    <AverageResponse>18916</AverageResponse>
    <MinimumResponse>6054</MinimumResponse>
    <MaximumResponse>342837</MaximumResponse>
    <TransactionCount>276</TransactionCount>
    <FailedTransactionCount>0</FailedTransactionCount>
    </Result>
    <Result id="Warehouse Query">
    <AverageResponse>24135</AverageResponse>
    <MinimumResponse>6256</MinimumResponse>
    <MaximumResponse>342323</MaximumResponse>
    <TransactionCount>280</TransactionCount>
    <FailedTransactionCount>0</FailedTransactionCount>
    </Result>
    </TransactionResults>
    

    Итак, тест без использования Flash Cache показал:

  • всего 556 транзакций было выполнено за 10 минут;
  • в среднем 0.91 транзакция была выполнена за секунду;
  • максимальное число транзакций в минуту было 131;
  • среднее время отклика для Sales Report составило 19 секунд;
  • максимальное время отклика для Sales Report составило 343 секунды;
  • всего 276 Sales Report транзакций было обработано за 10 минут;
  • среднее время отклика для Warehouse Report составило 24 секунды;
  • максимальное время отклика для Warehouse Report составило 342 секунды;
  • всего 280 Warehouse Report транзакций было обработано за 10 минут;
  • основными wait events были "db file sequential read" и "db file scattered read".

    Комплексный тест, с использованием Flash Cache

    Сконфигурируем базу данных для использования 10-ти Гб "вторичного" флэш-кэша так, как показано выше и запустим те же самые тесты.

    Использование flash cache позволило нам:

  • сгладить начальный "скачок" во времени отклика транзакций;
  • сократить время выполнения запросов;
  • удвоить количество транзакций в единицу времени.

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

    <Overview>
    <BenchmarkName>"Order Entry (PLSQL)"</BenchmarkName>
    <Comment>""</Comment>
    <TimeOfRun>Jul 13, 2012 1:11:49 PM</TimeOfRun>
    <TotalRunTime>0:10:07</TotalRunTime>
    <TotalLogonTime>0:00:00</TotalLogonTime>
    <TotalCompletedTransactions>926</TotalCompletedTransactions>
    <TotalFailedTransactions>0</TotalFailedTransactions>
    <AverageTransactionsPerSecond>1.53</AverageTransactionsPerSecond>
    <MaximumTransactionRate>100</MaximumTransactionRate>
    </Overview>
    <Configuration>
    <NumberOfUsers>20</NumberOfUsers>
    <MinimumThinkTime>100</MinimumThinkTime>
    <MaximumThinkTime>200</MaximumThinkTime>
    <ConnectString>//OUL/DB</ConnectString>
    <TimingsIn>milliseconds</TimingsIn>
    </Configuration>
    <DMLResults>
    <SelectStatements>0</SelectStatements>
    <InsertStatements>0</InsertStatements>
    <UpdateStatements>0</UpdateStatements>
    <DeleteStatements>0</DeleteStatements>
    <CommitStatements>0</CommitStatements>
    <RollbackStatements>0</RollbackStatements>
    </DMLResults>
    <TransactionResults>
    <Result id="Sales Rep Query">
    <AverageResponse>12752</AverageResponse>
    <MinimumResponse>6910</MinimumResponse>
    <MaximumResponse>15918</MaximumResponse>
    <TransactionCount>445</TransactionCount>
    <FailedTransactionCount>0</FailedTransactionCount>
    </Result>
    <Result id="Warehouse Query">
    <AverageResponse>12935</AverageResponse>
    <MinimumResponse>5912</MinimumResponse>
    <MaximumResponse>15956</MaximumResponse>
    <TransactionCount>481</TransactionCount>
    <FailedTransactionCount>0</FailedTransactionCount>
    </Result>
    </TransactionResults>
    

    Итак, тест с Flash Cache показал:

  • всего 926 транзакций было выполнено за 10 минут;
  • в среднем 1.53 транзакции было выполнено за секунду;
  • максимальное число транзакций в минуту было 100;
  • среднее время отклика для Sales Report составило 13 секунд;
  • максимальное время отклика для Sales Report составило 16 секунд;
  • всего 445 Sales Report транзакций было обработано за 10 минут;
  • среднее время отклика для Warehouse Report составило 13 секунды;
  • максимальное время отклика для Warehouse Report составило 16 секунд;
  • всего 481 Warehouse Report транзакция была обработана за 10 минут;
  • основным wait event был "db flash cache single block physical read".

    Сравнение AWR reports показало, что использование Database Flash Cache позволило уменьшить время физического синхронного чтения одиночного блока с диска с 25 микросекунд (без флэша) до 7 микросекунд - то есть приблизительно в 4 раза. При этом количество ожиданий в очереди на запись (IO Writes - Buffer Waits) сократилось более чем в 10 раз - с 29 тысяч до 2 тысяч ожиданий. Время физической записи на диск (Av Buf Wt) уменьшилось с 45 до 11 миллисекунд.

    Заключение

    Использование Database Flash Cache является эффективным средством улучшения общей производительности системы с недостаточным объёмом оперативной памяти (и других аппаратных средств). Применение технологии целесообразно в случае значительного количества одновременно выполняемых OLTP запросов и на больших объёмах данных. Без всяких дополнительных настроек системы нам удалось в два раза улучшить производительность устаревшего сервера базы данных, избежать необходимости замены аппаратных компонентов и покупки дополнительных лицензий. Размещение Flash Cache в группе ASM может привести к значительно большему выигрышу в производительности базы данных.

    Спасибо что зашли,

    Будьте благословенны!
    Денис