A maioria das pessoas provavelmente conhece o novo recurso do Oracle 12.1.0.2, a opção de banco de dados InMemory. Ao usar essa opção no Oracle RAC, o DBA pode especificar a cláusula DUPLICATE para que um objeto seja duplicado entre o armazenamento de colunas InMemory em todas as instâncias. Esta cláusula é para os sistemas projetados da Oracle, como o Exadata. No entanto, em sistemas não projetados, a Oracle parece permitir essa cláusula, mas não funciona como se poderia esperar. Para ilustrar, siga este exemplo, que foi executado em um banco de dados RAC de dois nós no meu MacBook Pro com VirtualBox... definitivamente não é um sistema projetado.
Primeiro, uma tabela é criada e depois alterada para INMEMORY DUPLICATE.
SQL> create table db_objs 2 as select * From dba_objects;
Table created.
SQL> alter table db_objs inmemory duplicate;
Table altered.
A definição desta cláusula não deveria gerar um erro, pois este é um sistema não projetado?
A tabela é verificada para mostrar que DUPLICATE está especificado.
SQL> select inmemory,inmemory_duplicate 2 from user_tables where table_name='DB_OBJS';
INMEMORY INMEMORY_DUPL -------- ------------- ENABLED DUPLICATE
Com um simples “select *” a tabela é emitida na instância 1. Podemos então verificar se a tabela é InMemory.
SQL> select inst_id,owner,segment_name,populate_status,inmemory_duplicate 2 from gv$im_segments;
INST_ID OWNER SEGMENT_NA POPULATE_ INMEMORY_DUPL ---------- ---------- ---------- --------- ------------- 1 SCOTT DB_OBJS COMPLETED DUPLICATE
Observe que os resultados acima mostram que o segmento está apenas na instância 1. A mesma tabela é consultada na instância 2, mas a consulta GV$IM_SEGMENTS ainda mostra apenas a instância 1.
Da instância 1:
SQL> select avg(object_id) from db_objs;
AVG(OBJECT_ID) -------------- 11095.2049
Elapsed: 00:00:00.01
Execution Plan ---------------------------------------------------------- Plan hash value: 1349857420
---------------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
---------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 1 | 5 | 10 (0)| 00:00:01 |
| 1 | SORT AGGREGATE | | 1 | 5 | | |
| 2 | TABLE ACCESS INMEMORY FULL| DB_OBJS | 21319 | 104K| 10 (0)| 00:00:01 |
---------------------------------------------------------------------------------------
Da instância 2:
SQL> select avg(object_id) from db_objs;
AVG(OBJECT_ID) -------------- 11095.2049
Elapsed: 00:00:00.03
Execution Plan ---------------------------------------------------------- Plan hash value: 1349857420
---------------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
---------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 1 | 5 | 4 (0)| 00:00:01 |
| 1 | SORT AGGREGATE | | 1 | 5 | | |
| 2 | TABLE ACCESS INMEMORY FULL| DB_OBJS | 21319 | 104K| 4 (0)| 00:00:01 |
---------------------------------------------------------------------------------------
Portanto, de qualquer instância, a tabela foi acessada INMEMORY. Mas podemos ver que apenas a instância 1 possui o segmento InMemory.
Todos os sinais apontam para a cláusula DUPLICATE como funcionando em um sistema não projetado, o que sabemos ser um erro. DBA_TABLES parece indicar que DUPLICATE está em jogo aqui. O Plano Explicar fornece concorrência. Mas GV$IM_SEGMENTS discorda e mostra que DUPLICATE não está funcionando neste sistema.