Oracle mechanics

14.07.2015

Deduplicate LOB

Filed under: Блокировки,Oracle — Игорь Усольцев @ 01:17
Tags: ,

Разочаровал способ реализации в Oracle killer-фичи версии 11g — Deduplicate LOB через обычный странный UNIQUE индекс, который значительно ограничивает возможности транзакционного использования, в частности, конкурентного заполнения таблицы дублирующими LOB-ами

SQL> CREATE TABLE deduplicate_clob (clob_data  CLOB)
  2  LOB(clob_data) STORE AS SECUREFILE dedup_lob( DEDUPLICATE ENABLE STORAGE IN ROW )
  3  tablespace USERS
  4  /
 
Table created

SQL> -- индекс вместе с LOB-сегментом создаются сразу по созданию таблицы:
SQL> select * from dba_indexes where table_name = 'DEDUPLICATE_CLOB';
 
OWNER  INDEX_NAME                INDEX_TYPE  TABLE_NAME        UNIQUENESS COMPRESSION   LOGGING STATUS  GENERATED VISIBILITY SEGMENT_CREATED INDEXING
------ ------------------------- ----------- ----------------- ---------- ------------- ------- ------- --------- ---------- --------------- --------
SCOTT  SYS_IL0000105054C00001$$  LOB         DEDUPLICATE_CLOB  UNIQUE     DISABLED      YES     VALID   Y         VISIBLE    YES             FULL

SQL> -- , однако, для случая ENABLE STORAGE IN ROW конкурентная вставка коротких LOB-дублей допускается:
SQL> insert into deduplicate_clob (clob_data) values ('test CLOB data'); -- в 1-й сессии без COMMIT-а
 
1 row inserted

SQL> -- и во 2-й сессии:
SQL> insert into deduplicate_clob (clob_data) values ('test CLOB data');
 
1 row inserted

SQL> -- при этом обе сессии вполне успешно получают две уникальные блокировки (неожиданно на разные ресурсы):
SQL> select * from v$lock where type = 'TX';
 
  SID TYPE        ID1        ID2      LMODE    REQUEST      CTIME      BLOCK     CON_ID
----- ---- ---------- ---------- ---------- ---------- ---------- ---------- ----------
  355 TX       327699       6328          6          0         46          0          0
  371 TX        65547       5571          6          0         52          0          0

SQL> -- - т.е. уникальность индекса не задействована, и, как следствие, в вышеописанном случае STORAGE IN ROW дедубликация в смысле экономии места практически не функционирует (как и продекларированная уникальность LOB-индекса)
SQL>
SQL> -- Если же при создании определить свойства LOB как DEDUPLICATE DISABLE STORAGE IN ROW, или же, не пересоздавая таблицу, попытаться одновременно в 2-х сессиях вставить в LOB длинные значения:
SQL> insert into deduplicate_clob (clob_data) values (rpad('test CLOB data',5000));
 
1 row inserted

SQL> -- получаем рудименты классического уникального индекса (проявляющиеся только при заполнении LOB-сегмента):
SQL> select * from v$lock where type = 'TX';
 
  SID TYPE        ID1        ID2      LMODE    REQUEST      CTIME      BLOCK     CON_ID
----- ---- ---------- ---------- ---------- ---------- ---------- ---------- ----------
  371 TX       458758       6029          6          0         16          1          0
  355 TX       458758       6029          0          4          5          0          0

SQL> -- с предсказуемым ожиданием на этом самом индексе:
SQL> @lock_tree
 
BLOCKING_TREE     USERNAME  EVENT                          REQ_OBJECT                           SECS_IN_WAIT BLOCK_SESSTAT SQL_TEXT                                                                       P1TEXT
----------------- --------- ------------------------------ ------------------------------------ ------------ ------------- ------------------------------------------------------------------------------ -------------------
INST#1 SID#371    SCOTT     SQL*Net message from client    LOB SCOTT.DEDUP_LOB                           604 NO HOLDER                                                                                    driver id driver id
  INST#1 SID#355  SCOTT     enq: TX - row lock contention  INDEX SCOTT.SYS_IL0000105054C00001$$          593 VALID         insert into deduplicate_clob (clob_data) values (rpad('test CLOB data',5000))  name|mode TX 4

SQL> -- - но в этом случае дедубликация действительно работает!

5 комментариев »

  1. Ну так надо же ораклу как-то дубликаты определять ) В принципе lobindex и с keep duplcates будет уникальный, но в случае deduplicate, он работает по хэшам от значений, так что в довесок, наверное, есть еще шанс и на коллизии нарываться :)

    комментарий от Sayan Malakshinov — 14.07.2015 @ 03:00 | Ответить

    • Ссылка на краткое описание от Riyaj Shamsudin’a: https://orainternals.files.wordpress.com/2008/03/oracle-11g-performance-features_riyaj_doc.pdf

      комментарий от Sayan Malakshinov — 14.07.2015 @ 03:15 | Ответить

    • Дубликаты определять как-то нужно, оно конечно, но легко могли бы и без блокировок обойтись)
      А так получается, что не работающая дедубликация для LOB IN ROW — это нормально, а если в LOB-индексе несколько ключей неиспользуемых останется — это большая проблема! ;)
      Ведь по назначению, дедубликация — для экономного ХРАНЕНИЯ, которое предполагает наполнение, которое, в свою очередь, может быть (и непременно будет) конкурентным!
      Огорчило отсутствие стратегического мЫшления)

      комментарий от Игорь Усольцев — 14.07.2015 @ 09:53 | Ответить

    • Скорее всего они реализовали наиболее очевидным способом со счетчиком ссылок:

      ROW—-
      \
      ROW—— (REFCNT) -> BLOB
      /
      ROW—-

      При такой схеме при добавлении новой строки он делает условный update blob_data set REFCNT = REFCNT + 1 where blob_hash = hash(blob)
      Это приводит к тому, что две вставки в исходную таблицу с одинаковыми BLOB-ами будут ждать друг друга чтобы обновить REFCNT.

      Можно было бы реализовать схему без REFCNT, но тогда нужен механизм «сбора мусора».

      комментарий от Дмитрий Балабанов — 04.08.2015 @ 22:09 | Ответить

      • Похоже, Дима,
        а учитывая периодическую необходимость упорядочивания пространства, занимаемого активно модифицируемыми LOB-сегментами (shrink space), такой дополнительный «сбор мусора» выглядел бы вполне гармонично ;)

        комментарий от Игорь Усольцев — 20.08.2015 @ 00:30 | Ответить


RSS feed for comments on this post. TrackBack URI

Добавить комментарий

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

Логотип WordPress.com

Для комментария используется ваша учётная запись WordPress.com. Выход / Изменить )

Фотография Twitter

Для комментария используется ваша учётная запись Twitter. Выход / Изменить )

Фотография Facebook

Для комментария используется ваша учётная запись Facebook. Выход / Изменить )

Google+ photo

Для комментария используется ваша учётная запись Google+. Выход / Изменить )

Connecting to %s

Блог на WordPress.com.

%d такие блоггеры, как: