Sie sind auf Seite 1von 140

Oracle Database

In-Memory Workshop
Student Guide
Version 1.1
{11/07/2014}

Oracle Database In-Memory Workshop

SOFTWARE.HARDWARE.COMPLETE

CHANGE LOG
Author

Organization

Date

Version

Comments

Maqsood Alam

Product Dev.

Oct 06, 2014

1.0

Initial creation

Maqsood Alam

Product Dev.

Nov 07, 2014

1.1

Updates to lab 6,8

2014 Oracle Corporation. All Rights Reserved.

Page 2

Oracle Database In-Memory Workshop

SOFTWARE.HARDWARE.COMPLETE

DISCLAIMER
Unless explicitly identified as such, the sample code here is not certified or supported by Oracle; it is intended for
educational or testing purposes only. The code samples may be modified but not redistributed.
This document is intended for attendees of the workshop for their private use. It is not to be sold, distributed to
others, or posted on internal or external web sites without the written consent of the Oracle Corporation.
Copyright 2014, Oracle. All rights reserved.
This documentation contains proprietary information of Oracle Corporation. It is provided under a license
agreement containing restrictions on use and disclosure and is also protected by copyright law. Reverse
engineering of the software is prohibited. If this documentation is delivered to a U.S. Government Agency of the
Department of Defense, then it is delivered with Restricted Rights and the following legend is applicable:
Restricted Rights Legend
Use, duplication or disclosure by the Government is subject to restrictions for commercial computer software and
shall be deemed to be Restricted Rights software under Federal law, as set forth in subparagraph (c)(1)(ii) of
DFARS 252.227-7013, Rights in Technical Data and Computer Software (October 1988).
This material or any portion of it may not be copied in any form or by any means without the express prior written
permission of Oracle Corporation. Any other copying is a violation of copyright law and may result in civil and/or
criminal penalties. If this documentation is delivered to a U.S. Government Agency not within the Department of
Defense, then it is delivered with Restricted Rights, as defined in FAR 52.227-14, Rights in Data-General,
including Alternate III (June 1987).
The information in this document is subject to change without notice. If you find any problems in the
documentation, please report them to the respective trainers for the workshop.
Oracle Corporation does not warrant that this document is error-free. Oracle and all references to Oracle Products
are trademarks or registered trademarks of Oracle Corporation. All other products or company names are used
for identification purposes only, and may be trademarks of their respective owners.

2014 Oracle Corporation. All Rights Reserved.

Page 3

Oracle Database In-Memory Workshop

SOFTWARE.HARDWARE.COMPLETE

TABLE OF CONTENTS
1. WORKSHOP OVERVIEW ........................................................................................................................................... 6
1.1. ABOUT THE ORACLE DATABASE IN-MEMORY OPTION .............................................................................................. 6
1.2. ABOUT THE VM ......................................................................................................................................................... 10
1.3. WORKSHOP LAB HARDWARE/SOFTWARE REQUIREMENTS .................................................................................. 12
1.4. VM ENVIRONMENT INSTALLATION .......................................................................................................................... 13
1.5. START THE DATABASE AND LISTENER ..................................................................................................................... 17
1.6. CONVENTIONS USED IN THIS MANUAL ..................................................................................................................... 17
2. ENABLING THE IN-MEMORY COLUMN STORE ............................................................................................... 19
2.1. IN-MEMORY AREA OVERVIEW ................................................................................................................................. 19
2.2. VERIFY IN-MEMORY AREA CONFIGURATION ........................................................................................................... 20
2.3. ENABLE THE IN-MEMORY COLUMN STORE ............................................................................................................. 21
2.4. INITIALIZATION PARAMETERS RELATED TO IM COLUMN STORE .......................................................................... 23
2.5. SUMMARY ................................................................................................................................................................... 26
3. ENABLING OBJECTS TO USE THE IM COLUMN STORE ................................................................................. 27
3.1. THE IN-MEMORY CLAUSE ......................................................................................................................................... 27
3.2. ENABLING A NEW TABLE .......................................................................................................................................... 29
3.3. ENABLING AN EXISTING TABLE WITH PRIORITY HIGH ........................................................................................... 30
3.4. ENABLING TABLE COLUMNS ..................................................................................................................................... 31
3.5. DISABLING A TABLE .................................................................................................................................................. 35
3.6. ENABLING AND DISABLING A TABLESPACE .............................................................................................................. 36
3.7. USING THE INMEMORY_CLAUSE_DEFAULT INSTANCE PARAMETER ....................................................................... 40
3.8. SUMMARY ................................................................................................................................................................... 43
4. POPULATING THE IM COLUMN STORE ............................................................................................................ 45
4.1. POPULATING BY QUERYING THE OBJECT ................................................................................................................. 45
4.2. POPULATING USING DBMS_INMEMORY .............................................................................................................. 48
4.3. POPULATING AUTOMATICALLY USING THE PRIORITY CLAUSE .............................................................................. 50
4.4. CONSIDERATIONS FOR RAC ...................................................................................................................................... 53
4.5. SUMMARY ................................................................................................................................................................... 54

2014 Oracle Corporation. All Rights Reserved.

Page 4

Oracle Database In-Memory Workshop

SOFTWARE.HARDWARE.COMPLETE

5. IN-MEMORY COLUMNAR COMPRESSION ......................................................................................................... 55


5.1. COMPRESSING OBJECTS IN-MEMORY ....................................................................................................................... 56
5.2. COMPRESS TABLESPACE FOR IN-MEMORY .............................................................................................................. 64
5.3. USING COMPRESSION ADVISOR ................................................................................................................................ 69
5.4. SUMMARY ................................................................................................................................................................... 72
6. QUERYING THE IM COLUMN STORE .................................................................................................................. 73
6.1. POPULATE RTL TABLES INTO IM COLUMN STORE ................................................................................................. 73
6.2. RUNNING A SIMPLE AGGREGATION QUERY ............................................................................................................. 76
6.3. IM COLUMN STORE EXECUTION PLANS AND STATISTICS ....................................................................................... 78
6.4. QUERY USING A FILTER ............................................................................................................................................. 84
6.5. QUERY USING MULTIPLE FILTERS ........................................................................................................................... 87
6.6. QUERY USING NON-EQUALITY PREDICATE ............................................................................................................. 90
6.7. SUMMARY ................................................................................................................................................................... 91
7. IN-MEMORY JOINS AND AGGREGATION .......................................................................................................... 93
7.2. SUMMARY ................................................................................................................................................................. 107
8. DML AND THE IM COLUMN STORE .................................................................................................................. 109
8.1. BULK DATA LOADS .................................................................................................................................................. 109
8.2. TRANSACTION PROCESSING .................................................................................................................................... 121
8.3. SUMMARY ................................................................................................................................................................. 134
9. DATA PUMP AND THE IM COLUMN STORE ................................................................................................... 135
9.1. IMPORTING IN-MEMORY DATABASE OBJECTS ...................................................................................................... 135
9.2. OVERRIDING THE IN-MEMORY CLAUSE OF DATABASE OBJECTS .......................................................................... 139
9.3. SUMMARY ................................................................................................................................................................. 140

2014 Oracle Corporation. All Rights Reserved.

Page 5

Oracle Database In-Memory Workshop

1.
1.1.

SOFTWARE.HARDWARE.COMPLETE

WORKSHOP OVERVIEW
ABOUT THE ORACLE DATABASE IN-MEMORY OPTION

Oracle Database has traditionally stored data in a row format in which each new transaction or
record stored in the row-format database is represented as a new row in a table. A row in a
row format database is made up of multiple columns, with each column representing a different
attribute about a record. The row format database is ideal for online transaction systems, as it
allows quick access to all of the columns in a record. All data for a given record are kept
together, both in-memory (i.e. buffer cache) and on-storage.
The Oracle Database In-Memory option introduces an additional format called the columnar or
the column format for representing table data. The column format stores each of the attributes
of a transaction or record in a separate column structure. A column format is ideal for analytics,
as it allows for faster data retrieval when only a few columns are selected and the query
requires a large portion of data to process results.
With the introduction of Oracle Database In-Memory option, a single database can now
efficiently support mixed workloads by delivering optimal performance for transactions while
simultaneously supporting real-time analytics and reporting workloads. This is possible due to
this "dual-format" architecture that enables data to be maintained in both, i.e. the existing
Oracle row format (buffer cache) for OLTP operations, and a new purely in-memory column
format optimized for analytical processing.
The In-Memory column store (or the IM column store) is the name given to the memory
structures that stores the column format database. The IM column store is an optional portion
of the system global area (SGA) and stores the column format copies of tables, table
partitions, and materialized views. In contrast to the other parts of the SGA, the data in IM
column store is populated by column rather than row. The IM column store only exists in
memory, and is one of the key components of the Oracle Database In-Memory option.
Figure 1.1 shows three tables stored in the IM column store: customers, products, and sales.
As you can see, the IM column store stores the data by column rather than row.

2014 Oracle Corporation. All Rights Reserved.

Page 6

Oracle Database In-Memory Workshop

SOFTWARE.HARDWARE.COMPLETE

Figure 1.1 - Oracles unique dual-format memory architecture


Note: The dual-format architecture does not double memory requirements. The in-memory
column format should be sized to accommodate the objects that must be stored in memory.
The buffer cache on the other hand, has been optimized for decades to run effectively with a
much smaller size than the size of the database. In practice, it is expected that the dual-format
architecture will impose less than a 20% overhead in terms of total memory requirements. This
is a small price to pay for gaining optimal performance at all times for all workloads.

1.1.1.

DUAL MEMORY FORMATS: COLUMNAR AND ROW

When fetching data, Oracle Database can read either the IM column store or the database
buffer cache, or both within the same query. The Oracle Optimizer is fully aware of the column
2014 Oracle Corporation. All Rights Reserved.

Page 7

Oracle Database In-Memory Workshop

SOFTWARE.HARDWARE.COMPLETE

format. It automatically routes analytic queries to the column format and OLTP operations
(such as primary key lookups) to the row format, ensuring outstanding performance and
complete data consistency for all workloads without any application changes.
As the IM column store is only stored in memory, it does not affect the format of data stored in
data files or in the buffer cache, nor does it affect undo, online redo logging, and so on. Also,
all on-disk data format for permanent, heap-organized tables is supported by the IM column
store.
The database processes DML modifications in the same way regardless of whether the IM
column store is in use: by updating the buffer cache, online redo log, undo tablespace, and so
on. However, the database uses an internal mechanism to track changes and ensure that the
IM column store is consistent with the rest of the database.
With Oracles unique approach, there remains a single copy of the table on storage, so there
are no additional storage costs or synchronization issues. The database maintains full
transactional consistency between the row and the columnar formats, just as it maintains
consistency between tables and indexes.
For example, if the SALES table resides in the IM column store (see Figure 1.1), and if a row in
SALES is updated, then the database automatically ensures the copy of the SALES table in the
IM column store is kept transactionally consistent. Due to this synchronization, a query that
accesses the IM column store always returns the same results for a query that accesses the
row store.

1.1.2.

BENEFITS OF THE IM COLUMN STORE

The IM column store enables the database to perform scans, joins, and aggregates much
faster than when it uses the on-disk row format. In particular, the IM column store is useful for:
Scanning many rows and applying filters that use operators such as =, <, >, and IN
Querying a subset of columns in a table, for example, selecting 5 of 100 columns
Accelerating joins by converting predicates on small dimension tables into filters on a
large fact table
2014 Oracle Corporation. All Rights Reserved.

Page 8

Oracle Database In-Memory Workshop

SOFTWARE.HARDWARE.COMPLETE

Business applications, ad-hoc analytic queries, and data warehouse workloads benefit most.
Pure OLTP databases that perform short transactions using index lookups benefit less.
The IM column store also provides the following advantages:
All existing database features are supported, including High Availability features.
No application changes are required as the optimizer automatically takes advantage of
the columnar format.
Configuration is simple. The INMEMORY_SIZE initialization parameter (described later)
specifies the amount of memory reserved for use by the IM column store. DDL
statements specify the tablespaces, tables, partitions, or columns that would be eligible
to be read into the IM column store.
The in-memory persistent data can be compressed using a variety of techniques to
increase the effective memory bandwidth, thereby allowing more data to be read by
sessions. Compression is optimized for query performance.
Fewer indexes, materialized views, and OLAP cubes are required. The reduction in the
number of pre-built objects results in reduced storage space and significantly less
processing overhead.
The IM column store does not improve performance for the following types of operations:
Queries with complex predicates
Queries that select a large number of columns
Queries that return a large number of rows
Queries with multiple large table joins
Also, a database object cannot be populated in the IM column store if it is owned by SYS or if it
is stored in the SYSTEM or SYSAUX tablespace.

2014 Oracle Corporation. All Rights Reserved.

Page 9

Oracle Database In-Memory Workshop

1.2.

SOFTWARE.HARDWARE.COMPLETE

ABOUT THE VM

The lab environment for the workshop is built using Oracle VirtualBox VM. The VirtualBox VM
contains the complete software stack required to run all lessons contained in this manual.
Having a preinstalled and self-contained VM environment saves valuable time in class, and
helps avoid environment misconfiguration issues. Also, the VM gives you the ability to install
additional software (after the workshop of course!), such as the client application, to test out
Oracle Database 12c features in conjunction with a real-world application. Or you could use it
as a training environment to learn more about Oracle Database 12c.
The supplied Oracle VirtualBox VM is a complete and fully integrated environment, and
contains all the required software and data to run various scenarios for the lab lessons. All labs
will be run within the VirtualBox VM environment.
The following software components are installed and configured within the VM.
Oracle Linux Server 6.5
Oracle Database 12.1.0.2
Oracle SQL Developer 4.0.0

1.2.1.

ABOUT THE DATABASE ENVIRONMENT

A non-container database named ORCL has been pre-created and configured in the VM, and
all labs are set to point to ORCL (Environment variables such as ORACLE_HOME are
automatically initialized in the shell). A Database listener named LISTENER is configured to
listen on the default port of 1521.
Note: Neither the database nor the listener is set to automatically startup when the VM is
started.

1.2.2.

OS & DATABASE USERNAMES AND PASSWORDS

Operating System: oracle/oracle, root/oracle (root user is never used)


Oracle Database: Passwords for all Database users (such as SYS, SYSTEM) is
oracle, except as noted below (please note that the passwords are case sensitive):
2014 Oracle Corporation. All Rights Reserved.

Page 10

Oracle Database In-Memory Workshop

SOFTWARE.HARDWARE.COMPLETE

o LABUSER: labuser
o RTL: rtl

1.2.3.

ABOUT THE LAB SCHEMAS

The ORCL Database contains two sets of schemas that you will use in this workshop, mainly
RTL and LABUSER.
The RTL schema is a stripped-down and modified version of Oracle Retail Data Model.
The LABUSER schema is a copy of the Sales History (SH) schema, which is a part of the
example schemas supplied by the Oracle Database. Figure 1.2 contains the data model
of SH.

2014 Oracle Corporation. All Rights Reserved.

Page 11

Oracle Database In-Memory Workshop

SOFTWARE.HARDWARE.COMPLETE

Figure 1.2: SH Schema

1.3.

WORKSHOP LAB HARDWARE/SOFTWARE REQUIREMENTS

The prerequisites to install Oracle VirtualBox VM on your laptop/desktop are given below.
Please ensure that you have them completed before proceeding to the next steps.

1.3.1.

HARDWARE REQUIREMENTS

Memory: 6 GB of RAM (minimum)


Hard Disk: 25 GB of free disk space (minimum)

2014 Oracle Corporation. All Rights Reserved.

Page 12

Oracle Database In-Memory Workshop

SOFTWARE.HARDWARE.COMPLETE

o 35 GB if planning to save the supplied Lab VM image on local disk


VT-x or AMD-v enabled in BIOS

1.3.2.

SOFTWARE REQUIREMENTS

Oracle VirtualBox 4.3.x or later


o Oracle VirtualBox Software will be supplied by the instructor
o You may also download an install ahead of time from
http://www.oracle.com/technetwork/server-storage/virtualbox/downloads/index.html
Unzip utility such as 7-zip or Winzip
OS: Windows 7 64-bit OS, or any supported 64-bit OS listed on
http://www.oracle.com/technetwork/server-storage/virtualbox/downloads/index.html

1.4.

VM ENVIRONMENT INSTALLATION

1.4.1.

VIRTUALBOX VM DOWNLOAD/COPY

The instructor will supply the Oracle VirtualBox VM in the class, along with the Oracle
VirtualBox software. The VM will be in a compressed (ZIP) format, and would need
decompressing prior to opening it from Oracle VirtualBox software.
Copy the supplied VM zip file to a location on your machine. Ensure that the location has
sufficient space to store the zip file, and also the Oracle VirtualBox VM files post
decompression. The VM files contain a Vbox file (containing VM metadata) and a set of VDI
files (one for each VM Disk).
Once the VM zip file is decompressed it should create a folder containing the following files.

2014 Oracle Corporation. All Rights Reserved.

Page 13

Oracle Database In-Memory Workshop

1.4.2.

SOFTWARE.HARDWARE.COMPLETE

ORACLE VIRTUALBOX INSTALLATION

Follow the below steps to install Oracle VirtualBox on Windows 7 64-bit hosts. For all other
hosts, refer to the platform specific installation instructions available at
http://download.virtualbox.org/virtualbox/UserManual.pdf.
1. Double-click the Oracle VirtualBox software executable (either downloaded or supplied by
the instructor).
2. You will be presented the Welcome screen.

3. Click Next.
4. For all the remaining screens, you may continue to click Next and accept all the default
selections.

2014 Oracle Corporation. All Rights Reserved.

Page 14

Oracle Database In-Memory Workshop

SOFTWARE.HARDWARE.COMPLETE

5. If presented with the Warning: Network Interfaces screen, click on Yes to proceed with
the installation.
6. Once the installation completes, you will see a start menu item created on your Windows
environment (All Program -> Oracle VM Virtual Box -> Oracle VM Virtual Box), and also
a desktop shortcut.

1.4.3.

START THE LAB VM

Before you can start the lab VM, you first need to add the VM to Oracle VirtualBox. The easiest
way to add the VM to VirtualBox is to double-click on the VM Vbox file (db12cvm1.vbox).
1. Browse to the folder (db12cvm1) that got created when the VM was extracted and doubleclick on db12cvm1.vbox.

Note: Another option for adding the VM is to first start Oracle VirtualBox, and then
manually adding the VM using (Machine -> Add).
2. Once the VM is added, it will show up in VirtualBox left pane. Select the VM and click on

2014 Oracle Corporation. All Rights Reserved.

Page 15

Oracle Database In-Memory Workshop

the start

SOFTWARE.HARDWARE.COMPLETE

button to start the VM. In case you have multiple VMs, ensure that the correct

VM is selected.
3. You should get the following login screen after the VM successfully starts up.

4. Login as the user oracle using the supplied password.

5. You should see the below Oracle Linux desktop upon a successful login.

2014 Oracle Corporation. All Rights Reserved.

Page 16

Oracle Database In-Memory Workshop

1.5.

SOFTWARE.HARDWARE.COMPLETE

START THE DATABASE AND LISTENER

The Oracle Database processes are not setup to start automatically upon boot time. Therefore,
start the listener and the ORCL database after booting the VM for the first time, and also at
subsequent startups as may be necessary.
1. Double Click the Terminal icon to start a new terminal session.

2. Setup the environment variables prior to starting the listener and the database.
Hint: Type the commands displayed only in bold.
$> . oraenv
ORACLE_SID = [orcl] ? orcl
The Oracle base remains unchanged with value /u01/app/oracle
3. Startup the listener using the following commands.
$> lsnrctl start
4. Startup a SQL*Plus session as the SYS user connected with the SYSDBA role.
$> sqlplus / AS SYSDBA
5. In the SQL*Plus session, start the ORCL database using the following commands.
SQL> STARTUP;
Note: ORCL is a non-container database.
6. If you have reached this step without errors, it means that your lab environment setup is
successful.

1.6.

CONVENTIONS USED IN THIS MANUAL

The following conventions are used in this lab manual:


2014 Oracle Corporation. All Rights Reserved.

Page 17

Oracle Database In-Memory Workshop

SOFTWARE.HARDWARE.COMPLETE

All user input is displayed in the box with the gray background (as shown below). Notice
the output of the commands is not displayed in the same box. The reason is to facilitate
cut/paste of commands between the lab manual and the Terminal window.
$> sqlplus / AS SYSDBA
All OS commands will display the OS prompt ($>), to distinguish them with SQL
commands.
o OS command example:
$> ls
o SQL commands example:
SELECT USER FROM DUAL;
All output from the commands is displayed in the box with a white background (as
shown below). The output may also contain the input, and this box is typically shown to
help illustrate the concept when relevant.
[oracle@db12cvm1 ~]$ sqlplus / as SYSDBA
SQL*Plus: Release 12.1.0.1.0 Production on Tue Nov 19 22:59:05 2013
(c) 1982, 2013, Oracle. All rights reserved.

Copyright

Connected to:
Oracle Database 12c Enterprise Edition Release 12.1.0.1.0 - 64bit Production
With the Partitioning, OLAP, Advanced Analytics and Real Application Testing
options
SQL>

The code font used in the lab is: COURIER IN BOLD SIZE 12 PT
Output font used in the lab is: COURIER SIZE 10 PT
Portions of the output are sometimes highlighted using: HIGHLIGHTED IN BOLD AND RED
The lab SQLs can either by typed, copy/pasted or run directly from the
/home/oracle/labs directory. However, when running the labs via scripts, be sure to
inspect the individual steps.
2014 Oracle Corporation. All Rights Reserved.

Page 18

Oracle Database In-Memory Workshop

2.

SOFTWARE.HARDWARE.COMPLETE

ENABLING THE IN-MEMORY COLUMN STORE

Oracle Database In-Memory option comes preinstalled with the Oracle Database 12c and does
not require additional software installation or recompilation of existing database software. This
is because the In-Memory option has been seamlessly integrated into the core of the Oracle
Database software as a new component of the Shared Global Area (SGA), so when the Oracle
Database is installed, Oracle Database In-Memory gets installed with it.
However, the IM column store is not enabled by default, but can be easily enabled via a few
steps, as outlined in this lesson.
It is important to remember that after the In-Memory option is enabled at the instance level,
you also have to specifically enable objects so they would be considered for In-Memory
column store population.
In this lesson, the steps to enable the IM column store are covered, whereas the next lesson
will focus on enabling the objects for the column store.

2.1.

IN-MEMORY AREA OVERVIEW

The In-Memory Area is a static pool within the SGA that holds the column format data (also
referred to as the In-Memory Column Store). The size of the In-Memory Area is controlled by
the initialization parameter INMEMORY_SIZE (default is 0, i.e. disabled).
The current size of the In-Memory Area is available by querying the INMEMORY_SIZE
initialization parameter from V$PARAMETER, and it is also visible in V$SGA. As the IM column
store is a static pool, any changes to the INMEMORY_SIZE parameter will not take effect until
the database instance is restarted. It is also not impacted or controlled by Automatic Memory
Management (AMM). The In-Memory Area must have a minimum size of 100MB.
The In-Memory Area is sub-divided into two pools: IMCU pool (In-Memory Compression Units ,
aka the 1MB pool) used to store the actual column formatted data populated into memory; and
a SMU pool (Snapshot Metadata Units, aka the 64KB pool) used to store metadata about the
objects that are populated into the IM column store. The amount of available memory in each
pool is visible in the V$INMEMORY_AREA view. The relative size of the two pools is determined
2014 Oracle Corporation. All Rights Reserved.

Page 19

Oracle Database In-Memory Workshop

SOFTWARE.HARDWARE.COMPLETE

by internal heuristics, but the majority of the memory gets allocated to the 1MB pool.

2.2.

VERIFY IN-MEMORY AREA CONFIGURATION

We have not enabled the column store in the VirtualBox VM yet, which also is the default
setting after a fresh database creation by DBCA. Lets verify that the INMEMORY_* parameters
are at default values, indicating that the column store is disabled and the SGA has not
allocated any memory structures for the store.
Note: Before proceeding further in this lesson, ensure that you have followed the steps
outlined in Section 1.4 and started up the VM, the database listener and the ORCL database.

LAB STEPS
1. Start a new terminal session from the desktop.

2. At the $> prompt, connect to the database using SQL*Plus as SYSDBA. All environment
variables such as ORACLE_HOME and PATH are set to initialize at startup.
sqlplus / AS SYSDBA
3. To see the amount of memory assigned to the IM column store, browse the parameters
that have the INMEMORY prefix:
SHOW PARAMETER INMEMORY
SQL> SHOW PARAMETER INMEMORY
NAME
----------------------------inmemory_clause_default
inmemory_force
inmemory_max_populate_servers
inmemory_query
inmemory_size
inmemory_trickle_repopulate_servers_
optimizer_inmemory_aware

2014 Oracle Corporation. All Rights Reserved.

TYPE
---------string
string
integer
string
big integer
integer
boolean

VALUE
-----------DEFAULT
0
ENABLE
0
1 percent
TRUE

Page 20

Oracle Database In-Memory Workshop

SOFTWARE.HARDWARE.COMPLETE

4. Seven new initialization parameters with the INMEMORY prefix have been introduced to
directly control the different aspects of the new in-memory functionality. There is also a new
optimizer parameter (INMEMORY_QUERY) that controls at the system and the session level
whether queries can use the column store or not. Further details on all IM column store
related initialization parameters are provided later in this lesson.
5. Right now we are only interested in one of these parameters, INMEMORY_SIZE to
determine if In-Memory is enabled. The size of the IM column store is controlled by the
INMEMORY_SIZE parameter.
6. As you can see the INMEMORY_SIZE parameter is set to 0 and therefore Oracle Database
In-Memory is disabled, as there is no IM column store allocated in the SGA.
7. We can also confirm by querying V$SGA that the In-Memory Area is not allocated.
SELECT NAME, VALUE FROM V$SGA;

NAME
VALUE
------------------ ---------Fixed Size
2926080
Variable Size
553650688
Database Buffers
1442840576
Redo Buffers
13848576

8. From the above output, V$SGA does not have an entry for In-Memory Area, which means
that it has not allocated the columnar store yet.

2.3.

ENABLE THE IN-MEMORY COLUMN STORE

Now that the IM column store is disabled and not in-use, lets go over the steps to enable it.
Execute the following steps in SQL*Plus connected as the user SYS with SYSDBA role.

LAB STEPS
1. Set the INMEMORY_SIZE initialization parameter to 1G. You must use ALTER SYSTEM
SET SCOPE=SPFILE command, as this parameter is not dynamically modifiable.
ALTER SYSTEM SET INMEMORY_SIZE=1G SCOPE=SPFILE;
Note: The minimum setting of this parameter is 100M.
2014 Oracle Corporation. All Rights Reserved.

Page 21

Oracle Database In-Memory Workshop

SOFTWARE.HARDWARE.COMPLETE

2. The next step is to restart the database, but before doing so, check if the SGA size is large
enough to accommodate the additional 1G of memory (which is what we setup) needed by
the column store so we dont run into memory allocation issues at startup.
3. As the ORCL database is setup with Automatic Shared Memory Management (ASMM),
lookup SGA_TARGET to get the current SGA size. Ensure that SGA_TARGET is high enough
to accommodate the IN_MEMORY size otherwise you will need to adjust the SGA_TARGET.
SHOW PARAMETER SGA_TARGET

SQL> SHOW PARAMETER SGA_TARGET


NAME
TYPE
VALUE
---------------------------- ----------- -----------------------------sga_target
big integer 1920M

Note: If your database is configured with Automatic Memory Management (AMM) then
check MEMORY_TARGET instead of SGA_TARGET. Also, you may also need to adjust
SGA_MAX_TARGET (or MEMORY_MAX_TARGET) accordingly as well.
4. As observed from the above output, SGA_TARGET is set to 1920M in the lab VM. This size
is sufficient to accommodate 1G of INMEMORY_SIZE.
5. Restart the database. This is required to initialize the IM column store in the SGA.
SHUTDOWN IMMEDIATE
STARTUP
6. Check the amount of memory allocated to the IM column store by checking the
INMEMORY_SIZE again.
SHOW PARAMETER INMEMORY_SIZE

SQL> SHOW PARAMETER INMEMORY_SIZE


NAME
TYPE
VALUE
----------------------- ----------- -----------------------------inmemory_size
big integer 1G

7. In the above output, observe that 1G has been allocated to In-Memory column store.

2014 Oracle Corporation. All Rights Reserved.

Page 22

Oracle Database In-Memory Workshop

SOFTWARE.HARDWARE.COMPLETE

8. You can also confirm by querying V$SGA. Observe the size of the In-Memory Area as
shown in V$SGA.
SELECT NAME, VALUE FROM V$SGA;

SQL> SELECT NAME, VALUE FROM V$SGA;


NAME
VALUE
-------------------- ---------Fixed Size
2926080
Variable Size
285215232
Database Buffers
637534208
Redo Buffers
13848576
In-Memory Area
1073741824

9. As you already learnt, the In-Memory Area is sub-divided into two pools: a 1MB pool (IMCU
pool) used to store the actual column formatted data populated into memory, and a 64KB
pool (SMU pool) used to store metadata about the objects that are populated into the IM
column store.
10. Query the amount of available memory allocated/used to/from each pool using
V$INMEMORY_AREA. The relative size of the two pools is determined by internal heuristics,
the majority of the In-Memory Area memory is allocated to the 1MB pool.
SELECT POOL, ALLOC_BYTES, USED_BYTES FROM V$INMEMORY_AREA;

SQL> SELECT POOL, ALLOC_BYTES, USED_BYTES FROM V$INMEMORY_AREA;


POOL
ALLOC_BYTES USED_BYTES
-------------------- ----------- ---------1MB POOL
854589440
0
64KB POOL
201326592
0

11. As you can see, the pool has been allocated in the SGA but not currently in use
(USED_BYTES are 0), as we have not yet configured any objects to use it.
12. We now have an IM column store configured. But the IM column store is still not in use as
no objects have yet been enabled for population, which you will do in the next few lessons.

2.4.

INITIALIZATION PARAMETERS RELATED TO IM COLUMN STORE

Seven new initialization parameters with the INMEMORY prefix have been introduced to directly
2014 Oracle Corporation. All Rights Reserved.

Page 23

Oracle Database In-Memory Workshop

SOFTWARE.HARDWARE.COMPLETE

control the different aspects of the new in-memory functionality. You have already seen the
use of INMEMORY_SIZE. Later on, you will work with some of the other parameters as well.
Their brief descriptions are given below.
INMEMORY_SIZE
This initialization parameter sets the size of the IM column store in a database instance.
The default value is 0, which means that the IM column store is not used. This
initialization parameter must be set to a non-zero value to enable the IM column store. If
the parameter is set to a non-zero value, then the minimum setting should be 100M.
In a multitenant environment, the setting for this parameter in the root is the setting for
the entire multitenant container database (CDB). This parameter can also be set in each
pluggable database (PDB) to limit the maximum size of the IM column store for each
PDB. The sum of the PDB values can be less than, equal to, or greater than the CDB
value. However, the CDB value is the maximum amount of memory available in the IM
column store for the entire CDB, including the root and all of the PDBs. Unless this
parameter is specifically set for a PDB, the PDB inherits the CDB value, which means
that the PDB can use all of the available IM column store for the CDB.
INMEMORY_FORCE
This initialization parameter can enable tables and materialized views for the IM column
store or disable all tables and materialized views for the IM column store.
Set this parameter to DEFAULT, the default value, to allow the INMEMORY or NO
INMEMORY attributes on the individual database objects determine if they will be
populated in the IM column store.
Set this parameter to OFF to specify that all tables and materialized views be disabled
for the IM column store.
INMEMORY_QUERY
This initialization parameter specifies whether in-memory queries are allowed. Set this
2014 Oracle Corporation. All Rights Reserved.

Page 24

Oracle Database In-Memory Workshop

SOFTWARE.HARDWARE.COMPLETE

parameter to ENABLE, the default value, to allow queries to access database objects
populated in the IM column store, or set this parameter to DISABLE to disable access to
the database objects populated in the IM column store.
INMEMORY_CLAUSE_DEFAULT
This initialization parameter enables you to specify a default IM column store clause for
new tables and materialized views.
Leave this parameter unset or set it to an empty string to specify that there is no default
IM column store clause for new tables and materialized views. Setting the value of this
parameter to NO INMEMORY has the same effect as setting it to the default value (the
empty string).
Set this parameter to a valid in-memory clause (in-memory clause is discussed in the
next lesson) to specify that the clause is the default for all new tables and materialized
views. The clause can include valid clauses for IM column store compression methods
and data population options.
If the clause starts with INMEMORY, then all new tables and materialized views, including
those without an INMEMORY clause, are populated in the IM column store. If the clause
omits INMEMORY, then it only applies to new tables and materialized views that are
enabled for the IM column store with an INMEMORY clause during creation.
INMEMORY_MAX_POPULATE_SERVERS
This initialization parameter specifies the maximum number of background populate
servers to use for IM column store population, so that these servers do not overload the
rest of the system. Set this parameter to an appropriate value based on the number of
cores in the system.
INMEMORY_OPTIMIZER_AWARE
This initialization parameter enables or disables all of the optimizer cost model
enhancements for in-memory. Setting the parameter to FALSE causes the optimizer to
2014 Oracle Corporation. All Rights Reserved.

Page 25

Oracle Database In-Memory Workshop

SOFTWARE.HARDWARE.COMPLETE

ignore the in-memory property of tables during the optimization of SQL statements.
INMEMORY_TRICKLE_POPULATE_SERVERS_PERCENT
This initialization parameter limits the maximum number of background populate servers
used for IM column store repopulation, as trickle repopulation is designed to use only a
small percentage of the populate servers. The value for this parameter is a percentage
of the INMEMORY_MAX_POPULATE_SERVERS initialization parameter value. For
example, if this parameter is set to 10 and INMEMORY_MAX_POPULATE_SERVERS is set
to 10, then on average one core is used for trickle repopulation.

2.5.

SUMMARY

The In-Memory column store needs to be setup at the instance level prior to using it. You have
seen how simple it is to configure the IM column store, mainly by setting only one initialization
parameter called INMEMORY_SIZE. Remember, the IM column store is a new static pool in the
SGA that cannot be resized dynamically and is not managed via the automatic SGA
management algorithms.

2014 Oracle Corporation. All Rights Reserved.

Page 26

Oracle Database In-Memory Workshop

3.

SOFTWARE.HARDWARE.COMPLETE

ENABLING OBJECTS TO USE THE IM COLUMN STORE

Oracle Database In-Memory provides a new clause to the database object creation DDL called
the in-memory clause, which when specified, the object becomes eligible to be populated into
the IM column store. The in-memory clause can be specified on the object or tablespace; and
either at creation time to enable or disable the object for the IM column store (via CREATE); or
when changing the in-memory parameters of an existing object (via ALTER).
Note: Enabling the object to use the IM column store does not automatically trigger its
population. IM Column Store population is a separate topic and is discussed in the next lesson.

3.1.

THE IN-MEMORY CLAUSE

Before you start enabling objects for the column store, it helps to learn about the in-memory
clause of object DDL. The in-memory clause is used to enable or disable an object (table,
tablespace, partition, subpartition, materialized view, or table column) for the IM column store,
and also to change its in-memory parameters. The in-memory clause has the same semantics
in both, CREATE and ALTER. The following is the syntax diagram for the in-memory clause for
all objects.

Specify INMEMORY to enable the object for the IM column store, or to change the
inmemory_parameters for the object that is already enabled for the IM column store.
Specify NO INMEMORY to disable the object for the IM column store.
inmemory_parameters allow you to specify four additional sub-clauses that extend
the in-memory definition on the object:
o PRIORITY: This parameter controls the population of objects into the column store.
A PRIORITY can be set for an object using which the database will decide the order
of its population, when compared to the rest of the objects that may also be enabled
2014 Oracle Corporation. All Rights Reserved.

Page 27

Oracle Database In-Memory Workshop

SOFTWARE.HARDWARE.COMPLETE

for the IM column store, and possibly with the same or different priority. Further
details on this parameter are discussed later in this lesson.
o MEMCOMPRESS: This clause specifies the compression levels to be used for the
table or its columns. Oracle offers multiple compression techniques providing
different levels of compression and performance. By default, data is compressed
using the FOR QUERY LOW option as this provides the best balance between
compression and performance. Further details on this clause are discussed later in
this lesson.
o DUPLICATE: In a RAC environment each database node has its own IM Column
Store. The same object can be duplicated in each of the column stores, which is
referred to as DUPLICATE. The default value for this option is NO DUPLICATE. This
option is only valid when the Oracle Database is resident on Oracle Exadata
Database Machine. On a single instance and non-Exadata databases this attribute
has no effect.
o DISTRIBUTE: This attributes also pertains to a RAC environment. When an object
is too big to fit into the IM Column Store on a single node, it is possible for pieces of
that object to be distributed between each of the RAC nodes. This is referred to as
DISTRIBUTE. The default value is AUTO-DISTRIBUTE, where Oracle automatically
decides how objects should be distributed between the nodes. On a single instance
database this attribute has on effect.
The objects created (or altered) with the in-memory clause are said to have their in-memory
attributes set. These attributes are captured in four new columns in the existing data dictionary
*_TABLES views (also, *_SEGMENTS, *_TAB_PARTITIONS, and *_TAB_SUB_PARTITIONS),
and also in V$IM_SEGMENTS and V$IM_USER_SEGMENTS.
The in-memory parameters are captured in the following column attributes:
INMEMORY: This attribute captures the INMEMORY|NO INMEMORY specification of the
in-memory clause, and would contain the values ENABLED or DISABLED.

2014 Oracle Corporation. All Rights Reserved.

Page 28

Oracle Database In-Memory Workshop

SOFTWARE.HARDWARE.COMPLETE

INMEMORY_PRIORITY: This attribute captures the values specified in the PRIORITY


clause. Valid values are NONE, LOW, MEDIUM, HIGH and CRITICAL.
INMEMORY_COMPRESSION: This attribute captures the compression methods for
objects specified via the MEMCOMPRESS clause.
INMEMORY_DUPLICATE & INMEMORY_DISTRIBUTE: These two attributes capture the
values set by DUPLICATE and DISTRIBUTE clauses, respectively.

3.2.

ENABLING A NEW TABLE

To create a table and enable it for the IM column store at creation time, you would use the
CREATE table DDL with the in-memory clause. The syntax for this statement is:
CREATE TABLE INMEMORY

LAB STEPS
1. Start a new terminal session.

2. Login to the database using SQL*Plus as the LABUSER, using password labuser.
sqlplus LABUSER/labuser
3. Create a table named PARTS and enable it for the column store by specifying the inmemory clause. Do not specify any of the parameters to this clause such as MEMCOMPRESS
and PRIORITY, as you want them to be assigned with default values.
CREATE TABLE PARTS (
PART_ID NUMBER,
NAME VARCHAR2(100),
MFR VARCHAR2(50),
CATEGORY VARCHAR2(30),
BRAND VARCHAR2(50)) INMEMORY;

SQL> CREATE TABLE PARTS (


PART_ID NUMBER,
2014 Oracle Corporation. All Rights Reserved.

Page 29

Oracle Database In-Memory Workshop

SOFTWARE.HARDWARE.COMPLETE

NAME VARCHAR2(100),
MFR VARCHAR2(50),
CATEGORY VARCHAR2(30),
BRAND VARCHAR2(50)) INMEMORY;
Table created.

4. Check the in-memory attributes of PARTS by querying USER_TABLES. The columns to


check are INMEMORY, INMEMORY_PRIORITY, INMEMORY_COMPRESSION,
INMEMORY_DISTRIBUTE and INMEMORY_DUPLICATE.
SELECT INMEMORY, INMEMORY_PRIORITY, INMEMORY_COMPRESSION,
INMEMORY_DISTRIBUTE, INMEMORY_DUPLICATE
FROM USER_TABLES
WHERE TABLE_NAME = 'PARTS';
SQL> SELECT INMEMORY, INMEMORY_PRIORITY, INMEMORY_COMPRESSION,
INMEMORY_DISTRIBUTE, INMEMORY_DUPLICATE
FROM USER_TABLES
WHERE TABLE_NAME = 'PARTS';
INMEMORY INMEMORY_PRIORITY INMEMORY_COMPRESS INMEMORY_DISTRI INMEMORY_DUPL
-------- ----------------- ----------------- --------------- ------------ENABLED NONE
FOR QUERY LOW
AUTO
NO DUPLICATE

5. As you observe from the above output, the PARTS table is enabled for in-memory as the
INMEMORY attribute is ENABLED. Also, observe that INMEMORY_PRIORITY is set to NONE,
INMEMORY_COMPRESS is set to FOR QUERY LOW, INMEMORY_DISTRIBUTE is set to
AUTO, and INMEMORY_DUPLICATE is set to NO DUPLICATE. As you had not specified any
of these parameters to the in-memory clause, they have all been assigned default values.

3.3.

ENABLING AN EXISTING TABLE WITH PRIORITY HIGH

To enable an existing table for the IM column store, you would use the ALTER table DDL with
the INMEMORY clause and the PRIORITY parameter. The syntax for this statement is:
ALTER TABLE INMEMORY PRIORITY [NONE|LOW|MEDIUM|HIGH|CRITICAL]

LAB STEPS
1. In the previous SQL*Plus session connected as the LABUSER, check the INMEMORY
attributes for the COSTS table. The table should be DISABLED for in-memory.
2014 Oracle Corporation. All Rights Reserved.

Page 30

Oracle Database In-Memory Workshop

SOFTWARE.HARDWARE.COMPLETE

SELECT INMEMORY, INMEMORY_PRIORITY, INMEMORY_COMPRESSION,


INMEMORY_DISTRIBUTE, INMEMORY_DUPLICATE
FROM USER_TABLES
WHERE TABLE_NAME = 'COSTS';
2. Alter the COSTS table and enable it for the column store by specifying the INMEMORY and a
PRIORITY of HIGH. Do not specify the remaining parameters such as MEMCOMPRESS or
DISTRIBUTE, which means they will get default values.
ALTER TABLE COSTS INMEMORY PRIORITY HIGH;
3. Check the in-memory attributes for COSTS again.
SELECT INMEMORY, INMEMORY_PRIORITY, INMEMORY_COMPRESSION,
INMEMORY_DISTRIBUTE, INMEMORY_DUPLICATE
FROM USER_TABLES
WHERE TABLE_NAME = 'COSTS';
SQL> SELECT INMEMORY, INMEMORY_PRIORITY, INMEMORY_COMPRESSION,
INMEMORY_DISTRIBUTE, INMEMORY_DUPLICATE
FROM USER_TABLES
WHERE TABLE_NAME = 'COSTS';
INMEMORY INMEMORY_PRIORITY INMEMORY_COMPRESS INMEMORY_DISTRI INMEMORY_DUPL
-------- ----------------- ----------------- --------------- ------------ENABLED HIGH
FOR QUERY LOW
AUTO
NO DUPLICATE

4. As you observe from the above output, the COSTS table has been enabled for in-memory
and is assigned the PRIORITY of HIGH. This means that COSTS table will be populated
into the column store before the tables containing NONE, LOW or MEDIUM priority. The
only other set of tables that will be loaded prior to COSTS are the ones that have CRITICAL
priority, or the ones whose population is triggered by querying them.
5. Also observe that the remaining attributes have all been assigned default values.

3.4.

ENABLING TABLE COLUMNS

For tables and materialized views, the in-memory clause allows an additional sub-clause called
the in-memory column clause (see syntax diagram below). The in-memory column clause is
used to enable or disable a table column for the IM column store, or to change the
compression levels for a table column, in case you choose to have a different compression
2014 Oracle Corporation. All Rights Reserved.

Page 31

Oracle Database In-Memory Workshop

SOFTWARE.HARDWARE.COMPLETE

method for a column than the table.

An additional dictionary view, V$IM_COLUMN_LEVEL, captures the column-level compression


attributes along with their enablement status. This view does not capture the other parameters
of the in-memory clause (i.e. PRIORITY, DUPLICATE, and DISTRIBUTE) as they cannot be
overridden at the column-level and must apply to the entire table or a table partition. Also, the
view does not contain any rows for tables whose columns do not have an overriding
compression clause or were selectively disabled.
For example, to enable an existing table for the IM column store, you would use the ALTER
table DDL with the INMEMORY clause, along with the in-memory column clause as shown
below.
ALTER TABLE

INMEMORY (col1)

ALTER TABLE

INMEMORY (col1, col2)

ALTER TABLE

NO INMEMORY (col1, col2)

ALTER TABLE

INMEMORY MEMCOMPRESS QUERY LOW (col1)

ALTER TABLE

INMEMORY MEMCOMPRESS QUERY HIGH (col2)


NO INMEMORY (col3)
INMEMORY PRIORITY HIGH

In this lab you will enable a few columns of the PROMOTIONS table in LABUSER schema for the
IM column store, but not all.

LAB STEPS
1. In the previous SQL*Plus session connected as the LABUSER, first check the INMEMORY
2014 Oracle Corporation. All Rights Reserved.

Page 32

Oracle Database In-Memory Workshop

SOFTWARE.HARDWARE.COMPLETE

attributes for the PROMOTIONS table. The table should be DISABLED for in-memory.
SELECT INMEMORY, INMEMORY_PRIORITY, INMEMORY_COMPRESSION,
INMEMORY_DISTRIBUTE, INMEMORY_DUPLICATE
FROM USER_TABLES
WHERE TABLE_NAME = 'PROMOTIONS';
2. Describe the table to get listing of its columns.
DESC PROMOTIONS

SQL> DESC PROMOTIONS;


Name
Null?
----------------------------------------PROMO_ID
NOT NULL
PROMO_NAME
NOT NULL
PROMO_SUBCATEGORY
NOT NULL
PROMO_SUBCATEGORY_ID
NOT NULL
PROMO_CATEGORY
NOT NULL
PROMO_CATEGORY_ID
NOT NULL
PROMO_COST
NOT NULL
PROMO_BEGIN_DATE
NOT NULL
PROMO_END_DATE
NOT NULL
PROMO_TOTAL
NOT NULL
PROMO_TOTAL_ID
NOT NULL

Type
-------- ---------------------------NUMBER(6)
VARCHAR2(30)
VARCHAR2(30)
NUMBER
VARCHAR2(30)
NUMBER
NUMBER(10,2)
DATE
DATE
VARCHAR2(15)
NUMBER

3. Alter the PROMOTIONS table and enable only a few columns for the IM column store. The
columns you like to keep disabled from the IM column store needs to be specifically
specified using the NO INMEMORY clause (see below), otherwise by default, the columns
not present in the INMEMORY clause will also be enabled (as it is the default action). Also
note that you need to enable the table itself for INMEMORY otherwise you will get an error
(unless the table was already enabled earlier).
ALTER TABLE PROMOTIONS INMEMORY
INMEMORY (PROMO_NAME, PROMO_CATEGORY, PROMO_COST, PROMO_TOTAL)
NO INMEMORY (PROMO_ID, PROMO_CATEGORY_ID, PROMO_SUBCATEGORY_ID);
4. Check the in-memory attributes for PROMOTIONS.
SELECT INMEMORY, INMEMORY_PRIORITY, INMEMORY_COMPRESSION,
INMEMORY_DISTRIBUTE, INMEMORY_DUPLICATE
FROM USER_TABLES
WHERE TABLE_NAME = 'PROMOTIONS';

2014 Oracle Corporation. All Rights Reserved.

Page 33

Oracle Database In-Memory Workshop

SOFTWARE.HARDWARE.COMPLETE

SQL> SELECT INMEMORY, INMEMORY_PRIORITY, INMEMORY_COMPRESSION,


INMEMORY_DISTRIBUTE, INMEMORY_DUPLICATE
FROM USER_TABLES
WHERE TABLE_NAME = 'PROMOTIONS';
INMEMORY INMEMORY INMEMORY_COMPRESS INMEMORY_DISTRI INMEMORY_DUPL
-------- -------- ----------------- --------------- ------------ENABLED NONE
FOR QUERY LOW
AUTO
NO DUPLICATE

5. The above output says that the PROMOTIONS table is enabled for in-memory with the
default parameters. But there is no information about the columns participation status in
USER_TABLES.
6. For column level information, check V$IM_COLUMN_LEVEL to see the columns that are
enabled for the IM column store.
SET LINES 100;
SELECT TABLE_NAME, COLUMN_NAME, INMEMORY_COMPRESSION
FROM V$IM_COLUMN_LEVEL
WHERE TABLE_NAME = 'PROMOTIONS';

SQL> SET LINES 100;


SQL> SELECT TABLE_NAME, COLUMN_NAME, INMEMORY_COMPRESSION
FROM V$IM_COLUMN_LEVEL
WHERE TABLE_NAME = 'PROMOTIONS';
TABLE_NAME
-----------PROMOTIONS
PROMOTIONS
PROMOTIONS
PROMOTIONS
PROMOTIONS
PROMOTIONS
PROMOTIONS
PROMOTIONS
PROMOTIONS
PROMOTIONS
PROMOTIONS

COLUMN_NAME
--------------PROMO_ID
PROMO_NAME
PROMO_SUBCATEGORY
PROMO_SUBCATEGORY_ID
PROMO_CATEGORY
PROMO_CATEGORY_ID
PROMO_COST
PROMO_BEGIN_DATE
PROMO_END_DATE
PROMO_TOTAL
PROMO_TOTAL_ID

INMEMORY_COMPRESSION
-------------------NO INMEMORY
DEFAULT
DEFAULT
NO INMEMORY
DEFAULT
NO INMEMORY
DEFAULT
DEFAULT
DEFAULT
DEFAULT
DEFAULT

7. The above output correctly displays that the PROMO_ID, PROMO_SUBCATEGORY_ID and
PROMO_CATEGORY_ID columns are disabled from the IM column store. Also,
PROMO_NAME, PROMO_CATEGORY, PROMO_COST, and PROMO_TOTAL are enabled,
but so are the remaining columns that were not included in the in-memory column clause.
This is because the default action is to enable the column if there is no in-memory column
2014 Oracle Corporation. All Rights Reserved.

Page 34

Oracle Database In-Memory Workshop

SOFTWARE.HARDWARE.COMPLETE

clause specified but the table is enabled.

3.5.

DISABLING A TABLE

To disable a table for the IM column store, use the NO INMEMORY clause. Once a table is
disabled, its information is purged from the data dictionary views, metadata from the IM column
store is cleared, and its in-memory column representation invalidated.

LAB STEPS
1. In the previous SQL*Plus session connected as the LABUSER, disable the PROMOTIONS
table from the column store.
ALTER TABLE PROMOTIONS NO INMEMORY;
2. Check the in-memory attributes for PROMOTIONS.
SELECT INMEMORY, INMEMORY_PRIORITY, INMEMORY_COMPRESSION,
INMEMORY_DISTRIBUTE, INMEMORY_DUPLICATE
FROM USER_TABLES
WHERE TABLE_NAME = 'PROMOTIONS';
SQL> SELECT INMEMORY, INMEMORY_PRIORITY, INMEMORY_COMPRESSION,
INMEMORY_DISTRIBUTE, INMEMORY_DUPLICATE
FROM USER_TABLES
WHERE TABLE_NAME = 'PROMOTIONS';
INMEMORY INMEMORY INMEMORY_COMPRESS INMEMORY_DISTRI INMEMORY_DUPL
-------- -------- ----------------- --------------- ------------DISABLED

3. Check if the column-level attributes for PROMOTIONS are saved. What do you observe?
SET LINES 100;
SELECT TABLE_NAME, COLUMN_NAME, INMEMORY_COMPRESSION
FROM V$IM_COLUMN_LEVEL
WHERE TABLE_NAME = 'PROMOTIONS';
4. There should be no rows returned by the above query. Remember that
V$IM_COLUMN_LEVEL contains rows only when the table is enabled for the column store
and the in-memory column clause is specified.

2014 Oracle Corporation. All Rights Reserved.

Page 35

Oracle Database In-Memory Workshop

SOFTWARE.HARDWARE.COMPLETE

5. At this time, lets also disable the COSTS table from the IM column store as well.
ALTER TABLE COSTS NO INMEMORY;

3.6.

ENABLING AND DISABLING A TABLESPACE

You can enable a tablespace for the IM column store by specifying the in-memory clause with
the CREATE or the ALTER TABLESPACE statements. The in-memory clause is the same for
tables, materialized views, and tablespaces, with the exception of the in-memory column
clause, which can only be specified for tables and materialized views but not for the
tablespace. Also, the DEFAULT prefix is required before the INMEMORY/NO INMEMORY clause
for a tablespace.
For example, to enable an existing tablespace for the IM column store, you would use the
ALTER tablespace DDL with the INMEMORY clause as shown below.
ALTER TABLESPACE DEFAULT INMEMORY
ALTER TABLESPACE DEFAULT INMEMORY MEMCOMPRESS QUERY HIGH
ALTER TABLESPACE DEFAULT INMEMORY PRIORITY LOW
When a tablespace is enabled for the IM column store, all tables and materialized views
created in the tablespace are enabled for the IM column store by default as they inherit the
tablespace in-memory clause (at creation time).
Also, the tables and materialized views in the tablespace can have different in-memory clause
parameters than the tablespace-level in-memory clause, with the table-level settings overriding
the tablespace-level settings. For example, if the tablespace is set to PRIORITY LOW for
populating data in memory, but a table is set to PRIORITY HIGH, then the table uses
PRIORITY HIGH.

LAB STEPS
1. In the previous SQL*Plus session connected as the LABUSER, check the in-memory
attributes for LAB_DATA tablespace. As you observe from the below output, the tablespace
2014 Oracle Corporation. All Rights Reserved.

Page 36

Oracle Database In-Memory Workshop

SOFTWARE.HARDWARE.COMPLETE

is not enabled for IM Column Store.


SELECT DEF_INMEMORY, DEF_INMEMORY_PRIORITY,
DEF_INMEMORY_COMPRESSION, DEF_INMEMORY_DISTRIBUTE,
DEF_INMEMORY_DUPLICATE
FROM DBA_TABLESPACES
WHERE TABLESPACE_NAME = 'LAB_DATA';

SQL> SELECT DEF_INMEMORY, DEF_INMEMORY_PRIORITY, DEF_INMEMORY_COMPRESSION,


DEF_INMEMORY_DISTRIBUTE, DEF_INMEMORY_DUPLICATE
FROM DBA_TABLESPACES
WHERE TABLESPACE_NAME = 'LAB_DATA';
DEF_INME DEF_INME DEF_INMEMORY_COMP DEF_INMEMORY_DI DEF_INMEMORY_
-------- -------- ----------------- --------------- ------------DISABLED

2. Alter the LAB_DATA tablespace to enable it for the IM column store. Specify FOR
CAPACITY HIGH compression for the database objects that will be stored in the
tablespace, and PRIORITY LOW for populating data in memory.
ALTER TABLESPACE LAB_DATA DEFAULT INMEMORY
MEMCOMPRESS FOR CAPACITY HIGH PRIORITY LOW;
3. Check the in-memory attributes for LAB_DATA tablespace. As you observe from the below
output, the tablespace has been enabled for IM Column Store with FOR CAPACITY HIGH
compression, LOW priority, NO DUPLICATE, and AUTO distribute.
SELECT DEF_INMEMORY, DEF_INMEMORY_PRIORITY,
DEF_INMEMORY_COMPRESSION, DEF_INMEMORY_DISTRIBUTE,
DEF_INMEMORY_DUPLICATE
FROM DBA_TABLESPACES
WHERE TABLESPACE_NAME = 'LAB_DATA';

SQL> SELECT DEF_INMEMORY, DEF_INMEMORY_PRIORITY, DEF_INMEMORY_COMPRESSION,


DEF_INMEMORY_DISTRIBUTE, DEF_INMEMORY_DUPLICATE
FROM DBA_TABLESPACES
WHERE TABLESPACE_NAME = 'LAB_DATA';
DEF_INME DEF_INME DEF_INMEMORY_COMP
-------- -------- ----------------ENABLED LOW
FOR CAPACITY HIGH

DEF_INMEMORY_DI DEF_INMEMORY_
--------------- ------------AUTO
NO DUPLICATE

4. Create a table named PARTS2 in LAB_DATA.

2014 Oracle Corporation. All Rights Reserved.

Page 37

Oracle Database In-Memory Workshop

SOFTWARE.HARDWARE.COMPLETE

CREATE TABLE PARTS2 (


PART_ID NUMBER,
NAME VARCHAR2(100),
MFR VARCHAR2(50),
CATEGORY VARCHAR2(30),
BRAND VARCHAR2(50));
5. Check the in-memory attributes for PARTS2. As LAB_DATA is enabled for IM Column Store
with the above attributes, PARTS2 will inherit the in-memory attributes of the tablespace as
well, as shown in the output below.
SELECT INMEMORY, INMEMORY_PRIORITY, INMEMORY_COMPRESSION,
INMEMORY_DISTRIBUTE, INMEMORY_DUPLICATE
FROM USER_TABLES
WHERE TABLE_NAME = 'PARTS2';

SQL> SELECT INMEMORY, INMEMORY_PRIORITY, INMEMORY_COMPRESSION,


INMEMORY_DISTRIBUTE, INMEMORY_DUPLICATE
FROM USER_TABLES
WHERE TABLE_NAME = 'PARTS2';
INMEMORY INMEMORY INMEMORY_COMPRESS INMEMORY_DISTRI INMEMORY_DUPL
-------- -------- ----------------- --------------- -----------ENABLED LOW
FOR CAPACITY HIGH AUTO
NO DUPLICATE

6. Create a table named PARTS3 in LAB_DATA. This time, use a different set of in-memory
attributes for PARTS3 than the LAB_DATA tablespace in-memory attributes.
CREATE TABLE PARTS3 (
PART_ID NUMBER,
NAME VARCHAR2(100),
MFR VARCHAR2(50),
CATEGORY VARCHAR2(30),
BRAND VARCHAR2(50))
INMEMORY MEMCOMPRESS FOR QUERY HIGH PRIORITY HIGH;
7. Check the in-memory attributes for PARTS3. Observe that PARTS3 is created with FOR
QUERY HIGH compression and HIGH priority. The in-memory clause at the object level
takes precedence over the in-memory clause at the tablespace level.
SELECT INMEMORY, INMEMORY_PRIORITY, INMEMORY_COMPRESSION,
INMEMORY_DISTRIBUTE, INMEMORY_DUPLICATE
FROM USER_TABLES
WHERE TABLE_NAME = 'PARTS3';
2014 Oracle Corporation. All Rights Reserved.

Page 38

Oracle Database In-Memory Workshop

SOFTWARE.HARDWARE.COMPLETE

SQL> SELECT INMEMORY, INMEMORY_PRIORITY, INMEMORY_COMPRESSION,


INMEMORY_DISTRIBUTE, INMEMORY_DUPLICATE
FROM USER_TABLES
WHERE TABLE_NAME = 'PARTS3';
INMEMORY INMEMORY INMEMORY_COMPRESS INMEMORY_DISTRI INMEMORY_DUPL
-------- -------- ----------------- --------------- -----------ENABLED HIGH
FOR QUERY HIGH
AUTO
NO DUPLICATE

8. Disable the LAB_DATA tablespace for the IM column store by including a NO INMEMORY
clause in the ALTER TABLESPACE statement.
ALTER TABLESPACE LAB_DATA DEFAULT NO INMEMORY;
9. Check the tablespace level in-memory attributes for LAB_DATA and ensure they are now
cleared.
SELECT DEF_INMEMORY, DEF_INMEMORY_PRIORITY,
DEF_INMEMORY_COMPRESSION, DEF_INMEMORY_DISTRIBUTE,
DEF_INMEMORY_DUPLICATE
FROM DBA_TABLESPACES
WHERE TABLESPACE_NAME = 'LAB_DATA';
SQL> SELECT DEF_INMEMORY, DEF_INMEMORY_PRIORITY, DEF_INMEMORY_COMPRESSION,
DEF_INMEMORY_DISTRIBUTE, DEF_INMEMORY_DUPLICATE
FROM DBA_TABLESPACES
WHERE TABLESPACE_NAME = 'LAB_DATA';
DEF_INME DEF_INME DEF_INMEMORY_COMP DEF_INMEMORY_DI DEF_INMEMORY_
-------- -------- ----------------- --------------- ------------DISABLED

10. Check the in-memory table attributes for tables PARTS2 and PARTS3. Observe that the
attributes stay intact even after clearing them from the tablespace level. This is the
expected behavior.
SELECT INMEMORY, INMEMORY_PRIORITY, INMEMORY_COMPRESSION,
INMEMORY_DISTRIBUTE, INMEMORY_DUPLICATE
FROM USER_TABLES
WHERE TABLE_NAME IN ('PARTS2','PARTS3');

SQL> SELECT INMEMORY, INMEMORY_PRIORITY, INMEMORY_COMPRESSION,


INMEMORY_DISTRIBUTE, INMEMORY_DUPLICATE
FROM USER_TABLES
2014 Oracle Corporation. All Rights Reserved.

Page 39

Oracle Database In-Memory Workshop

SOFTWARE.HARDWARE.COMPLETE

WHERE TABLE_NAME IN ('PARTS2','PARTS3');


INMEMORY
-------ENABLED
ENABLED

3.7.

INMEMORY INMEMORY_COMPRESS INMEMORY_DISTRI INMEMORY_DUPL


-------- ----------------- --------------- -----------HIGH
FOR QUERY HIGH
AUTO
NO DUPLICATE
LOW
FOR CAPACITY HIGH AUTO
NO DUPLICATE

USING THE INMEMORY_CLAUSE_DEFAULT INSTANCE PARAMETER

The INMEMORY_CLAUSE_DEFAULT initialization parameter enables you to specify a default IM


column store clause for new tables and materialized views.
Set this parameter to a valid INMEMORY clause, that will be used as the default for all new
tables and materialized views. The clause can include valid clauses for IM column store
compression methods and data population options.
Leave INMEMORY_CLAUSE_DEFAULT parameter unset or set it to an empty string to disable
this behavior. Setting the value of this parameter to NO INMEMORY has the same effect as
setting it to the default value (the empty string).
If the clause starts with INMEMORY, then all new tables and materialized views, including those
without an INMEMORY clause, are populated in the IM column store. If the clause omits
INMEMORY, then it only applies to new tables and materialized views that are enabled for the
IM column store with an INMEMORY clause.
For example, if the INMEMORY_CLAUSE_DEFAULT parameter is set to MEMCOMPRESS FOR
CAPACITY LOW and a table is created as INMEMORY PRIORITY HIGH, then the table is
treated as if it was declared with the union of two clauses, i.e. INMEMORY MEMCOMPRESS FOR
CAPACITY LOW PRIORITY HIGH.
Note: Objects explicitly created with the NO INMEMORY clause will not inherit the instancelevel INMEMORY_CLAUSE_DEFAULT parameter. Also, if there is a default in-memory clause
specified for the tablespace for a given segment, then the tablespace-level clause will override
the value of the instance-level clause.

2014 Oracle Corporation. All Rights Reserved.

Page 40

Oracle Database In-Memory Workshop

SOFTWARE.HARDWARE.COMPLETE

LAB STEPS
1. Start a new terminal session.

2. Login to the database using SQL*Plus as the SYS user with SYSDBA role.
$> sqlplus / AS SYSDBA
3. Enable the INMEMORY_CLAUSE_DEFAULT parameter using the ALTER SYSTEM command.
This parameter can be modified with SCOPE=BOTH, which means there is no need to restart
the database.
ALTER SYSTEM SET INMEMORY_CLAUSE_DEFAULT = "MEMCOMPRESS FOR QUERY
HIGH" SCOPE=BOTH;
4. In the same SQL*Plus session, connect as the LABUSER.
CONNECT LABUSER/labuser;
5. Create a table named TEST_TAB and enable it for the column store by specifying the inmemory PRIORITY of HIGH.
CREATE TABLE TEST_TAB (COL1 NUMBER) INMEMORY PRIORITY HIGH;
6. Check the in-memory table attributes for TEST_TAB. Observe that the in-memory attributes
are a union of the table level in-memory clause and the instance level
INMEMORY_CLAUSE_DEFAULT.
SELECT INMEMORY, INMEMORY_PRIORITY, INMEMORY_COMPRESSION,
INMEMORY_DISTRIBUTE, INMEMORY_DUPLICATE
FROM USER_TABLES
WHERE TABLE_NAME = 'TEST_TAB';

SQL> SELECT INMEMORY, INMEMORY_PRIORITY, INMEMORY_COMPRESSION,


INMEMORY_DISTRIBUTE, INMEMORY_DUPLICATE
FROM USER_TABLES
WHERE TABLE_NAME = 'TEST_TAB';

2014 Oracle Corporation. All Rights Reserved.

Page 41

Oracle Database In-Memory Workshop

SOFTWARE.HARDWARE.COMPLETE

INMEMORY INMEMORY INMEMORY_COMPRESS INMEMORY_DISTRI INMEMORY_DUPL


-------- -------- ----------------- --------------- ------------ENABLED HIGH
FOR QUERY HIGH
AUTO
NO DUPLICATE

7. Create another table named TEST_TAB2 and enable it for the column store by specifying
the in-memory clause, along with the clause MEMCOMPRESS FOR CAPACITY LOW.
CREATE TABLE TEST_TAB2 (COL1 NUMBER) INMEMORY MEMCOMPRESS FOR
CAPACITY LOW;
8. Check the in-memory table attributes for TEST_TAB2. Observe that the MEMCOMPRESS
clause specified at the table level (i.e. FOR CAPACITY LOW) is persisted and the instance
level MEMCOMPRESS clause is not inherited. This is the expected behavior.
SELECT INMEMORY, INMEMORY_PRIORITY, INMEMORY_COMPRESSION,
INMEMORY_DISTRIBUTE, INMEMORY_DUPLICATE
FROM USER_TABLES
WHERE TABLE_NAME = 'TEST_TAB2';

SQL> SELECT INMEMORY, INMEMORY_PRIORITY, INMEMORY_COMPRESSION,


INMEMORY_DISTRIBUTE, INMEMORY_DUPLICATE
FROM USER_TABLES
WHERE TABLE_NAME = 'TEST_TAB2';
INMEMORY INMEMORY INMEMORY_COMPRESS INMEMORY_DISTRI INMEMORY_DUPL
-------- -------- ----------------- --------------- ------------ENABLED NONE
FOR CAPACITY LOW AUTO
NO DUPLICATE

9. Create another table named TEST_TAB3 and specifically disable it for the column store by
specifying NO INMEMORY.
CREATE TABLE TEST_TAB3 (COL1 NUMBER) NO INMEMORY;
10. Check the in-memory table attributes for TEST_TAB3. Observe that TEST_TAB3 is not
enabled for the IM column store.
SELECT INMEMORY, INMEMORY_PRIORITY, INMEMORY_COMPRESSION,
INMEMORY_DISTRIBUTE, INMEMORY_DUPLICATE
FROM USER_TABLES
WHERE TABLE_NAME = 'TEST_TAB3';

SQL> SELECT INMEMORY, INMEMORY_PRIORITY, INMEMORY_COMPRESSION,


INMEMORY_DISTRIBUTE, INMEMORY_DUPLICATE
2014 Oracle Corporation. All Rights Reserved.

Page 42

Oracle Database In-Memory Workshop

SOFTWARE.HARDWARE.COMPLETE

FROM USER_TABLES
WHERE TABLE_NAME = 'TEST_TAB3';
INMEMORY INMEMORY INMEMORY_COMPRESS INMEMORY_DISTRI INMEMORY_DUPL
-------- -------- ----------------- --------------- ------------DISABLED

11. Create another table named TEST_TAB4 and do not specify the INMEMORY clause.
CREATE TABLE TEST_TAB4 (COL1 NUMBER);
12. Check the in-memory table attributes for TEST_TAB4. Observe that TEST_TAB4 is not
enabled for the IM column store, as initialization parameter INMEMORY_CLAUSE_DEFAULT
did not contain the string INMEMORY.
SELECT INMEMORY, INMEMORY_PRIORITY, INMEMORY_COMPRESSION,
INMEMORY_DISTRIBUTE, INMEMORY_DUPLICATE
FROM USER_TABLES
WHERE TABLE_NAME = 'TEST_TAB4';

SQL> SELECT INMEMORY, INMEMORY_PRIORITY, INMEMORY_COMPRESSION,


INMEMORY_DISTRIBUTE, INMEMORY_DUPLICATE
FROM USER_TABLES
WHERE TABLE_NAME = 'TEST_TAB4';
INMEMORY INMEMORY INMEMORY_COMPRESS INMEMORY_DISTRI INMEMORY_DUPL
-------- -------- ----------------- --------------- ------------DISABLED

13. Cleanup the schema by dropping the tables created for the purpose of this lesson.
DROP
DROP
DROP
DROP

TABLE
TABLE
TABLE
TABLE

TEST_TAB;
TEST_TAB2;
TEST_TAB3;
TEST_TAB4;

14. Disable the INMEMORY_CLAUSE_DEFAULT.


ALTER SYSTEM SET INMEMORY_CLAUSE_DEFAULT = '' SCOPE=BOTH;

3.8.

SUMMARY

In this lesson, you had an opportunity to experience how easy it is to mark an object to be
populated into the in-memory column store. You may enable a table, partition, subpartition,
2014 Oracle Corporation. All Rights Reserved.

Page 43

Oracle Database In-Memory Workshop

SOFTWARE.HARDWARE.COMPLETE

materialized views and tablespaces for in-memory via the new in-memory clause. Also by
default, enabling the table for in-memory does not automatically initiate its population. InMemory Column Store population is discussed next.

2014 Oracle Corporation. All Rights Reserved.

Page 44

Oracle Database In-Memory Workshop

4.

SOFTWARE.HARDWARE.COMPLETE

POPULATING THE IM COLUMN STORE

Although you have enabled the objects for the IM column store (i.e. by enabling their inmemory attributes), they still do not reside in the IM column store. This is because, by default,
Oracle automatically decides when to populate the table into the column store (referred to as
on-demand population). You could also manually initiate the population manually by executing
the DBMS_INMEMORY procedures or by querying the object.
If you want to enable automatic population of objects into the IM column store, you can use the
PRIORITY sub-clause of the INMEMORY clause.
Note: Populate is the term used to bring data into the IM column store. We use the term
populate instead of load because load is commonly used to mean inserting new data into
the database. Populate doesnt bring new data into the database, it brings existing data into
memory and reorganizes it in an optimized column format.
Note: When an object does not have the in-memory clause specified, and when the
tablespace to which it belongs does not have it specified either, then the only way to force
populate it into the IM column store is by using the INMEMORY_FORCE initialization parameter.

4.1.

POPULATING BY QUERYING THE OBJECT

By default, Oracle typically populates the table after it gets accessed (i.e. queried via full table
scan) for the first time. When an object is enabled for the column store and is queried, and if
the query requires data that has not yet been populated in the column store, then the database
reads the requested data from the buffer cache or disk while background processes
asynchronously populate the missing data in the IM column store. With this asynchronous
background population, the columnar version of the table gradually becomes available for later
queries.
The IM column store is populated by a set of background processes referred to as worker
processes (e.g. ora_w***_*). Each worker process is given a subset of database blocks from
the object to populate into the IM column store. Population is a streaming mechanism,
simultaneously columnizing and compressing the data. The database is fully active /
accessible while this occurs.
2014 Oracle Corporation. All Rights Reserved.

Page 45

Oracle Database In-Memory Workshop

SOFTWARE.HARDWARE.COMPLETE

Just as a tablespace on disk is made up of multiple extents, the IM column store is made up of
multiple In-Memory Compression Units (IMCUs). Each worker process allocates its own IMCU
and populates its subset of database blocks in the IMCU. Data is not sorted or ordered in any
specific way during population. It is read in the same order it appears in the row format. The
size and chunk of the IMCU is determined by the system using internal heuristics.

LAB STEPS
1. In the previous SQL*Plus session connected as the LABUSER, enable the SALES table to
use the column store using the following SQL.
ALTER TABLE SALES INMEMORY;
2. Ensure by querying the dictionary view that the table is enabled for in-memory.
SELECT INMEMORY, INMEMORY_PRIORITY, INMEMORY_COMPRESSION,
INMEMORY_DISTRIBUTE, INMEMORY_DUPLICATE
FROM USER_TABLES
WHERE TABLE_NAME = 'SALES';
3. There are two new V$ views, mainly V$IM_SEGMENTS and V$IM_USER_SEGMENTS, that
indicate what objects are populated in the IM column store and their population status.
These views contain only the segments that have an in-memory representation. If a
segment is marked for the in-memory store (IM column store) but is not populated, no
corresponding row for that segment is displayed in this view.
V$IM_USER_SEGMENTS presents the same information as V$IM_SEGMENTS but only for
the current database user.
4. DESCRIBE the V$IM_SEGMENTS view to display the attributes it contains. As you can see
from the column names, the view provides information about the objects that are in the
column store.
DESC V$IM_SEGMENTS

SQL> DESC V$IM_SEGMENTS


Name
Null?
Type
--------------------------- -------- -----------------OWNER
VARCHAR2(128)
2014 Oracle Corporation. All Rights Reserved.

Page 46

Oracle Database In-Memory Workshop


SEGMENT_NAME
PARTITION_NAME
SEGMENT_TYPE
TABLESPACE_NAME
INMEMORY_SIZE
BYTES
BYTES_NOT_POPULATED
POPULATE_STATUS
INMEMORY_PRIORITY
INMEMORY_DISTRIBUTE
INMEMORY_DUPLICATE
INMEMORY_COMPRESSION
CON_ID

SOFTWARE.HARDWARE.COMPLETE

VARCHAR2(128)
VARCHAR2(128)
VARCHAR2(18)
VARCHAR2(30)
NUMBER
NUMBER
NUMBER
VARCHAR2(9)
VARCHAR2(8)
VARCHAR2(15)
VARCHAR2(13)
VARCHAR2(17)
NUMBER

5. In order to determine what objects are in the IM column store, query the V$IM_SEGMENTS
view using the below SQL. Ensure that the SALES table is not output by the below query as
it was just enabled.
SELECT OWNER, SEGMENT_NAME, POPULATE_STATUS, BYTES_NOT_POPULATED
FROM V$IM_SEGMENTS;
6. Now its time to populate the SALES table by executing a simple query (count) to trigger its
population into the column store. Notice the use of the full table scan hint. This is needed
because SALES has index enabled and will be used for the count (by passing SALES).
SELECT /*+ FULL (s) */ COUNT(*) FROM SALES s;
7. You can watch as the background processes populate the IM column store by opening a
second terminal window and executing the top command from the Linux command line.
You will know the population has completed when you no longer see the ora_w***_orcl
processes at the top of the process list.
$> top
8. Alternatively, you can monitor the progress of population by querying the view
V$IM_SEGMENTS. Observe that the SALES table will now show in this view. As the table
gets loaded, the BYTES_NOT_POPULATED and the STATUS columns may change. Having
0 in the BYTES_NOT_POPULATED column and the STATUS of COMPLETED, indicates that
the entire table has been completely populated into the column store.
SELECT OWNER, SEGMENT_NAME, POPULATE_STATUS, BYTES_NOT_POPULATED
FROM V$IM_SEGMENTS;
2014 Oracle Corporation. All Rights Reserved.

Page 47

Oracle Database In-Memory Workshop

SOFTWARE.HARDWARE.COMPLETE

SQL> SELECT OWNER, SEGMENT_NAME, POPULATE_STATUS, BYTES_NOT_POPULATED


FROM V$IM_SEGMENTS;
OWNER
------LABUSER

SEGMENT_NAME
-----------SALES

POPULATE_
--------COMPLETED

BYTES_NOT_POPULATED
------------------0

9. The actual size of the objects in the IM column store is shown in V$IM_SEGMENTS. The
column BYTES contain the total size of the on-disk segment (in bytes), whereas
INMEMORY_SIZE contain the total size of the in-memory version of the segment (in bytes).
The sizes will be different due to the data being compressed in the in-memory column
store. Use the following SQL to query V$IM_SEGMENTS.
SELECT OWNER, SEGMENT_NAME, BYTES, INMEMORY_SIZE
FROM V$IM_SEGMENTS;
SQL> SELECT OWNER, SEGMENT_NAME, BYTES, INMEMORY_SIZE FROM V$IM_SEGMENTS;
OWNER
----LABUSER

SEGMENT_NAME BYTES
------------ --------SALES
33554432

INMEMORY_SIZE
------------7536640

10. As you observe from the above output, the in-memory size of SALES is smaller than its ondisk size (about 22% of its on-disk size). This is because the default in-memory
compression (QUERY LOW) was applied to this table.
11. Now, disable the SALES table for the IM column store using the NO INMEMORY clause.
ALTER TABLE SALES NO INMEMORY;
12. Notice that once the table is disabled, it is gone form the column store. You can query the
V$IM_SEGMENTS view to ensure that it does not list the SALES table.
SELECT OWNER, SEGMENT_NAME, BYTES, INMEMORY_SIZE
FROM V$IM_SEGMENTS;

4.2.

POPULATING USING DBMS_INMEMORY

The DBMS_INMEMORY package provides an interface for in-memory column store functionality
by providing two procedures.
2014 Oracle Corporation. All Rights Reserved.

Page 48

Oracle Database In-Memory Workshop

SOFTWARE.HARDWARE.COMPLETE

POPULATE: Forces population of a given table.


REPOPULATE: Forces repopulation of a given table, after it has been populated at least
once.

LAB STEPS
1. In the previous SQL*Plus session connected as the LABUSER, re-enable the SALES table
to use the column store.
ALTER TABLE SALES INMEMORY;
2. Query the V$IM_SEGMENTS view and ensure that the SALES table is not populated into the
column store.
SELECT OWNER, SEGMENT_NAME, POPULATE_STATUS, BYTES_NOT_POPULATED
FROM V$IM_SEGMENTS;
3. Populate the SALES table by executing the DBMS_INMEMORY.POPULATE procedure. This
procedure is to be used for first time population only.
EXEC DBMS_INMEMORY.POPULATE('LABUSER','SALES');
4. Monitor the progress of the population by querying the view V$IM_SEGMENTS.
SELECT OWNER, SEGMENT_NAME, POPULATE_STATUS, BYTES_NOT_POPULATED
FROM V$IM_SEGMENTS;
SQL> SELECT OWNER, SEGMENT_NAME, POPULATE_STATUS, BYTES_NOT_POPULATED
FROM V$IM_SEGMENTS;
OWNER
------LABUSER

SEGMENT_NAME
-----------SALES

POPULATE_
--------COMPLETED

BYTES_NOT_POPULATED
------------------0

5. Flush out the IMCUs from the IM column store for SALES, by disabling and re-enabling the
table for INMEMORY.
ALTER TABLE SALES NO INMEMORY;
ALTER TABLE SALES INMEMORY;
6. Populate the SALES table once again by executing the DBMS_INMEMORY.REPOPULATE
2014 Oracle Corporation. All Rights Reserved.

Page 49

Oracle Database In-Memory Workshop

SOFTWARE.HARDWARE.COMPLETE

with FORCE=TRUE option. This option forces a complete re-population, which is similar to a
full refresh.
EXEC DBMS_INMEMORY.REPOPULATE('LABUSER','SALES', FORCE=>TRUE);
7. Monitor the progress of the population by querying the view V$IM_SEGMENTS.
SELECT OWNER, SEGMENT_NAME, POPULATE_STATUS, BYTES_NOT_POPULATED
FROM V$IM_SEGMENTS;
SQL> SELECT OWNER, SEGMENT_NAME, POPULATE_STATUS, BYTES_NOT_POPULATED
FROM V$IM_SEGMENTS;
OWNER
------LABUSER

SEGMENT_NAME
-----------SALES

POPULATE_
--------COMPLETED

BYTES_NOT_POPULATED
------------------0

8. Disable the SALES table for the IM column store, using the NO INMEMORY clause.
ALTER TABLE SALES NO INMEMORY;

4.3.

POPULATING AUTOMATICALLY USING THE PRIORITY CLAUSE

Objects can set to be automatically populated in the IM column store after the database is
opened, or after the object is altered, or loaded with data. This is possible by specifying a subclause to the INMEMORY clause called PRIORITY. Objects get populated in a prioritized list,
the order of which is controlled by the priority level (NONE, LOW, MEDIUM, HIGH,
CRITICAL). All objects at a given priority level must be fully populated before the population
for any objects at a lower priority level can commence.
However, the population order can be superseded if an object without a PRIORITY is scanned,
thereby triggering its population into IM column store. The default PRIORITY is NONE, which
means an object is populated only after it is scanned for the first time.
The population algorithm also varies depending on whether you use single-instance or Oracle
RAC. Further details on RAC and IM Column Store are provided later in this lesson.
The database must reconstruct the entire in-memory columnar representation from the on-disk
representation every time the database instance restarts. This reconstruction is necessary
2014 Oracle Corporation. All Rights Reserved.

Page 50

Oracle Database In-Memory Workshop

SOFTWARE.HARDWARE.COMPLETE

because the IM column store resides only in memory.

LAB STEPS
1. In the previous SQL*Plus session connected as the LABUSER, alter the SALES table to be
enabled for the IM column store with PRIORITY HIGH.
ALTER TABLE SALES INMEMORY PRIORITY HIGH;
2. Alter the CUSTOMERS table to be enabled for the IM column store with PRIORITY MEDIUM.
ALTER TABLE CUSTOMERS INMEMORY PRIORITY MEDIUM;
3. Alter the COSTS table to be enabled for the IM column store with PRIORITY LOW.
ALTER TABLE COSTS INMEMORY PRIORITY LOW;
4. Observe their population by running the below SQL. When all the objects get populated,
the below SQL would return COMPLETED in POPULATE_STATUS for all the three tables.
Observe that the population was started in the order of priority by looking at the
START_POP and INMEMORY_PRIORITY columns. Also observe that the next population did
not start (START_POP) until FINISH_POP time of the previous table having a higher
PRIORITY.
Note: You may have to run the below query a few times as the population/repopulation
process is set to wake up every 2 minutes.
COL OBJECT_NAME FORMAT A15
SELECT a.OBJECT_NAME, b.INMEMORY_PRIORITY, b.POPULATE_STATUS,
TO_CHAR(c.CREATETIME, 'MM/DD/YYYY HH24:MI:SS.FF2') START_POP,
TO_CHAR(MAX(d.TIMESTAMP),'MM/DD/YYYY HH24:MI:SS.FF2') FINISH_POP
FROM DBA_OBJECTS a, V$IM_SEGMENTS b,
V$IM_SEGMENTS_DETAIL c, V$IM_HEADER d
WHERE OBJECT_NAME IN ('CUSTOMERS','SALES','COSTS')
AND a.OBJECT_NAME = b.SEGMENT_NAME
AND a.OBJECT_TYPE = 'TABLE'
AND a.OBJECT_ID = c.BASEOBJ
AND c.DATAOBJ = d.OBJD
GROUP BY a.OBJECT_NAME, b.INMEMORY_PRIORITY, b.POPULATE_STATUS,
c.CREATETIME
ORDER BY FINISH_POP;
2014 Oracle Corporation. All Rights Reserved.

Page 51

Oracle Database In-Memory Workshop

OBJECT_NAME
----------SALES
CUSTOMERS
COSTS

INMEMORY
-------HIGH
MEDIUM
LOW

POPULATE_
--------COMPLETED
COMPLETED
COMPLETED

SOFTWARE.HARDWARE.COMPLETE

START_POP
---------------------10/06/2014 22:12:08.62
10/06/2014 22:12:13.68
10/06/2014 22:12:15.52

FINISH_POP
---------------------10/06/2014 22:12:11.37
10/06/2014 22:12:14.50
10/06/2014 22:12:15.97

5. Next, you will restart the database, which will initiate a population on startup. You should
observe the same effect as seen in the previous step.
6. Re-connect as the SYS user with the SYSDBA role.
CONNECT / AS SYSDBA
7. Restart the database.
SHUTDOWN IMMEDIATE;
STARTUP;
8. Observe the object population again by running the below SQL. When the objects get
populated, the below SQL would return COMPLETED in POPULATE_STATUS for all the three
tables. You may need to wait a bit for the population to complete.
COL OBJECT_NAME FORMAT A15
SELECT a.OBJECT_NAME, b.INMEMORY_PRIORITY, b.POPULATE_STATUS,
TO_CHAR(c.CREATETIME, 'MM/DD/YYYY HH24:MI:SS.FF2') START_POP,
TO_CHAR(MAX(d.TIMESTAMP),'MM/DD/YYYY HH24:MI:SS.FF2') FINISH_POP
FROM DBA_OBJECTS a, V$IM_SEGMENTS b,
V$IM_SEGMENTS_DETAIL c, V$IM_HEADER d
WHERE OBJECT_NAME IN ('CUSTOMERS','SALES','COSTS')
AND a.OBJECT_NAME = b.SEGMENT_NAME
AND a.OBJECT_TYPE = 'TABLE'
AND a.OBJECT_ID = c.BASEOBJ
AND c.DATAOBJ = d.OBJD
GROUP BY a.OBJECT_NAME, b.INMEMORY_PRIORITY, b.POPULATE_STATUS,
c.CREATETIME
ORDER BY FINISH_POP;

OBJECT_NAME
----------SALES
CUSTOMERS
COSTS

INMEMORY
-------HIGH
MEDIUM
LOW

POPULATE_
--------COMPLETED
COMPLETED
COMPLETED

2014 Oracle Corporation. All Rights Reserved.

START_POP
---------------------10/06/2014 22:17:43.17
10/06/2014 22:17:44.64
10/06/2014 22:17:45.02

FINISH_POP
---------------------10/06/2014 22:17:44.63
10/06/2014 22:17:45.01
10/06/2014 22:17:45.16

Page 52

Oracle Database In-Memory Workshop

SOFTWARE.HARDWARE.COMPLETE

9. Did the results of this test match the previous population?

4.4.

CONSIDERATIONS FOR RAC

In a RAC environment each database node has its own In-Memory Column Store. The same
object can be in each of the column stores. This is referred to as DUPLICATE. Alternatively if
an object is too big to fit in the IM column store on a single node it is possible for pieces of that
object to be distributed between each of the RAC nodes. This is referred to as DISTRIBUTE.
How each object should populate in the column store is displayed in the
INMEMORY_DISTRIBUTE column of the *_TABLES views. The default value is AUTODISTRIBUTE, where Oracle automatically decides how an objects should be distribute among
the IM column store in a RAC environment. On a single instance database this attribute has no
effect. By default in Oracle RAC, each in-memory table is distributed among the database
instances.
The default NO DUPLICATE clause specifies that the database maintain only one copy of an
object. For example, a three-node Oracle RAC might store the 2012 partition of a SALES table
in instance 1, the 2013 partition in instance 2, and the 2014 partition in instance 3. Each table
partition resides in exactly one instance.
To increase availability, you can use the DUPLICATE ALL clause to specify that each inmemory table is available on each database instance. For example, the entire SALES table
resides in instance 1, instance 2, and instance 3. Thus, any instance can retrieve the data for a
query of SALES.
In contrast to DUPLICATE ALL, the DUPLICATE clause specifies that the database maintain
two copies of an object in different database instances. For example, the database can
maintain a copy of the 2014 partition of SALES in both instance 1 and instance 3. Only one
instance is the primary for this table partition, but the database can use either the primary copy
or the backup to satisfy a query. If the primary database instance fails, then the surviving
instance becomes the primary.
Note: When you deploy Oracle RAC on a non-engineered system, the DUPLICATE clause is
treated as NO DUPLICATE.
2014 Oracle Corporation. All Rights Reserved.

Page 53

Oracle Database In-Memory Workshop

4.5.

SOFTWARE.HARDWARE.COMPLETE

SUMMARY

In this lesson, you were able to populate the in-memory enabled objects in the in-memory
column store, via three different ways. First, by accessing the object via a query to force trigger
its population so subsequent queries would access it directly from the IM column store.
Second, you also force populated the object using DBMS_INMEMORY.POPULATE procedure.
Third, you have seen the use of the PRIORITY clause to trigger automatic population of the
object by the Oracle Database.
The population speed depends on the CPU capacity of the system, as the data compression
(which happens by default) is a CPU intensive operation. The more CPU you have the faster
the populations will occur. The next lesson discusses data compression options of the IM
column store.

2014 Oracle Corporation. All Rights Reserved.

Page 54

Oracle Database In-Memory Workshop

5.

SOFTWARE.HARDWARE.COMPLETE

IN-MEMORY COLUMNAR COMPRESSION

The IM column store uses special compression formats optimized for access speed rather than
storage reduction. The database increases speed in the following ways:
The compression formats enable the database to decrease the amount of memory
processed for each column. SQL executes directly on the compressed columns (when a
select few compression formats are used).
The database uses SIMD vector (array) instructions to process an array of column
values in a single CPU clock cycle. The database can store many values in a vector,
which maximizes the performance benefits with SIMD vector processing.
The MEMCOMPRESS sub-clause of CREATE and ALTER allows you to specify compression
options for each table, partition, or column. For example, you might optimize some columns in
a table for scan speed, and others for storage, therefore choose to compress them differently.
The default compression option is MEMCOMPRESS FOR QUERY LOW. This option provides the
fastest read times because the database does not need to decompress the data. The other
compression options, such as FOR QUERY HIGH and FOR CAPACITY, use additional layers
of compression, some of which require decompression. The following are the various
compression options possible in the IM column store.
NO MEMCOMPRESS: Data is populated without any compression
MEMCOMPRESS FOR DML: Minimal compression optimized for DML performance
MEMCOMPRESS FOR QUERY LOW: Optimized for query performance (default)
MEMCOMPRESS FOR QUERY HIGH: Optimized for query performance as well as space
saving
MEMCOMPRESS FOR CAPACITY LOW: Balanced with a greater bias towards space
saving
MEMCOMPRESS FOR CAPACITY HIGH: Optimized for space saving
2014 Oracle Corporation. All Rights Reserved.

Page 55

Oracle Database In-Memory Workshop

5.1.

SOFTWARE.HARDWARE.COMPLETE

COMPRESSING OBJECTS IN-MEMORY

By default, data is compressed using the FOR QUERY LOW option, which provides the best
performance for queries. This option utilizes common compression techniques such as
Dictionary Encoding, Run Length Encoding and Bit-Packing. The FOR CAPACITY options
apply an additional compression technique on top of FOR QUERY [LOW|HIGH] compression,
which can have a significant impact on performance as each entry must be decompressed
before the WHERE clause predicates can be applied. The FOR CAPACITY LOW option applies
a proprietary compression technique called OZIP that offers extremely fast decompression that
is tuned specifically for the Oracle Database. The FOR CAPACITY HIGH option applies a
heavier-weight compression algorithm with a larger penalty on decompression in order to
provide higher compression.
The compression option used at the table level is shown in the INMEMORY_COMPRESSION
column of the *_TABLES views.

5.1.1.

DEFAULT COMPRESSION

Lets create a table without the MEMCOMPRESS clause and validate that the default
compression method was used. Populate the table into the column store and verify its
compression ratio.

LAB STEPS
1. In a SQL*Plus session, connect as the LABUSER user.
CONNECT LABUSER/labuser
2. Create a table via CTAS. Enable the table for INMEMORY at create time and do not specify
the MEMCOMPRESS clause.
CREATE TABLE SALES_INM INMEMORY AS SELECT * FROM SALES;
SQL> CREATE TABLE SALES_INM INMEMORY AS SELECT * FROM SALES;
Table created.

3. Check the INMEMORY_COMPRESSION attribute by querying USER_SEGMENTS. Notice that


2014 Oracle Corporation. All Rights Reserved.

Page 56

Oracle Database In-Memory Workshop

SOFTWARE.HARDWARE.COMPLETE

the default compression method of FOR QUERY LOW is used.


Note: V$IM_SEGMENTS contains information at the segment level, so if you had partitioned
tables, you would see them listed in this view.
COL SEGMENT_NAME FORMAT A30
SELECT SEGMENT_NAME, INMEMORY, INMEMORY_COMPRESSION FROM
USER_SEGMENTS WHERE SEGMENT_NAME = 'SALES_INM';
SQL> SELECT SEGMENT_NAME, INMEMORY, INMEMORY_COMPRESSION FROM USER_SEGMENTS
WHERE SEGMENT_NAME = 'SALES_INM';
SEGMENT_NAME
INMEMORY INMEMORY_COMPRESS
------------------------ -------- ----------------SALES_INM
ENABLED FOR QUERY LOW

4. Execute a simple COUNT(*) query to trigger SALES_INMs population into the IM column
store.
SELECT COUNT(*) FROM SALES_INM;
5. Monitor the IM column store population progress by querying V$IM_SEGMENTS. Wait until
the BYTES_NOT_POPULATED is 0 and the STATUS is COMPLETED before moving to the
next step.
COL OWNER FORMAT A20
SELECT OWNER, SEGMENT_NAME, POPULATE_STATUS, BYTES_NOT_POPULATED
FROM V$IM_SEGMENTS WHERE SEGMENT_NAME = 'SALES_INM';
SQL> COL OWNER FORMAT A20
SQL> SELECT OWNER, SEGMENT_NAME, POPULATE_STATUS, BYTES_NOT_POPULATED
FROM V$IM_SEGMENTS WHERE SEGMENT_NAME = 'SALES_INM';
OWNER
SEGMENT_NAME
POPULATE_ BYTES_NOT_POPULATED
---------------- ---------------------- --------- ------------------LABUSER
SALES_INM
COMPLETED
0

6. Check the time it took to populate the table by using the following query. Record the
FINISH_POP time for later comparisons.
COL OBJECT_NAME FORMAT A20
2014 Oracle Corporation. All Rights Reserved.

Page 57

Oracle Database In-Memory Workshop

SOFTWARE.HARDWARE.COMPLETE

SELECT a.OBJECT_NAME, b.POPULATE_STATUS,


TO_CHAR(c.CREATETIME, 'MM/DD/YYYY HH24:MI:SS.FF2') START_POP,
TO_CHAR(MAX(d.TIMESTAMP),'MM/DD/YYYY HH24:MI:SS.FF2') FINISH_POP
FROM DBA_OBJECTS a, V$IM_SEGMENTS b,
V$IM_SEGMENTS_DETAIL c, V$IM_HEADER d
WHERE OBJECT_NAME IN ('SALES_INM')
AND a.OBJECT_NAME = b.SEGMENT_NAME
AND a.OBJECT_TYPE = 'TABLE'
AND a.OBJECT_ID = c.BASEOBJ
AND c.DATAOBJ = d.OBJD
GROUP BY a.OBJECT_NAME, b.INMEMORY_PRIORITY, b.POPULATE_STATUS,
c.CREATETIME;

SQL> COL OBJECT_NAME FORMAT A20


SELECT a.OBJECT_NAME, b.POPULATE_STATUS,
TO_CHAR(c.CREATETIME, 'MM/DD/YYYY HH24:MI:SS.FF2') START_POP,
TO_CHAR(MAX(d.TIMESTAMP),'MM/DD/YYYY HH24:MI:SS.FF2') FINISH_POP
FROM DBA_OBJECTS a, V$IM_SEGMENTS b, V$IM_SEGMENTS_DETAIL c, V$IM_HEADER d
WHERE OBJECT_NAME IN ('SALES_INM')
AND a.OBJECT_NAME = b.SEGMENT_NAME
AND a.OBJECT_TYPE = 'TABLE'
AND a.OBJECT_ID = c.BASEOBJ
AND c.DATAOBJ = d.OBJD
GROUP BY a.OBJECT_NAME, b.INMEMORY_PRIORITY, b.POPULATE_STATUS, c.CREATETIME;
OBJECT_NAME POPULATE_ START_POP
FINISH_POP
------------ --------- ---------------------- ---------------------SALES_INM
COMPLETED 10/06/2014 12:10:38.98 10/06/2014 12:10:39.99

7. Compute the compression ratio by running the following query. The BYTES column of
V$IM_SEGMENTS gives you the on-disk table size, whereas the INMEMORY_SIZE column
gives you the corresponding in-memory size.
SELECT V.OWNER, V.SEGMENT_NAME,
V.BYTES ORIG_SIZE,
V.INMEMORY_SIZE IN_MEM_SIZE,
V.BYTES/V.INMEMORY_SIZE COMP_RATIO
FROM V$IM_SEGMENTS V
WHERE SEGMENT_NAME = 'SALES_INM';

SQL> SELECT V.OWNER, V.SEGMENT_NAME,


V.BYTES ORIG_SIZE,
V.INMEMORY_SIZE IN_MEM_SIZE,
V.BYTES/V.INMEMORY_SIZE COMP_RATIO
FROM V$IM_SEGMENTS V
HERE SEGMENT_NAME = 'SALES_INM';
2014 Oracle Corporation. All Rights Reserved.

Page 58

Oracle Database In-Memory Workshop

SOFTWARE.HARDWARE.COMPLETE

OWNER
SEGMENT_NAME ORIG_SIZE IN_MEM_SIZE COMP_RATIO
---------------- ------------ --------- ----------- ---------LABUSER
SALES_INM
12582912
7536640 1.66956522

8. As you observe from the above output, the QUERY LOW compression on SALES_INM is
compressed 1.7x times, i.e. to 60% of its on-disk size.

5.1.2.

CAPACITY HIGH COMPRESSION

Lets create another table with CAPACITY HIGH compression clause and verify the
compression ratio and the time it takes to populate the table to the IM column store.

LAB STEPS
1. In the previous SQL*Plus session connected as the LABUSER user, create a table via
CTAS. Enable the table for INMEMORY at create time with MEMCOMPRESS FOR CAPACITY
HIGH, along with the PRIORITY clause of HIGH to initiate the population immediately after
the data load.
CREATE TABLE SALES_INM2 INMEMORY MEMCOMPRESS FOR CAPACITY HIGH
PRIORITY HIGH AS SELECT * FROM SALES;
SQL> CREATE TABLE SALES_INM2 INMEMORY MEMCOMPRESS FOR CAPACITY HIGH PRIORITY
HIGH AS SELECT * FROM SALES;
Table created.

2. Check the tables INMEMORY, INMEMORY_COMPRESSION, and INMEMORY_PRIORITY


attributes by querying USER_SEGMENTS. Validate the attributes correspond to the values
specified at creation time.
COL SEGMENT_NAME FORMAT A20
SELECT SEGMENT_NAME, INMEMORY, INMEMORY_PRIORITY,
INMEMORY_COMPRESSION FROM USER_SEGMENTS
WHERE SEGMENT_NAME = 'SALES_INM2';
SQL> COL SEGMENT_NAME FORMAT A20
SQL> SELECT SEGMENT_NAME, INMEMORY, INMEMORY_PRIORITY, INMEMORY_COMPRESSION FROM
USER_SEGMENTS WHERE SEGMENT_NAME = 'SALES_INM2';
2014 Oracle Corporation. All Rights Reserved.

Page 59

Oracle Database In-Memory Workshop

SOFTWARE.HARDWARE.COMPLETE

SEGMENT_NAME
INMEMORY INMEMORY INMEMORY_COMPRESS
---------------- -------- -------- ----------------SALES_INM2
ENABLED HIGH
FOR CAPACITY HIGH

3. As we had triggered the population at create time by specifying a PRIORITY of HIGH,


check the progress by querying V$IM_SEGMENTS. Wait until the BYTES_NOT_POPULATED
is 0 and the STATUS is COMPLETED before moving to the next step.
COL OWNER FORMAT A20
SELECT OWNER, SEGMENT_NAME, POPULATE_STATUS, BYTES_NOT_POPULATED
FROM V$IM_SEGMENTS WHERE SEGMENT_NAME = 'SALES_INM2';
SQL> COL OWNER FORMAT A20
SQL> SELECT OWNER, SEGMENT_NAME, POPULATE_STATUS, BYTES_NOT_POPULATED
FROM V$IM_SEGMENTS WHERE SEGMENT_NAME = 'SALES_INM2';
OWNER
SEGMENT_NAME
POPULATE_ BYTES_NOT_POPULATED
---------------- ---------------------- --------- ------------------LABUSER
SALES_INM2
COMPLETED
0

4. Check the time it took to populate the table by using the following query. Record the
FINISH_POP time and compare it with the prior value. What do you find?
Note: In the lab environment, you may not find a sizeable slowdown in population time
when a higher compression option is specified. This is because you are working with much
smaller datasets, which probably is not realistic when compared to a real world scenario.
COL OBJECT_NAME FORMAT A20
SELECT a.OBJECT_NAME, b.POPULATE_STATUS,
TO_CHAR(c.CREATETIME, 'MM/DD/YYYY HH24:MI:SS.FF2') START_POP,
TO_CHAR(MAX(d.TIMESTAMP),'MM/DD/YYYY HH24:MI:SS.FF2') FINISH_POP
FROM DBA_OBJECTS a, V$IM_SEGMENTS b,
V$IM_SEGMENTS_DETAIL c, V$IM_HEADER d
WHERE OBJECT_NAME IN ('SALES_INM2')
AND a.OBJECT_NAME = b.SEGMENT_NAME
AND a.OBJECT_TYPE = 'TABLE'
AND a.OBJECT_ID = c.BASEOBJ
AND c.DATAOBJ = d.OBJD
GROUP BY a.OBJECT_NAME, b.INMEMORY_PRIORITY, b.POPULATE_STATUS,
c.CREATETIME;

2014 Oracle Corporation. All Rights Reserved.

Page 60

Oracle Database In-Memory Workshop

SOFTWARE.HARDWARE.COMPLETE

SQL> COL OBJECT_NAME FORMAT A20


SELECT a.OBJECT_NAME, b.POPULATE_STATUS,
TO_CHAR(c.CREATETIME, 'MM/DD/YYYY HH24:MI:SS.FF2') START_POP,
TO_CHAR(MAX(d.TIMESTAMP),'MM/DD/YYYY HH24:MI:SS.FF2') FINISH_POP
FROM DBA_OBJECTS a, V$IM_SEGMENTS b,
V$IM_SEGMENTS_DETAIL c, V$IM_HEADER d
WHERE OBJECT_NAME IN ('SALES_INM2')
AND a.OBJECT_NAME = b.SEGMENT_NAME
AND a.OBJECT_TYPE = 'TABLE'
AND a.OBJECT_ID = c.BASEOBJ
AND c.DATAOBJ = d.OBJD
GROUP BY a.OBJECT_NAME, b.INMEMORY_PRIORITY, b.POPULATE_STATUS, c.CREATETIME;
OBJECT_NAME
POPULATE_ START_POP
FINISH_POP
---------------- --------- ---------------------- ---------------------SALES_INM2
COMPLETED 10/06/2014 13:12:28.31 10/06/2014 13:12:29.40

5. Compute the compression ratio by running the following query. How do the compression
ratios compare to the previous option of QUERY LOW?
SELECT V.OWNER, V.SEGMENT_NAME,
V.BYTES ORIG_SIZE,
V.INMEMORY_SIZE IN_MEM_SIZE,
V.BYTES/V.INMEMORY_SIZE COMP_RATIO
FROM V$IM_SEGMENTS V
WHERE SEGMENT_NAME = 'SALES_INM2';

SQL> SELECT V.OWNER, V.SEGMENT_NAME,


V.BYTES ORIG_SIZE,
V.INMEMORY_SIZE IN_MEM_SIZE,
V.BYTES/V.INMEMORY_SIZE COMP_RATIO
FROM V$IM_SEGMENTS V
WHERE SEGMENT_NAME = 'SALES_INM2';
OWNER
SEGMENT_NAME ORIG_SIZE IN_MEM_SIZE COMP_RATIO
---------------- ------------ --------- ----------- ---------LABUSER
SALES_INM2
12582912
2293760 5.48571429

6. As you observe from the above output, the CAPACITY HIGH compression on
SALES_INM2 is compressed about 5.5x times, i.e. 18% of its on-disk size.

5.1.3.

COLUMN LEVEL COMPRESSION

As you have seen in the earlier lessons, the compression techniques can be specified at the
column level using the in-memory column clause. In this lesson, you will apply selective
column level compression and validate the attributes using V$IM_COLUMN_LEVEL.
2014 Oracle Corporation. All Rights Reserved.

Page 61

Oracle Database In-Memory Workshop

SOFTWARE.HARDWARE.COMPLETE

Remember, this view returns no rows for a table that has no associated selective column
compression levels. For each column of a table that is associated with selective column
compression levels, this view presents:
The associated compression level of the column
Or, the string DEFAULT if no compression level has been defined for the column
Or NO INMEMORY if the column is DISABLED for IN MEMORY

LAB STEPS
1. In the previous SQL*Plus session connected as the LABUSER, alter the CUSTOMERS table
and enable a selective column level compression with the following settings:
CUST_FIRST_NAME and CUST_LAST_NAME: Compressed using QUERY HIGH
CUST_STREET_ADDRESS: Compressed using CAPACITY LOW
CUST_CITY and CUST_STATE_PROVINCE: No compression
All other columns: DEFAULT (i.e. QUERY LOW)
ALTER TABLE CUSTOMERS INMEMORY
INMEMORY MEMCOMPRESS FOR QUERY HIGH (CUST_FIRST_NAME,
CUST_LAST_NAME)
INMEMORY MEMCOMPRESS FOR CAPACITY LOW (CUST_STREET_ADDRESS)
INMEMORY NO MEMCOMPRESS (CUST_CITY, CUST_STATE_PROVINCE);
2. Check the column-level attributes for CUSTOMERS. Notice that the compression levels have
been changed according to the ALTER TABLE specification, as highlighted in the output.
SET LINES 100;
SELECT TABLE_NAME, COLUMN_NAME, INMEMORY_COMPRESSION
FROM V$IM_COLUMN_LEVEL
WHERE TABLE_NAME = 'CUSTOMERS';

SQL> SET LINES 100;


SQL> SELECT TABLE_NAME, COLUMN_NAME, INMEMORY_COMPRESSION
2014 Oracle Corporation. All Rights Reserved.

Page 62

Oracle Database In-Memory Workshop

SOFTWARE.HARDWARE.COMPLETE

FROM V$IM_COLUMN_LEVEL
WHERE TABLE_NAME = 'CUSTOMERS';
TABLE_NAME
-----------------------CUSTOMERS
CUSTOMERS
CUSTOMERS
CUSTOMERS
CUSTOMERS
CUSTOMERS
CUSTOMERS
CUSTOMERS
CUSTOMERS
CUSTOMERS
CUSTOMERS
CUSTOMERS
CUSTOMERS
CUSTOMERS
CUSTOMERS
CUSTOMERS
CUSTOMERS
CUSTOMERS
CUSTOMERS
CUSTOMERS
CUSTOMERS
CUSTOMERS
CUSTOMERS

COLUMN_NAME
---------------------------CUST_ID
CUST_FIRST_NAME
CUST_LAST_NAME
CUST_GENDER
CUST_YEAR_OF_BIRTH
CUST_MARITAL_STATUS
CUST_STREET_ADDRESS
CUST_POSTAL_CODE
CUST_CITY
CUST_CITY_ID
CUST_STATE_PROVINCE
CUST_STATE_PROVINCE_ID
COUNTRY_ID
CUST_MAIN_PHONE_NUMBER
CUST_INCOME_LEVEL
CUST_CREDIT_LIMIT
CUST_EMAIL
CUST_TOTAL
CUST_TOTAL_ID
CUST_SRC_ID
CUST_EFF_FROM
CUST_EFF_TO
CUST_VALID

INMEMORY_COMPRESSION
------------------------DEFAULT
FOR QUERY HIGH
FOR QUERY HIGH
DEFAULT
DEFAULT
DEFAULT
FOR CAPACITY LOW
DEFAULT
NO MEMCOMPRESS
DEFAULT
NO MEMCOMPRESS
DEFAULT
DEFAULT
DEFAULT
DEFAULT
DEFAULT
DEFAULT
DEFAULT
DEFAULT
DEFAULT
DEFAULT
DEFAULT
DEFAULT

23 rows selected.

3. Populate the CUSTOMERS table using DBMS_INMEMORY.REPOPULATE with FORCE=TRUE.


EXEC DBMS_INMEMORY.REPOPULATE('LABUSER','CUSTOMERS', FORCE=>TRUE);
4. Check if the table got populated by querying V$IM_SEGMENTS.
SELECT SEGMENT_NAME, POPULATE_STATUS, BYTES_NOT_POPULATED
FROM V$IM_SEGMENTS WHERE SEGMENT_NAME = 'CUSTOMERS';
5. Alter the CUSTOMERS table once again and change the column participation and also the
compression methods.
ALTER TABLE CUSTOMERS INMEMORY
INMEMORY MEMCOMPRESS FOR QUERY LOW (CUST_FIRST_NAME)
INMEMORY MEMCOMPRESS FOR CAPACITY LOW (CUST_MAIN_PHONE_NUMBER)
INMEMORY NO MEMCOMPRESS (CUST_STREET_ADDRESS);
6. Check the column-level attributes for CUSTOMER. Notice that the existing attributes are
unchanged since last time they were set. The red highlight indicates the changed attributes.
2014 Oracle Corporation. All Rights Reserved.

Page 63

Oracle Database In-Memory Workshop

SOFTWARE.HARDWARE.COMPLETE

SET LINES 100;


SELECT TABLE_NAME, COLUMN_NAME, INMEMORY_COMPRESSION
FROM V$IM_COLUMN_LEVEL
WHERE TABLE_NAME = 'CUSTOMERS';
TABLE_NAME
----------------------CUSTOMERS
CUSTOMERS
CUSTOMERS
CUSTOMERS
CUSTOMERS
CUSTOMERS
CUSTOMERS
CUSTOMERS
CUSTOMERS
CUSTOMERS
CUSTOMERS
CUSTOMERS
CUSTOMERS
CUSTOMERS
CUSTOMERS
CUSTOMERS
CUSTOMERS
CUSTOMERS
CUSTOMERS
CUSTOMERS
CUSTOMERS
CUSTOMERS
CUSTOMERS

COLUMN_NAME
----------------------CUST_ID
CUST_FIRST_NAME
CUST_LAST_NAME
CUST_GENDER
CUST_YEAR_OF_BIRTH
CUST_MARITAL_STATUS
CUST_STREET_ADDRESS
CUST_POSTAL_CODE
CUST_CITY
CUST_CITY_ID
CUST_STATE_PROVINCE
CUST_STATE_PROVINCE_ID
COUNTRY_ID
CUST_MAIN_PHONE_NUMBER
CUST_INCOME_LEVEL
CUST_CREDIT_LIMIT
CUST_EMAIL
CUST_TOTAL
CUST_TOTAL_ID
CUST_SRC_ID
CUST_EFF_FROM
CUST_EFF_TO
CUST_VALID

INMEMORY_COMPRESSION
-------------------------DEFAULT
FOR QUERY LOW
FOR QUERY HIGH
DEFAULT
DEFAULT
DEFAULT
NO MEMCOMPRESS
DEFAULT
NO MEMCOMPRESS
DEFAULT
NO MEMCOMPRESS
DEFAULT
DEFAULT
FOR CAPACITY LOW
DEFAULT
DEFAULT
DEFAULT
DEFAULT
DEFAULT
DEFAULT
DEFAULT
DEFAULT
DEFAULT

23 rows selected.

7. Note: Changing the compression clause of columns with an ALTER TABLE statement
results in flushing its existing data from the IM column store. This will require repopulation,
either manually or automatically when PRIORITY clause is used.
8. As the PRIORITY clause was not used for CUSTOMERS, verify that the table has been
flushed out of the IM column store. What do you see when you run the below query?
SELECT SEGMENT_NAME, POPULATE_STATUS, BYTES_NOT_POPULATED
FROM V$IM_SEGMENTS WHERE SEGMENT_NAME = 'CUSTOMERS';

5.2.

COMPRESS TABLESPACE FOR IN-MEMORY

You can enable a tablespace for the IM column store during tablespace creation with a
CREATE TABLESPACE statement that includes the INMEMORY clause. You can also alter a
2014 Oracle Corporation. All Rights Reserved.

Page 64

Oracle Database In-Memory Workshop

SOFTWARE.HARDWARE.COMPLETE

tablespace to enable it for the IM column store with an ALTER TABLESPACE statement that
includes the INMEMORY clause.
A tablespace can be disabled for the IM column store by including a NO INMEMORY clause in a
CREATE TABLESPACE or ALTER TABLESPACE statement.
When a tablespace is enabled for the IM column store, all tables and materialized views in the
tablespace are enabled for the IM column store by default. The INMEMORY clause is the same
for tables, materialized views, and tablespaces. The DEFAULT storage clause is required
before the INMEMORY clause when enabling a tablespace for the IM column store and before
the NO INMEMORY clause when disabling a tablespace for the IM column store.
When a tablespace is enabled for the IM column store, individual tables and materialized views
in the tablespace can have different in-memory settings, and the settings for individual
database objects override the settings for the tablespace. For example, if the tablespace is set
to PRIORITY LOW for populating data in memory, but a table in the tablespace is set to
PRIORITY HIGH, then the table uses PRIORITY HIGH.
To enable or disable a tablespace for the IM column store, complete the following steps:

LAB STEPS
1. In the previous SQL*Plus session connected as LABUSER, check the current in-memory
compression attributes for the LAB_DATA tablespace (i.e. the default tablespace for
LABUSER) using the following query.
SELECT TABLESPACE_NAME, DEF_INMEMORY, DEF_INMEMORY_COMPRESSION
FROM DBA_TABLESPACES;

SQL> SELECT TABLESPACE_NAME, DEF_INMEMORY, DEF_INMEMORY_COMPRESSION


2 FROM DBA_TABLESPACES;
TABLESPACE_NAME
---------------------SYSTEM
SYSAUX
UNDOTBS1
TEMP
USERS
RTL_DATA

DEF_INME DEF_INMEMORY_COMP
-------- ----------------DISABLED
DISABLED
DISABLED
DISABLED
DISABLED
DISABLED

2014 Oracle Corporation. All Rights Reserved.

Page 65

Oracle Database In-Memory Workshop


LAB_DATA

SOFTWARE.HARDWARE.COMPLETE

DISABLED

7 rows selected.

2. Alter the LAB_DATA tablespace and modify the default in-memory compression level to
CAPACITY HIGH, and also the PRIORITY level to HIGH (to trigger automatic population).
ALTER TABLESPACE LAB_DATA DEFAULT INMEMORY MEMCOMPRESS FOR CAPACITY
HIGH PRIORITY HIGH;

SQL> ALTER TABLESPACE LAB_DATA DEFAULT INMEMORY MEMCOMPRESS FOR CAPACITY HIGH
PRIORITY HIGH;
Tablespace altered.

3. Check the in-memory compression attributes once again for LAB_DATA.


SELECT TABLESPACE_NAME, DEF_INMEMORY,
DEF_INMEMORY_COMPRESSION, DEF_INMEMORY_PRIORITY
FROM DBA_TABLESPACES WHERE TABLESPACE_NAME = 'LAB_DATA';

SQL> SELECT TABLESPACE_NAME, DEF_INMEMORY,


DEF_INMEMORY_COMPRESSION, DEF_INMEMORY_PRIORITY
FROM DBA_TABLESPACES WHERE TABLESPACE_NAME = 'LAB_DATA';
TABLESPACE_NAME
DEF_INME DEF_INMEMORY_COMP DEF_INME
------------------------ -------- ----------------- -------LAB_DATA
ENABLED FOR CAPACITY HIGH HIGH

4. Create two new tables using CTAS. On the first, do not specify the in-memory clause so it
defaults to the tablespace clause. On the second, specify the in-memory clause to override
the tablespace level compression attribute to QUERY HIGH.
CREATE TABLE SALES_INM3 AS SELECT * FROM SALES;
CREATE TABLE SALES_INM4 INMEMORY MEMCOMPRESS FOR QUERY HIGH AS
SELECT * FROM SALES;
5. Check the new tables in-memory attributes and validate that they correspond to the values
set at creation time.
COL SEGMENT_NAME FORMAT A20
SELECT SEGMENT_NAME, INMEMORY, INMEMORY_PRIORITY,
2014 Oracle Corporation. All Rights Reserved.

Page 66

Oracle Database In-Memory Workshop

SOFTWARE.HARDWARE.COMPLETE

INMEMORY_COMPRESSION FROM USER_SEGMENTS WHERE SEGMENT_NAME IN


('SALES_INM3','SALES_INM4');

SQL> SQL> COL SEGMENT_NAME FORMAT A20


SELECT SEGMENT_NAME, INMEMORY, INMEMORY_PRIORITY, INMEMORY_COMPRESSION FROM
USER_SEGMENTS WHERE SEGMENT_NAME IN ('SALES_INM3','SALES_INM4');
SQL> SQL>
SEGMENT_NAME
INMEMORY INMEMORY INMEMORY_COMPRESS
----------------- -------- -------- ----------------SALES_INM3
ENABLED HIGH
FOR CAPACITY HIGH
SALES_INM4
ENABLED NONE
FOR QUERY HIGH

6. Did you notice that the SALES_INM4 table is not configured with PRIORITY HIGH? Why?
Note: Unlike the INMEMORY_CLAUSE_DEFAULT instance parameter (which performs a
union of all attributes specified at the clause level with the object level attributes), the
tablespace level clause does not apply when the objects in-memory clause is specified,
and the object clause completely overrides the tablespace level clause.
7. Trigger a manual population of SALES_INM4 (as it will not be automatically populated due
to reasons cited above).
SELECT COUNT(*) FROM SALES_INM4;
8. Check the population progress by querying V$IM_SEGMENTS. Wait until the
BYTES_NOT_POPULATED is 0 and the STATUS is COMPLETED for both tables before
moving to the next step.
COL OWNER FORMAT A20
SELECT OWNER, SEGMENT_NAME, POPULATE_STATUS, BYTES_NOT_POPULATED
FROM V$IM_SEGMENTS WHERE SEGMENT_NAME IN ('SALES_INM3',
'SALES_INM4');

SQL> COL OWNER FORMAT A20


SELECT OWNER, SEGMENT_NAME, POPULATE_STATUS, BYTES_NOT_POPULATED
FROM V$IM_SEGMENTS WHERE SEGMENT_NAME IN ('SALES_INM3', 'SALES_INM4');
SQL> SQL>
2
OWNER
SEGMENT_NAME
POPULATE_ BYTES_NOT_POPULATED
-------------------- -------------------- --------- ------------------LABUSER
SALES_INM3
COMPLETED
0
LABUSER
SALES_INM4
COMPLETED
0
2014 Oracle Corporation. All Rights Reserved.

Page 67

Oracle Database In-Memory Workshop

SOFTWARE.HARDWARE.COMPLETE

9. Compute the compression ratios obtained on the two tables by running the following query.
SELECT V.SEGMENT_NAME,
V.INMEMORY_COMPRESSION,
V.BYTES ORIG_SIZE,
V.INMEMORY_SIZE IN_MEM_SIZE,
V.BYTES/V.INMEMORY_SIZE COMP_RATIO
FROM V$IM_SEGMENTS V
WHERE SEGMENT_NAME IN ('SALES_INM3','SALES_INM4');

SQL> SELECT V.SEGMENT_NAME,


V.INMEMORY_COMPRESSION,
V.BYTES ORIG_SIZE,
V.INMEMORY_SIZE IN_MEM_SIZE,
V.BYTES/V.INMEMORY_SIZE COMP_RATIO
FROM V$IM_SEGMENTS V
WHERE SEGMENT_NAME IN ('SALES_INM3','SALES_INM4');
SEGMENT_NAME
---------------SALES_INM3
SALES_INM4

INMEMORY_COMPRESS
----------------FOR CAPACITY HIGH
FOR QUERY HIGH

ORIG_SIZE IN_MEM_SIZE COMP_RATIO


--------- ----------- ---------12582912
3342336 3.76470588
12582912
5439488 2.31325301

10. As you observe from the above output, the CAPACITY HIGH compression on
SALES_INM4 is compressed about 3.7x times, whereas QUERY HIGH is about 2.3x.
11. Remove the in-memory clause from the tablespace using the ALTER command. Do you
think the tables in-memory attributes in the tablespace will be affected?
ALTER TABLESPACE LAB_DATA DEFAULT NO INMEMORY;
12. Verify the tablespace in-memory attributes were in-fact removed.
SELECT TABLESPACE_NAME, DEF_INMEMORY, DEF_INMEMORY_COMPRESSION
FROM DBA_TABLESPACES WHERE TABLESPACE_NAME = 'LAB_DATA';

SQL> SELECT TABLESPACE_NAME, DEF_INMEMORY, DEF_INMEMORY_COMPRESSION


2 FROM DBA_TABLESPACES WHERE TABLESPACE_NAME = 'LAB_DATA';
TABLESPACE_NAME
DEF_INME DEF_INMEMORY_COMP
---------------------- -------- ----------------LAB_DATA
DISABLED

13. Check the table level in-memory attributes. Are they still intact?
COL SEGMENT_NAME FORMAT A20
2014 Oracle Corporation. All Rights Reserved.

Page 68

Oracle Database In-Memory Workshop

SOFTWARE.HARDWARE.COMPLETE

SELECT SEGMENT_NAME, INMEMORY, INMEMORY_PRIORITY,


INMEMORY_COMPRESSION FROM USER_SEGMENTS WHERE SEGMENT_NAME IN
('SALES_INM3','SALES_INM4');
SQL> SQL> COL SEGMENT_NAME FORMAT A20
SELECT SEGMENT_NAME, INMEMORY, INMEMORY_PRIORITY, INMEMORY_COMPRESSION FROM
USER_SEGMENTS WHERE SEGMENT_NAME IN ('SALES_INM3','SALES_INM4');
SQL> SQL>
SEGMENT_NAME
INMEMORY INMEMORY INMEMORY_COMPRESS
----------------- -------- -------- ----------------SALES_INM3
ENABLED HIGH
FOR CAPACITY HIGH
SALES_INM4
ENABLED NONE
FOR QUERY HIGH

14. Finally, check V$IM_SEGMENTS to ensure that the data is still resident in the IM column
store and is still compressed.
SELECT V.SEGMENT_NAME,
V.INMEMORY_COMPRESSION,
V.BYTES ORIG_SIZE,
V.INMEMORY_SIZE IN_MEM_SIZE,
V.BYTES/V.INMEMORY_SIZE COMP_RATIO
FROM V$IM_SEGMENTS V
WHERE SEGMENT_NAME IN ('SALES_INM3','SALES_INM4');
SQL> SELECT V.SEGMENT_NAME,
V.INMEMORY_COMPRESSION,
V.BYTES ORIG_SIZE,
V.INMEMORY_SIZE IN_MEM_SIZE,
V.BYTES/V.INMEMORY_SIZE COMP_RATIO
FROM V$IM_SEGMENTS V
WHERE SEGMENT_NAME IN ('SALES_INM3','SALES_INM4');
SEGMENT_NAME
---------------SALES_INM3
SALES_INM4

5.3.

INMEMORY_COMPRESS
----------------FOR CAPACITY HIGH
FOR QUERY HIGH

ORIG_SIZE IN_MEM_SIZE COMP_RATIO


--------- ----------- ---------12582912
3342336 3.76470588
12582912
5439488 2.31325301

USING COMPRESSION ADVISOR

Prior storing a table in the IM column store, you can use Oracle Compression Advisor to report
an estimated compression ratio, and thus help you size the in-memory space. Oracle
Compression Advisor (DBMS_COMPRESSION) has been enhanced to support in-memory
compression.
2014 Oracle Corporation. All Rights Reserved.

Page 69

Oracle Database In-Memory Workshop

SOFTWARE.HARDWARE.COMPLETE

The advisor provides an estimate of the compression ratio that can be realized through the use
of MEMCOMPRESS. This estimate is based on analysis of a sample of the table data and
provides a good estimate of the actual results obtained once the table is populated into the IM
column store. As the advisor actually applies the new MEMCOMPRESS algorithms to the data, it
can only be run in an Oracle Database 12.1.0.2 (or later) environment. However, the inmemory option need not be enabled for this to work.
Using DBMS_COMPRESSION.GET_COMPRESSION_RATIO, check the compression ratio
estimates on SALES_INM3 and SALES_INM4 tables. Compare the estimates with the actual
ratios obtained in the previous lab.

LAB STEPS
1. In a SQL*Plus session, connect as the LABUSER user.
CONNECT LABUSER/labuser
2. First, get the compression ratio estimates on SALES_INM3 for the CAPCACITY HIGH
option, using the following PL/SQL block.
SET SERVEROUTPUT ON
DECLARE
l_blkcnt_cmp
PLS_INTEGER;
l_blkcnt_uncmp PLS_INTEGER;
l_row_cmp
PLS_INTEGER;
l_row_uncmp
PLS_INTEGER;
l_cmp_ratio
PLS_INTEGER;
l_comptype_str VARCHAR2(100);
BEGIN
dbms_compression.get_compression_ratio (
-- Input parameters
scratchtbsname => 'LAB_DATA',
ownname => 'LABUSER',
objname => 'SALES_INM4',
subobjname => NULL,
comptype => dbms_compression.comp_inmemory_capacity_high,
-- Output parameter
blkcnt_cmp => l_blkcnt_cmp,
blkcnt_uncmp => l_blkcnt_uncmp,
row_cmp => l_row_cmp,
row_uncmp => l_row_uncmp,
2014 Oracle Corporation. All Rights Reserved.

Page 70

Oracle Database In-Memory Workshop

SOFTWARE.HARDWARE.COMPLETE

cmp_ratio => l_cmp_ratio,


comptype_str => l_comptype_str,
subset_numrows => dbms_compression.comp_ratio_allrows);
dbms_output.put_line('Comp. ratio (Capacity High):'||l_cmp_ratio);
END;
/

Comp. ratio (Capacity High): 5


PL/SQL procedure successfully completed.

3. Next, get the compression ratio estimates on SALES_INM4 for the QUERY HIGH option,
using the following PL/SQL block.
SET SERVEROUTPUT ON
DECLARE
l_blkcnt_cmp
PLS_INTEGER;
l_blkcnt_uncmp PLS_INTEGER;
l_row_cmp
PLS_INTEGER;
l_row_uncmp
PLS_INTEGER;
l_cmp_ratio
PLS_INTEGER;
l_comptype_str VARCHAR2(100);
BEGIN
dbms_compression.get_compression_ratio (
-- Input parameters
scratchtbsname => 'LAB_DATA',
ownname => 'LABUSER',
objname => 'SALES_INM4',
subobjname => NULL,
comptype => dbms_compression.comp_inmemory_query_high,
-- Output parameter
blkcnt_cmp => l_blkcnt_cmp,
blkcnt_uncmp => l_blkcnt_uncmp,
row_cmp => l_row_cmp,
row_uncmp => l_row_uncmp,
cmp_ratio => l_cmp_ratio,
comptype_str => l_comptype_str,
subset_numrows => dbms_compression.comp_ratio_allrows);
dbms_output.put_line('Comp. ratio (Query High):'||l_cmp_ratio);
END;
/

Comp. ratio (Query High): 2

2014 Oracle Corporation. All Rights Reserved.

Page 71

Oracle Database In-Memory Workshop

SOFTWARE.HARDWARE.COMPLETE

PL/SQL procedure successfully completed.

4. As you notice, the compression ratio estimates for SALES_INM3 with CAPACITY HIGH
option is 4, whereas for SALES_INM4 with the QUERY HIGH option is 2 (or 3 in some
cases, depending on how the data is ordered). How do these numbers compare with the
actual ratios obtained earlier?

5.4.

SUMMARY

Typically, compression is considered only as a space-saving mechanism. However, data


populated into the IM column store is compressed using a new set of compression algorithms
that not only help save space but also improve query performance. The new Oracle In-Memory
compression format allows queries to execute directly against the compressed columns. This
means all scanning and filtering operations will execute on a much smaller amount of data.
Data is only decompressed when it is required for the result set.
In-memory compression is specified using the keyword MEMCOMPRESS, a sub-clause of the
INMEMORY attribute. Compression ratios can vary from 2X 20X, depending on the
compression option chosen, the data type, and the contents of the table. The compression
technique used can vary across columns, or partitions within a single table. For example, you
might optimize some columns in a table for scan speed, and others for space saving.
The in-memory columnar compression is closely related to Hybrid Columnar Compression.
Both technologies involve processing sets of column vectors. The primary difference is that the
column vectors for the IM column store are optimized for memory storage, whereas the column
vectors for Hybrid Columnar Compression are optimized for disk storage.

2014 Oracle Corporation. All Rights Reserved.

Page 72

Oracle Database In-Memory Workshop

6.

SOFTWARE.HARDWARE.COMPLETE

QUERYING THE IM COLUMN STORE

Now that you have learnt about the different ways of enabling and populating objects into the
IM column store, lets move on and look at the benefits of using it. In this lesson, you will
execute a series of queries against a large fact table DWB_RTL_SLS_RETRN_LINE_ITEM in
the RTL schema, in both the buffer cache and the column store, to demonstrate the different
ways the column store can improve query performance above and beyond the basic
performance benefits of accessing data in memory only.

6.1.

POPULATE RTL TABLES INTO IM COLUMN STORE

You will work in the RTL schema for this lesson. But first, you would need to enable all tables
in the RTL schema for INMEMORY and ensure they are populated in the IM column store prior
to running any queries.

LAB STEPS
1. In a SQL*Plus session, connect as the RTL user.
CONNECT RTL/rtl
2. Enable all tables in the RTL schema for the IM column store using ALTER TABLE
INMEMORY.
ALTER
ALTER
ALTER
ALTER
ALTER

TABLE
TABLE
TABLE
TABLE
TABLE

DWB_RTL_SLS_RETRN_LINE_ITEM INMEMORY;
DWB_RTL_TNDR_LI INMEMORY;
DWB_RTL_TRX INMEMORY;
DWR_ORG_BSNS_UNIT INMEMORY;
DWR_SKU_ITEM INMEMORY;

SQL> ALTER TABLE DWB_RTL_SLS_RETRN_LINE_ITEM INMEMORY;


Table altered.
SQL> ALTER TABLE DWB_RTL_TNDR_LI INMEMORY;
Table altered.
SQL> ALTER TABLE DWB_RTL_TRX INMEMORY;
Table altered.
SQL> ALTER TABLE DWR_ORG_BSNS_UNIT INMEMORY;
Table altered.
SQL> ALTER TABLE DWR_SKU_ITEM INMEMORY;
2014 Oracle Corporation. All Rights Reserved.

Page 73

Oracle Database In-Memory Workshop

SOFTWARE.HARDWARE.COMPLETE

Table altered.

3. Ensure that all the tables have been enabled for the column store.
SELECT TABLE_NAME, INMEMORY, INMEMORY_PRIORITY,
INMEMORY_DISTRIBUTE, INMEMORY_COMPRESSION
FROM USER_TABLES;
4. As you may observe from the last output, the partitioned tables will not have their inmemory attributes set in USER_TABLES. Query USER_TAB_PARITIONS to browse the inmemory attributes of partitioned tables.
COL TABLE_NAME FORMAT A20;
SELECT TABLE_NAME, INMEMORY, INMEMORY_PRIORITY,
INMEMORY_DISTRIBUTE, INMEMORY_COMPRESSION
FROM USER_TAB_PARTITIONS;

TABLE_NAME
-------------------DWB_RTL_SLS_RETRN_LINE_ITEM
DWB_RTL_TNDR_LI
DWB_RTL_TNDR_LI
DWB_RTL_SLS_RETRN_LINE_ITEM
DWB_RTL_TRX
DWB_RTL_TRX
DWB_RTL_TRX
DWB_RTL_TNDR_LI
DWB_RTL_SLS_RETRN_LINE_ITEM
DWB_RTL_TNDR_LI
DWB_RTL_SLS_RETRN_LINE_ITEM
DWB_RTL_TRX

INMEMORY
-------ENABLED
ENABLED
ENABLED
ENABLED
ENABLED
ENABLED
ENABLED
ENABLED
ENABLED
ENABLED
ENABLED
ENABLED

INMEMORY
-------NONE
NONE
NONE
NONE
NONE
NONE
NONE
NONE
NONE
NONE
NONE
NONE

INMEMORY_DISTRI
--------------AUTO
AUTO
AUTO
AUTO
AUTO
AUTO
AUTO
AUTO
AUTO
AUTO
AUTO
AUTO

INMEMORY_COMPRESS
----------------FOR QUERY LOW
FOR QUERY LOW
FOR QUERY LOW
FOR QUERY LOW
FOR QUERY LOW
FOR QUERY LOW
FOR QUERY LOW
FOR QUERY LOW
FOR QUERY LOW
FOR QUERY LOW
FOR QUERY LOW
FOR QUERY LOW

5. Prior to populating the RTL tables, ensure that there are no other objects loaded into the inmemory area, as the RTL tables would require about 700 MB, and the total size of the inmemory area on ORCL is only 1 GB.
6. Therefore, flush out all other tables from the in-memory area before loading the RTL tables.
Use the query below to find the objects that are currently resident in the in-memory area.
COL OWNER FORMAT A15
COL SEGMENT_NAME FORMAT A20
SELECT OWNER, SEGMENT_NAME, INMEMORY_SIZE, POPULATE_STATUS
FROM V$IM_SEGMENTS;
2014 Oracle Corporation. All Rights Reserved.

Page 74

Oracle Database In-Memory Workshop

SOFTWARE.HARDWARE.COMPLETE

SQL> COL OWNER FORMAT A15


COL SEGMENT_NAME FORMAT A20
SELECT OWNER, SEGMENT_NAME, INMEMORY_SIZE, POPULATE_STATUS
FROM V$IM_SEGMENTS;
OWNER
SEGMENT_NAME
--------------- --------LABUSER
SALES_INM3
LABUSER
COSTS
LABUSER
SALES_INM2
LABUSER
SALES_INM4
LABUSER
SALES
LABUSER
SALES_INM
LABUSER
CUSTOMERS

INMEMORY_SIZE
------------3342336
1179648
2293760
5439488
7536640
7536640
4325376

POPULATE_
--------COMPLETED
COMPLETED
COMPLETED
COMPLETED
COMPLETED
COMPLETED
COMPLETED

7. Your results may differ from the above output. Use the below SQL as an example to
disable the current objects from the IM column store. Substitute the table names in the
below script with tables that were output from the previous query.
ALTER
ALTER
ALTER
ALTER
ALTER
ALTER
ALTER

TABLE
TABLE
TABLE
TABLE
TABLE
TABLE
TABLE

LABUSER.SALES_INM NO INMEMORY;
LABUSER.SALES_INM2 NO INMEMORY;
LABUSER.SALES_INM3 NO INMEMORY;
LABUSER.SALES_INM4 NO INMEMORY;
LABUSER.COSTS NO INMEMORY;
LABUSER.SALES NO INMEMORY;
LABUSER.CUSTOMERS NO INMEMORY;

8. Check the IM column store once again, and ensure that all tables are flushed out, i.e. no
rows should be returned from the below SQL.
COL OWNER FORMAT A15
COL SEGMENT_NAME FORMAT A20
SELECT OWNER, SEGMENT_NAME, INMEMORY_SIZE, POPULATE_STATUS
FROM V$IM_SEGMENTS;

no rows selected

9. You are now ready to populate the RTL tables. Execute a simple COUNT(*) query on each
of the tables in RTL schema to trigger their population, as shown below.
SELECT COUNT(*) FROM DWB_RTL_SLS_RETRN_LINE_ITEM;
SELECT COUNT(*) FROM DWB_RTL_TNDR_LI;
SELECT COUNT(*) FROM DWB_RTL_TRX;
2014 Oracle Corporation. All Rights Reserved.

Page 75

Oracle Database In-Memory Workshop

SOFTWARE.HARDWARE.COMPLETE

SELECT COUNT(*) FROM DWR_ORG_BSNS_UNIT;


SELECT COUNT(*) FROM DWR_SKU_ITEM;
10. Check if all RTL tables and partitions are completely populated by looking at the
POPULATE_STATUS column of V$IM_SEGMENTS. Wait until all tables are populated before
proceeding to the next lab.
COL OWNER FORMAT A15
COL SEGMENT_NAME FORMAT A20
SELECT OWNER, SEGMENT_NAME, INMEMORY_SIZE, POPULATE_STATUS
FROM V$IM_SEGMENTS;
OWNER
SEGMENT_NAME
--------------- -------------------RTL
DWB_RTL_SLS_RETRN_LINE_ITEM
RTL
DWR_SKU_ITEM
RTL
DWB_RTL_TNDR_LINE_ITEM
RTL
DWB_RTL_TRX
RTL
DWB_RTL_SLS_RETRN_LINE_ITEM
RTL
DWR_ORG_BSNS_UNIT
RTL
DWB_RTL_TNDR_LI
RTL
DWB_RTL_TRX
RTL
DWB_RTL_SLS_RETRN_LINE_ITEM
RTL
DWB_RTL_TNDR_LI
RTL
DWB_RTL_TRX

INMEMORY_SIZE
------------178520064
5373952
23265280
23265280
178520064
1179648
23265280
23265280
179568640
23265280
23265280

POPULATE_
--------COMPLETED
COMPLETED
COMPLETED
COMPLETED
COMPLETED
COMPLETED
COMPLETED
COMPLETED
COMPLETED
COMPLETED
COMPLETED

11 rows selected.

6.2.

RUNNING A SIMPLE AGGREGATION QUERY

Lets begin with a simple aggregation query, What was the most expensive item sold to date?
Since we have no alternative access paths (indexes or views) built in the schema, the
execution plan for this query will use a full table scan of DWB_RTL_SLS_RETRN_LINE_ITEM.
Run the query with and without using the IM column store. To switch between the in-memory
column store and the buffer cache, you will enable/disable the INMEMORY_QUERY parameter
for the session.

LAB STEPS
1. In order to do the comparison between the IM column store and the buffer cache, you need
to enable the timer in the SQL*Plus session to capture wall-clock execution times. You
2014 Oracle Corporation. All Rights Reserved.

Page 76

Oracle Database In-Memory Workshop

SOFTWARE.HARDWARE.COMPLETE

can do this by using the SET TIMING ON clause.


2. In the previous SQL*Plus session connected as RTL, execute the following query against
the IM column store.
SET TIMING ON;
SELECT MAX(EXTENDED_AMT) FROM DWB_RTL_SLS_RETRN_LINE_ITEM;
SQL> SET TIMING ON;
SQL> SELECT MAX(EXTENDED_AMT) FROM DWB_RTL_SLS_RETRN_LINE_ITEM;
MAX(EXTENDED_AMT)
----------------10.55
Elapsed: 00:00:00.86

3. Execute the same query against the buffer cache by first disabling the IM column store
using the INMEMORY_QUERY parameter, as the optimizer will always favor accessing the
data via the column store when the execution plan is a full table scan, which will be true in
this case.
4. To execute the query against the buffer cache type the following SQL.
ALTER SESSION SET INMEMORY_QUERY=DISABLE;
SELECT MAX(EXTENDED_AMT) FROM DWB_RTL_SLS_RETRN_LINE_ITEM;
SQL> ALTER SESSION SET INMEMORY_QUERY=DISABLE;
Session altered.
Elapsed: 00:00:00.00
SQL> SELECT MAX(EXTENDED_AMT)
FROM DWB_RTL_SLS_RETRN_LINE_ITEM;
MAX(EXTENDED_AMT)
----------------10.55
Elapsed: 00:00:02.66

5. As you can see the query executed extremely quickly in both cases because this is purely
an in-memory scan. However, the performance of the query against the IM column was
2014 Oracle Corporation. All Rights Reserved.

Page 77

Oracle Database In-Memory Workshop

SOFTWARE.HARDWARE.COMPLETE

faster than on the traditional buffer cache - Why?


6. The IM column store only has to scan a single column EXTENDED_AMT - while the row
store has to scan all of the columns in each of the rows until it reaches the EXTENDED_AMT
column. We are also benefiting from the excellent compression ratio and the fact that the
columnar format requires no additional manipulation to take advantage of SIMD vector
processing. Yes, even in the VM environment, SIMD vector processing should be in effect if
you are on Intel CPU architecture.
7. Before proceeding to the next lab, dont forget to re-enable INMEMORY_QUERY using the
following SQL.
ALTER SESSION SET INMEMORY_QUERY=ENABLE;

SQL> ALTER SESSION SET INMEMORY_QUERY=ENABLE;


Session altered.

6.3.

IM COLUMN STORE EXECUTION PLANS AND STATISTICS

How can you tell if your query is using a table from the IM column store? Typically you would
start by examining the querys execution plan to determine how a SQL statement is executed
the plan would contain information as to whether it is using the IM column store or not. But to
get an accurate answer, you should check the querys run time statistics as well.
In this section, you will examine the execution plans and the query statistics.

6.3.1.

IM COLUMN STORE EXECUTION PLANS

Execute the following steps to capture query execution plans for in-memory and buffer cache.
It helps to have two simultaneous SQL*Plus sessions open so you could compare the two
plans side-by-side.

LAB STEPS
1. Open two SQL*Plus sessions connected as the user RTL. In Session 1, you will run the
queries against the IM column store. In Session 2, you will run queries against the buffer
2014 Oracle Corporation. All Rights Reserved.

Page 78

Oracle Database In-Memory Workshop

SOFTWARE.HARDWARE.COMPLETE

cache.
Session 1

Session 2

sqlplus RTL/rtl

sqlplus RTL/rtl

2. In Session 1, execute the following SQLs and capture the query execution plan when the
query uses the IM column store.
Session 1
SET
SET
SET
SET

PAGES 0
LINES 200
TIMING ON
ECHO ON

-- IM Column Store query


SELECT MAX(EXTENDED_AMT) FROM DWB_RTL_SLS_RETRN_LINE_ITEM;
-- Display the query plan
SELECT * FROM TABLE(DBMS_XPLAN.DISPLAY_CURSOR());
SET ECHO OFF;
3. In Session 2, execute the following SQLs and capture the query execution plan when the
query is forced to use the buffer cache.
Session 2
SET
SET
SET
SET

PAGES 0
LINES 200
TIMING ON
ECHO ON

-- Force query to use Buffer Cache query


ALTER SESSION SET INMEMORY_QUERY=DISABLE;
-- Execute the query
SELECT MAX(EXTENDED_AMT) FROM DWB_RTL_SLS_RETRN_LINE_ITEM;
-- Display the query plan
SELECT * FROM TABLE(DBMS_XPLAN.DISPLAY_CURSOR());
2014 Oracle Corporation. All Rights Reserved.

Page 79

Oracle Database In-Memory Workshop

SOFTWARE.HARDWARE.COMPLETE

ALTER SESSION SET INMEMORY_QUERY=ENABLE;


SET ECHO OFF;
4. The output of two sessions is shown below. Notice that the execution plan for the first query
has a new set of keywords IN MEMORY, while the buffer cache query does not. These
keywords indicate that the DWB_RTL_SLS_RETRN_LINE_ITEM table has been marked for
IN MEMORY and the database may use the column store in this query.
Session 1
-- IM Column Store query
SELECT MAX(EXTENDED_AMT) FROM DWB_RTL_SLS_RETRN_LINE_ITEM;
-- Display the query plan
SELECT * FROM TABLE(DBMS_XPLAN.DISPLAY_CURSOR());
SET ECHO OFF;
SQL> SQL> SQL> SQL> SQL> SQL> SQL>

10.55

Elapsed: 00:00:00.06
SQL_ID
8q5xwrfukc71s, child number 0
------------------------------------SELECT MAX(EXTENDED_AMT) FROM DWB_RTL_SLS_RETRN_LINE_ITEM
Plan hash value: 501864787
----------------------------------------------------------------------------------------------------------------------------------| Id | Operation |Name | Rows | Bytes | Cost (%CPU) |Time |Pstart |Pstop | TQ
|IN-OUT| PQ Distrib |
----------------------------------------------------------------------------------------------------------------------------------|
0 | SELECT STATEMENT
|
|
|
|
17500 (100)|
|
|
|
|
|
|
|
1 | SORT AGGREGATE
|
|
1 |
4 |
|
|
|
|
|
|
|
|
2 |
PX COORDINATOR
|
|
|
|
|
|
|
|
|
|
|
|
3 |
PX SEND QC (RANDOM)
| :TQ10000
|
1 |
4 |
|
|
|
| Q1,00 | P->S | QC (RAND) |
|
4 |
SORT AGGREGATE
|
|
1 |
4 |
|
|
|
| Q1,00 | PCWP |
|
|
5 |
PX BLOCK ITERATOR
|
|
27M|
105M| 17500(1)| 00:00:01 |
1 |1048575| Q1,00 | PCWC |
|
|* 6 |
TABLE ACCESS INMEMORY FULL| DWB_RTL_SLS_RETRN_LINE_ITEM |
27M|
105M| 17500(1)| 00:00:01 |
1 |1048575| Q1,00 | PCWP |
|
----------------------------------------------------------------------------------------------------------------------------------------------------------Note
2014 Oracle Corporation. All Rights Reserved.

Page 80

Oracle Database In-Memory Workshop

SOFTWARE.HARDWARE.COMPLETE

----- statistics feedback used for this statement

Session 2
8q5xwrfukc71s, child number 1
------------------------------------SELECT MAX(EXTENDED_AMT) FROM DWB_RTL_SLS_RETRN_LINE_ITEM
Plan hash value: 501864787
-------------------------------------------------------------------------------------------------------------------------------------------------| Id | Operation
| Name
| Rows | Bytes | Cost
(%CPU)| Time
| Pstart| Pstop |
TQ |IN-OUT| PQ Distrib |
-------------------------------------------------------------------------------------------------------------------------------------------------|
0 | SELECT STATEMENT
|
|
|
|
17500 (100)|
|
|
|
|
|
|
|
1 | SORT AGGREGATE
|
|
1 |
4 |
|
|
|
|
|
|
|
|
2 |
PX COORDINATOR
|
|
|
|
|
|
|
|
|
|
|
|
3 |
PX SEND QC (RANDOM) | :TQ10000
|
1 |
4 |
|
|
|
|
Q1,00 | P->S | QC (RAND) |
|
4 |
SORT AGGREGATE
|
|
1 |
4 |
|
|
|
|
Q1,00 | PCWP |
|
|
5 |
PX BLOCK ITERATOR |
|
27M|
105M|
17500
(1)| 00:00:01 |
1 |1048575|
Q1,00 | PCWC |
|
|* 6 |
TABLE ACCESS FULL| DWB_RTL_SLS_RETRN_LINE_ITEM |
27M|
105M| 17500
(1)| 00:00:01 |
1 |1048575|
Q1,00 | PCWP |
|
--------------------------------------------------------------------------------------------------------------------------------------------------

5. What does may use mean? Well, there are a small number of cases where the database
will not use the IM column store even though the object has been marked IN MEMORY.
Whether the query uses the column store or not is determined at runtime. This is similar to
how the keyword STORAGE is used on Oracle Exadata environments.

6.3.2.

IM COLUMN STORE STATISTICS

In order to confirm that the IM column store was used, we need to examine the session level
statistics. You can monitor the session level statistics by querying the performance views
V$MYSTAT and V$STATNAME. All of the statistics related to IM Column Store begin with IM.

LAB STEPS
1. Start a new SQL*Plus session and login as RTL, or just re-connect as RTL in the current
session. Do not use a previously logged in RTL session (you will see why shortly).
2014 Oracle Corporation. All Rights Reserved.

Page 81

Oracle Database In-Memory Workshop

SOFTWARE.HARDWARE.COMPLETE

CONNECT RTL/rtl
2. Execute the below SQL to get a full listing of IM column store statistics.
SELECT DISPLAY_NAME
FROM
V$STATNAME
WHERE DISPLAY_NAME LIKE 'IM %';

SQL> SELECT DISPLAY_NAME


FROM
V$STATNAME
WHERE DISPLAY_NAME LIKE 'IM%';
DISPLAY_NAME
-------------------------------IM populate blocks invalid
IM populate transactions check
IM populate undo segheader rollback
IM populate undo records applied
IM populate transactions active
IM repopulate blocks invalid
IM repopulate transactions check
IM repopulate undo segheader rollback
IM repopulate undo records applied
.
.
.

3. Thats a lot of statistics! Dont worry you dont need to know them all. You just need to
understand if your query really executed in the IM column store. You only need to examine
only a few of them right now, mainly:
IM scan bytes uncompressed: Uncompressed size in bytes of all CUs in scan prior to
any optimizations
IM scan bytes in-memory: Compressed size in bytes of all CUs in scan prior to any
optimizations
IM scan CUs columns accessed: Count of CUs accessed by the scan
IM scan CUs columns theoretical max: Count of columns that would be accessed if
each scan looked at all columns in all IMCUs
4. By comparing the above statistics when you run the query, you will be able to see how
much of the DWB_RTL_SLS_RETRN_LINE_ITEM table was actually accessed by the query.
2014 Oracle Corporation. All Rights Reserved.

Page 82

Oracle Database In-Memory Workshop

SOFTWARE.HARDWARE.COMPLETE

5. To query your particular sessions statistics, run the following SQL.


SELECT DISPLAY_NAME, VALUE
FROM V$MYSTAT m, V$STATNAME n
WHERE m.STATISTIC# = n.STATISTIC#
AND n.DISPLAY_NAME IN (
'IM scan bytes in-memory',
'IM scan bytes uncompressed',
'IM scan CUs columns accessed',
'IM scan CUs columns theoretical max');
DISPLAY_NAME
VALUE
------------------------------------------------------ -------IM scan bytes in-memory
0
IM scan bytes uncompressed
0
IM scan CUs columns accessed
0
IM scan CUs columns theoretical max
0

6. Observe that the value of the above statistics are zero, unless you have reused a previous
SQL*Plus session for RTL, in which case it is quite possible that you may have run queries
accessing the IM column store, which will bump-up the IM statistics.
7. Now, lets re-execute the earlier aggregation query.
SELECT MAX(EXTENDED_AMT) FROM DWB_RTL_SLS_RETRN_LINE_ITEM;
8. Check the statistics again.
SELECT DISPLAY_NAME, VALUE
FROM V$MYSTAT m, V$STATNAME n
WHERE m.STATISTIC# = n.STATISTIC#
AND n.DISPLAY_NAME IN (
'IM scan bytes in-memory',
'IM scan bytes uncompressed',
'IM scan CUs columns accessed',
'IM scan CUs columns theoretical max');

DISPLAY_NAME
VALUE
------------------------------------------------------ ---------IM scan bytes in-memory
483912593
IM scan bytes uncompressed
3044446804
IM scan CUs columns accessed
43
IM scan CUs columns theoretical max
688

9. The session statistics show that the query scanned DWB_RTL_SLS_RETRN_LINE_ITEM


2014 Oracle Corporation. All Rights Reserved.

Page 83

Oracle Database In-Memory Workshop

SOFTWARE.HARDWARE.COMPLETE

tables compression units from the IM column store. Notice the following statistics get
populated: IM scan bytes uncompressed, IM scan bytes in-memory, IM scan CUs
columns accessed, and IM scan CUs columns theoretical max. As the query did not
have a filter, it was expected to scan all IMCUs and all CUs within the IMCU for the
segment that is if there wouldnt be column projection, but as you can see, only one column
CU per IMCU is touched because of column projection. This is evident in the IM scan CU
columns theoretical max value of 688 (43 IMCUs x 16 columns) from which IM scan CUs
columns accessed are only 43 which happen to be the total IMCUs for 1 column
(EXTENDED_AMT).
10. Now try executing the same steps but this time, run the query in buffer cache.
ALTER SESSION SET INMEMORY_QUERY=DISABLE;
SELECT MAX(EXTENDED_AMT) FROM DWB_RTL_SLS_RETRN_LINE_ITEM;
ALTER SESSION SET INMEMORY_QUERY=ENABLE;
11. Check the statistics again.
SELECT DISPLAY_NAME, VALUE
FROM V$MYSTAT m, V$STATNAME n
WHERE m.STATISTIC# = n.STATISTIC#
AND n.DISPLAY_NAME IN (
'IM scan bytes in-memory',
'IM scan bytes uncompressed',
'IM scan CUs columns accessed',
'IM scan CUs columns theoretical max');
12. This time you will notice that the IM statistics do not get incremented because the query bypassed the IM column store and executed in the buffer cache instead.

6.4.

QUERY USING A FILTER

Traditionally, a full table scan is not the most efficient execution plan when you are looking for
a subset of rows in a table. Tables stored in the IM column store break this stereotype as we
demonstrate by adding a filter to the query on the fact table
DWB_RTL_SLS_RETRN_LINE_ITEM on ACTN_CD.

2014 Oracle Corporation. All Rights Reserved.

Page 84

Oracle Database In-Memory Workshop

SOFTWARE.HARDWARE.COMPLETE

LAB STEPS
1. In the previous SQL*Plus session connected as RTL, execute the following query against
the IM column store:
SET TIMING ON
SELECT SUM(EXTENDED_AMT)
FROM RTL.DWB_RTL_SLS_RETRN_LINE_ITEM
WHERE ACTN_CD = 'Return';
SET TIMING OFF
2. Now, execute the same query against the buffer cache.
ALTER SESSION SET INMEMORY_QUERY=DISABLE;
SET TIMING ON
SELECT SUM(EXTENDED_AMT)
FROM RTL.DWB_RTL_SLS_RETRN_LINE_ITEM
WHERE ACTN_CD = 'Return';
SET TIMING OFF
ALTER SESSION SET INMEMORY_QUERY=ENABLE;
3. Again the IM column store shows an impressive improvement over the traditional buffer
cache, but how?
4. Remember the IM column store has access to a storage index on each of the columns,
which enables it to perform min/max pruning. The where clause predicate is compared to
the min/max range for each in-memory segment of the corresponding column, and if the
value doesnt fall in the specified range then the segment is skipped completely.
5. You can tell that min/max pruning occurred by looking at the following session statistics.
IM scan segments minmax eligible: Count of CUs eligible for minmax pruning.
IM scan CUs pruned: Count of CUs with no rows passing minmax
6. To capture the session statistics for the previous query, reconnect as the user RTL in the
2014 Oracle Corporation. All Rights Reserved.

Page 85

Oracle Database In-Memory Workshop

SOFTWARE.HARDWARE.COMPLETE

current session. The reconnection is a cheap and dirty way to reinitialize the session level
statistics.
CONNECT RTL/rtl
7. Execute the query in the IM column store again.
SET TIMING ON
SELECT SUM(EXTENDED_AMT)
FROM RTL.DWB_RTL_SLS_RETRN_LINE_ITEM
WHERE ACTN_CD = 'Return';
SET TIMING OFF
8. Check the session level statistics.
SELECT DISPLAY_NAME, VALUE
FROM V$MYSTAT m, V$STATNAME n
WHERE m.STATISTIC# = n.STATISTIC#
AND n.DISPLAY_NAME IN (
'IM scan segments minmax eligible',
'IM scan CUs pruned',
'IM scan CUs columns accessed');

DISPLAY_NAME
VALUE
---------------------------------------------------- ---------IM scan CUs columns accessed
6
IM scan CUs pruned
40
IM scan segments minmax eligible
43

9. From these results you can see just how effective the min/max pruning can potentially be.
Below are the key observations:
The total IMCUs that were eligible for minmax pruning (IM scan segments minmax
eligible) are 43. This is same as the total number of IMCUs that the table occupies in
the IM column store.
The statistics show that a large number of column CUs are pruned (evident from IM
scan CUs pruned = 40) because all columns failed the min/max comparison in these
IMCUs. This means the database never scans those IMCUs.
Only a small number of IMCUs were considered for further processing (3, i.e. 43 40)
2014 Oracle Corporation. All Rights Reserved.

Page 86

Oracle Database In-Memory Workshop

SOFTWARE.HARDWARE.COMPLETE

because their value fell in the min/max range.


Why do you think that the total column CUs that were accessed are 6 (as seen from IM
scan CUs columns accessed)? This is because in the 3 IMCUs that were considered
for the scan, the database had to access 2 column CUs per IMCU (one for each
column; EXTENDED_AMT and ACTN_CD), which makes the total of 6 column CUs to
scan.

6.5.

QUERY USING MULTIPLE FILTERS

You have just seen that filter clauses can take advantage of min/max pruning and speed up
single-row lookups. However, its not often that an analytical query has only one equality in the
WHERE clause predicate. What happens when there are multiple single column predicates on a
table? Traditionally you would create a multi-column index. Can column store indexes compete
with the traditional approach?
Lets change our query and add an additional filter and see how that will help the query to run
faster.

LAB STEPS
1. In the previous SQL*Plus session reconnect as the user RTL to initialize session statistics.
CONNECT RTL/rtl
2. Now execute the following query against the IM column store, with a different filter than the
one used in the previous lab (and also the number of SELECT column projections):
SELECT SUM(EXTENDED_AMT)
FROM RTL.DWB_RTL_SLS_RETRN_LINE_ITEM
WHERE ACTN_CD = 'Return'
AND QTY = 2;
3. This time, lets capture three additional statistics:
IM scan rows. Count of rows that would be scanned from IMCUs before applying
optimizations.
IM scan rows valid. Actual count of rows scanned from an IMCU after applying
2014 Oracle Corporation. All Rights Reserved.

Page 87

Oracle Database In-Memory Workshop

SOFTWARE.HARDWARE.COMPLETE

optimizations. Note that this is not the same as the query result i.e. the rows returned
after applying the WHERE clause, as this statistics gives the number of rows in the
IMCUs that will be actually scanned.
IM scan rows optimized. The rows skipped i.e. IM scan rows - IM scan rows valid.
4. Capture the above statistics, along with IM scan segments minmax eligible, IM scan
CUs columns accessed, and IM scan CUs pruned (discussed earlier). As we had
reconnected as the RTL user, all stats that are displayed are the values consumed by the
previous SQL alone.
SELECT DISPLAY_NAME, VALUE
FROM V$MYSTAT m, V$STATNAME n
WHERE m.STATISTIC# = n.STATISTIC#
AND n.DISPLAY_NAME IN (
'IM scan segments minmax eligible',
'IM scan CUs pruned',
'IM scan CUs columns accessed',
'IM scan rows',
'IM scan rows valid',
'IM scan rows optimized');

DISPLAY_NAME
VALUE
------------------------------------------------------ -------IM scan CUs columns accessed
9
IM scan rows
27541321
IM scan rows valid
1727284
IM scan rows optimized
25814037
IM scan CUs pruned
40
IM scan segments minmax eligible
43

5. A few observations from above:


According to the statistic IM scan segments minmax eligible, the segment has a total
of 43 IMCUs.
3 of the 43 IMCUs will be touched by this query because of min-max/dictionary pruning
(i.e. IM scan segments minmax eligible IM scan CUs pruned).
A total of 9 column CUs are accessed in the 3 IMCUs (3 for each column per IMCU in
the query EXTENDED_AMT, ACTN_CD, QTY)
2014 Oracle Corporation. All Rights Reserved.

Page 88

Oracle Database In-Memory Workshop

SOFTWARE.HARDWARE.COMPLETE

IM scan rows: These are the rows that would be scanned if there were no In-Memory
optimizations. In our case, the table DWB_RTL_SLS_RETRN_LINE_ITEM has about
27.5 Million rows and this statistic reflects that count.
IM scan rows valid: After applying all optimizations and pruning, these are the number
rows that are candidates to be scanned within all IMCUs. 1.7 Million rows out of the
27.5 Million rows are valid rows upon which the WHERE clause predicates will be
applied, perhaps using SIMD vector processing if the operation deserves so.
IM scan rows optimized. Approx. 25.8 Million rows have been optimized in this
operation (~ 27.5 1.7)
6. Reconnect as the use RTL once again to reinitialize the session statistics.
CONNECT RTL/rtl
7. Execute the below query. Notice the additional WHERE clause added on
BEGIN_DT_TIMESTAMP column. The query will return NULL but the example serves the
purpose.
SELECT SUM(EXTENDED_AMT)
FROM RTL.DWB_RTL_SLS_RETRN_LINE_ITEM
WHERE ACTN_CD = 'Return'
AND QTY = 2
AND BEGIN_DT_TIMESTAMP =
TO_TIMESTAMP('01/01/2014 08:00','MM/DD/YYYY HH24:MI');
8. Observe the session statistics once again and compare.
SELECT DISPLAY_NAME, VALUE
FROM V$MYSTAT m, V$STATNAME n
WHERE m.STATISTIC# = n.STATISTIC#
AND n.DISPLAY_NAME IN (
'IM scan segments minmax eligible',
'IM scan CUs pruned',
'IM scan CUs columns accessed',
'IM scan rows',
'IM scan rows valid',
'IM scan rows optimized');
DISPLAY_NAME
2014 Oracle Corporation. All Rights Reserved.

VALUE
Page 89

Oracle Database In-Memory Workshop


----------------------------------------------------IM scan CUs columns accessed
IM scan rows
IM scan rows valid
IM scan rows optimized
IM scan CUs pruned
IM scan segments minmax eligible

SOFTWARE.HARDWARE.COMPLETE

-------4
27541321
1191957
26349364
41
43

9. Notice that with the addition of the third predicate, there was an additional IMCU skipped
due to minmax pruning (41 IMCUs pruned now when compared with 40 IMCUs earlier).
10. Only 4 column CUs were finally scanned from 2 IMCUs (i.e. 43 minmax eligible 41
pruned).

6.6.

QUERY USING NON-EQUALITY PREDICATE

What if the where clause predicate isnt an equality predicate? Can you still benefit from
min/max pruning? Lets change the query to What was the most expensive item purchased in
quantity greater than 2 by a customer?

LAB STEPS
1. In the previous SQL*Plus session reconnect as the user RTL to initialize session statistics.
CONNECT RTL/rtl
2. Now execute the following query against the IM column store that uses a non-equality
predicate:
SET TIMING ON;
SELECT SUM(EXTENDED_AMT) FROM DWB_RTL_SLS_RETRN_LINE_ITEM
WHERE BEGIN_DT_TIMESTAMP BETWEEN
TO_TIMESTAMP('01/01/2014 08:00','MM/DD/YYYY HH24:MI')
AND TO_TIMESTAMP('01/01/2014 08:10','MM/DD/YYYY HH24:MI');
SET TIMING OFF;
3. For the above SQL, capture the session related In-Memory statistics.
SELECT DISPLAY_NAME, VALUE
FROM V$MYSTAT m, V$STATNAME n
WHERE m.STATISTIC# = n.STATISTIC#
AND n.DISPLAY_NAME IN (
2014 Oracle Corporation. All Rights Reserved.

Page 90

Oracle Database In-Memory Workshop

'IM
'IM
'IM
'IM
'IM
'IM

scan
scan
scan
scan
scan
scan

SOFTWARE.HARDWARE.COMPLETE

segments minmax eligible',


CUs pruned',
CUs columns accessed',
rows',
rows valid',
rows optimized');

DISPLAY_NAME
----------------------------------------------------IM scan CUs columns accessed
IM scan rows
IM scan rows valid
IM scan rows optimized
IM scan CUs pruned
IM scan segments minmax eligible

VALUE
-------12
27541321
3778859
23762462
37
43

6 rows selected.

4. Note that the optimizations still occur when an inequality clause (such as the BETWEEN
clause) is used. This is evident from 37 IMCUs that are pruned, leading to a total 12 column
CUs being accessed, i.e. (43-37) * 2 column predicates (the BETWEEN clause translates
to two predicates on the column, one with with >= and the second with <=).
5. Execute the same query against the buffer cache and compare the timings to the previous
IM column store run.
ALTER SESSION SET INMEMORY_QUERY=DISABLE;
SET TIMING ON;
SELECT SUM(EXTENDED_AMT) FROM DWB_RTL_SLS_RETRN_LINE_ITEM
WHERE BEGIN_DT_TIMESTAMP BETWEEN
TO_TIMESTAMP('01/01/2014 08:00','MM/DD/YYYY HH24:MI')
AND TO_TIMESTAMP('01/01/2014 08:10','MM/DD/YYYY HH24:MI');
SET TIMING OFF;
ALTER SESSION SET INMEMORY_QUERY=ENABLE;
6. The IM column store still out-performs the buffer cache because the query scans only a few
IMCUs after applying the IM column store optimizations such as min-max and dictionary
pruning.

6.7.

SUMMARY

2014 Oracle Corporation. All Rights Reserved.

Page 91

Oracle Database In-Memory Workshop

SOFTWARE.HARDWARE.COMPLETE

In this lesson you had an opportunity to try out Oracles in-memory performance claims with
queries that run against the DWB_RTL_SLS_RETRN_LINE_ITEM table containing 27 Million
rows and residing in the IM column store. From a very simple single row look-up, to more
complex queries, the IM column store was able to out perform the buffer cache queries.
Remember both of sets of queries are executing completely within memory, so thats quite an
impressive improvement.
These significant performance improvements are possible because of Oracles unique inmemory columnar format that allows us to only scan the columns we need and to take full
advantage of SIMD vector processing. We also got a little help from our new in-memory
storage indexes, which allow us to prune out unnecessary data. Remember with the IM column
store, every column has a storage index that is automatically maintained for you.
In this lesson you also got an opportunity to get your first experience with monitoring an inmemory workload. Those of you familiar with Oracles Exadata Engineered Systems will see a
lot of similarity here. There is a new keyword (IN MEMORY) in the execution plan to indicate
which operations within that plan are eligible to be executed on the IM column store. But to
confirm that these operations actually took place in the IM column store you need to examine
the new set of in-memory (IM_*) session statistics.

2014 Oracle Corporation. All Rights Reserved.

Page 92

Oracle Database In-Memory Workshop

7.

SOFTWARE.HARDWARE.COMPLETE

IN-MEMORY JOINS AND AGGREGATION

Up until now we have been focused on queries that scan only one table,
DWB_RTL_SLS_RETRN_LINE_ITEM. Lets broaden the scope of our investigation to include
joins and aggregation. This lesson executes a series of queries that begin with a single join
between the fact table, DWB_RTL_SLS_RETRN_LINE_ITEM, and a dimension table but works
gradually up to multi-dimension joins, group by and aggregations. The queries will be executed
in both the buffer cache and the column store, to demonstrate the different ways the column
store can improve query performance above and beyond the basic performance benefits of
scanning data in a columnar format.

7.1.

A SIMPLE JOIN AND AGGREGATION QUERY

We will begin with the simplest join query, a join between the fact table
DWB_RTL_SLS_RETRN_LINE_ITEM and the dimension table DWR_SKU_ITEM, with filter
predicates on both. This query sums up the total sales of a particular beverage Diet Pepsi,
across all years of sales:
Note: Dont run the below query, yet!
SELECT SUM(li.EXTENDED_AMT)
FROM DWB_RTL_SLS_RETRN_LINE_ITEM li,
DWR_SKU_ITEM p
WHERE li.SKU_ITEM_KEY = p.SKU_ITEM_KEY
AND li.ACTN_CD = 'Sale'
AND p.SKU_ITEM_DESC LIKE 'Diet Pepsi%';

The query will use Bloom Filters for joining the two tables. In case you are new to bloom
filters, they were originally introduced in Oracle Database 10g to enhance hash join
performance and are not specific to Oracle Database 12c or the IM column store. However,
they are very efficiently applied to columnar data via SIMD vector processing.
When two tables are joined via a hash join, the first table (typically the smaller table) is
scanned and the rows that satisfy the where clause predicates (for that table) are used to
create a hash table. During the hash table creation a bit vector or bloom filter is also created
based on the join column. The bit vector is then sent as an additional predicate to the second
table scan. After the where clause predicates have been applied to the second table scan, the
resulting rows will have their join column hashed and it will be compared to values in the bit
2014 Oracle Corporation. All Rights Reserved.

Page 93

Oracle Database In-Memory Workshop

SOFTWARE.HARDWARE.COMPLETE

vector. If a match is found in the bit vector that row will be sent to the hash join. If no match is
found then the row will be disregarded. On Exadata the bloom filter or bit vector is passed as
an additional predicate so it will be offloaded to the storage cells thereby making bloom filtering
very efficient.

LAB STEPS
1. Using SQL*Plus connect as the RTL user.
CONNECT RTL/rtl
2. Execute the lab query against the IM column store. As before, you will enable the
SQL*Plus timer function using SET TIMING ON.
SET TIMING ON
-- IM Column Store query
SELECT SUM(li.EXTENDED_AMT)
FROM DWB_RTL_SLS_RETRN_LINE_ITEM li, DWR_SKU_ITEM p
WHERE li.SKU_ITEM_KEY = p.SKU_ITEM_KEY
AND li.ACTN_CD = 'Sale'
AND p.SKU_ITEM_DESC LIKE 'Diet Pepsi%';
SET TIMING OFF
3. Execute the lab query against the buffer cache and observe the runtime. Is it faster than the
IM column store query?
ALTER SESSION SET INMEMORY_QUERY = DISABLE;
SET TIMING ON
-- Buffer cache query
SELECT SUM(li.EXTENDED_AMT)
FROM DWB_RTL_SLS_RETRN_LINE_ITEM li, DWR_SKU_ITEM p
WHERE li.SKU_ITEM_KEY = p.SKU_ITEM_KEY
AND li.ACTN_CD = 'Sale'
AND p.SKU_ITEM_DESC LIKE 'Diet Pepsi%';
SET TIMING OFF
ALTER SESSION SET INMEMORY_QUERY = ENABLE;
4. The IM column store has no problem executing a query with a join because it is able to take
advantage of bloom filters. The bloom filter transforms a join to a filter that can be applied
2014 Oracle Corporation. All Rights Reserved.

Page 94

Oracle Database In-Memory Workshop

SOFTWARE.HARDWARE.COMPLETE

as part of the scan of the fact table.


5. It is easy to identify bloom filters in the execution plan. They will appear in two places, at
creation time and again when it is applied. Below is the SQL to capture the plan for the lab
query. Notice the bloom filter in the plan (highlighted).
SET
SET
SET
SET

PAGES 0
LINES 200
TIMING ON
ECHO ON

-- IM Column Store query


SELECT SUM(li.EXTENDED_AMT)
FROM DWB_RTL_SLS_RETRN_LINE_ITEM li, DWR_SKU_ITEM p
WHERE li.SKU_ITEM_KEY = p.SKU_ITEM_KEY
AND li.ACTN_CD = 'Sale'
AND p.SKU_ITEM_DESC LIKE 'Diet Pepsi%';
-- Display the query plan
SELECT * FROM TABLE(DBMS_XPLAN.DISPLAY_CURSOR());
SET ECHO OFF
6. You can also see the join condition that was used to build the bloom filter by looking at the
predicate information under the plan. Look for SYS_OP_BLOOM_FILTER in the filter
predicates.
SQL_ID
974n3f0fz50gy, child number 0
------------------------------------SELECT SUM(li.EXTENDED_AMT) FROM DWB_RTL_SLS_RETRN_LINE_ITEM li,
DWR_SKU_ITEM p WHERE li.SKU_ITEM_KEY = p.SKU_ITEM_KEY AND li.ACTN_CD =
'Sale' AND p.SKU_ITEM_DESC LIKE 'Diet Pepsi%'
Plan hash value: 117935668
----------------------------------------------------------------------------------------------------------------------------| Id | Operation
| Name
| Rows | Bytes |
Cost (%CPU)| Time
| Pstart| Pstop |
----------------------------------------------------------------------------------------------------------------------------|
0 | SELECT STATEMENT
|
|
|
| 32118 (100)|
|
|
|
|
1 | SORT AGGREGATE
|
|
1 |
42 |
|
|
|
|
|* 2 |
HASH JOIN
|
|
615 |
25830 | 32118
(2)| 00:00:02 |
|
|
|
3 |
JOIN FILTER CREATE
| :BF0000
|
1 |
26 |
106
(1)| 00:00:01 |
|
|
2014 Oracle Corporation. All Rights Reserved.

Page 95

Oracle Database In-Memory Workshop


|*
|
|

SOFTWARE.HARDWARE.COMPLETE

4 |

TABLE ACCESS INMEMORY FULL | DWR_SKU_ITEM


|
1
26 |
106
(1)| 00:00:01 |
|
|
5 |
JOIN FILTER USE
| :BF0000
|
27M|
418M| 31943
(2)| 00:00:02 |
|
|
|
6 |
PARTITION RANGE ALL
|
|
27M|
418M| 31943
(2)| 00:00:02 |
1 |1048575|
|* 7 |
TABLE ACCESS INMEMORY FULL| DWB_RTL_SLS_RETRN_LINE_ITEM |
27M|
418M| 31943
(2)| 00:00:02 |
1 |1048575|
----------------------------------------------------------------------------------------------------------------------------Predicate Information (identified by operation id):
--------------------------------------------------2 - access("LI"."SKU_ITEM_KEY"="P"."SKU_ITEM_KEY")
4 - inmemory("P"."SKU_ITEM_DESC" LIKE 'Diet Pepsi%')
filter("P"."SKU_ITEM_DESC" LIKE 'Diet Pepsi%')
7 - inmemory(("LI"."ACTN_CD"='Sale' AND
SYS_OP_BLOOM_FILTER(:BF0000,"LI"."SKU_ITEM_KEY")))
filter(("LI"."ACTN_CD"='Sale' AND
SYS_OP_BLOOM_FILTER(:BF0000,"LI"."SKU_ITEM_KEY")))

7.2.

A COMPLEX JOIN AND AGGREGATION QUERY

Lets try a more complex query that encompasses a 4-way join and an aggregation of a lot
more data. In this case the query will compute the revenues generated from the sale of a
specific sets of products (Diet Pepsi) in the a few select states (AZ, CA, NM, TX). Notice
that we are introducing a second fact table in the join, mainly DWB_RTL_TRX.
Note: Again, dont run the below SQL, yet!
SELECT p.SKU_ITEM_DESC, SUM(li.EXTENDED_AMT)
FROM DWB_RTL_SLS_RETRN_LINE_ITEM li,
DWB_RTL_TRX t,
DWR_SKU_ITEM p,
DWR_ORG_BSNS_UNIT s
WHERE li.TRX_NBR = t.TRX_NBR
AND li.DAY_KEY = t.DAY_KEY
AND li.SKU_ITEM_KEY = p.sku_item_key
AND t.BSNS_UNIT_KEY = s.ORG_BSNS_UNIT_KEY
AND li.ACTN_CD = 'Sale'
AND p.SKU_ITEM_DESC LIKE 'Diet Pepsi%'
AND s.STATE IN ('AZ', 'CA', 'NM', 'TX')
GROUP BY p.SKU_ITEM_DESC;

LAB STEPS
1. Run the below steps in a SQL*Plus session connected as the RTL user.
2. Execute the lab query against the IM column store. As we are dealing with more data this
2014 Oracle Corporation. All Rights Reserved.

Page 96

Oracle Database In-Memory Workshop

SOFTWARE.HARDWARE.COMPLETE

time, lets using parallel execution to speed up the query so we dont need to wait to long
for the results.
SET TIMING ON
-- IM Column Store query
SELECT /*+ PARALLEL (2) */ p.SKU_ITEM_DESC,
SUM(li.EXTENDED_AMT)
FROM DWB_RTL_SLS_RETRN_LINE_ITEM li,
DWB_RTL_TRX t,
DWR_SKU_ITEM p,
DWR_ORG_BSNS_UNIT s
WHERE li.TRX_NBR = t.TRX_NBR
AND li.DAY_KEY = t.DAY_KEY
AND li.SKU_ITEM_KEY = p.sku_item_key
AND t.BSNS_UNIT_KEY = s.ORG_BSNS_UNIT_KEY
AND li.ACTN_CD = 'Sale'
AND p.SKU_ITEM_DESC LIKE 'Diet Pepsi%'
AND s.STATE IN ('AZ', 'CA', 'NM', 'TX')
GROUP BY p.SKU_ITEM_DESC;
SET TIMING OFF
3. To get better and accurate timings, run the above query one more time. This is to avoid
issues with stale statistics by using the 12c new feature of dynamic statistics at query
execution time to automatically gather the latest stats.
SET TIMING ON
-- IM Column Store query
SELECT /*+ PARALLEL (2) */ p.SKU_ITEM_DESC,
SUM(li.EXTENDED_AMT)
FROM DWB_RTL_SLS_RETRN_LINE_ITEM li,
DWB_RTL_TRX t,
DWR_SKU_ITEM p,
DWR_ORG_BSNS_UNIT s
WHERE li.TRX_NBR = t.TRX_NBR
AND li.DAY_KEY = t.DAY_KEY
AND li.SKU_ITEM_KEY = p.sku_item_key
AND t.BSNS_UNIT_KEY = s.ORG_BSNS_UNIT_KEY
AND li.ACTN_CD = 'Sale'
AND p.SKU_ITEM_DESC LIKE 'Diet Pepsi%'
AND s.STATE IN ('AZ', 'CA', 'NM', 'TX')
GROUP BY p.SKU_ITEM_DESC;
SET TIMING OFF
2014 Oracle Corporation. All Rights Reserved.

Page 97

Oracle Database In-Memory Workshop

SOFTWARE.HARDWARE.COMPLETE

4. Execute the lab query against the buffer cache and observe the runtime. Tricky question: Is
it faster than the IM column store query?
ALTER SESSION SET INMEMORY_QUERY = DISABLE;
SET TIMING ON
-- Buffer cache query
SELECT /*+ PARALLEL (2) */ p.SKU_ITEM_DESC,
SUM(li.EXTENDED_AMT)
FROM DWB_RTL_SLS_RETRN_LINE_ITEM li,
DWB_RTL_TRX t,
DWR_SKU_ITEM p,
DWR_ORG_BSNS_UNIT s
WHERE li.TRX_NBR = t.TRX_NBR
AND li.DAY_KEY = t.DAY_KEY
AND li.SKU_ITEM_KEY = p.sku_item_key
AND t.BSNS_UNIT_KEY = s.ORG_BSNS_UNIT_KEY
AND li.ACTN_CD = 'Sale'
AND p.SKU_ITEM_DESC LIKE 'Diet Pepsi%'
AND s.STATE IN ('AZ', 'CA', 'NM', 'TX')
GROUP BY p.SKU_ITEM_DESC;
SET TIMING OFF
ALTER SESSION SET INMEMORY_QUERY = ENABLE;
5. The IM column store continues to out-perform the buffer cache query but what is more
interesting is the execution plan for this query.
6. Examine the execution plan for the query by rerunning it against the IM column store.
SET
SET
SET
SET

PAGES 0
LINES 200
TIMING ON
ECHO ON

-- IM Column Store query


SELECT /*+ PARALLEL (2) */ p.SKU_ITEM_DESC,
SUM(li.EXTENDED_AMT)
FROM DWB_RTL_SLS_RETRN_LINE_ITEM li,
DWB_RTL_TRX t,
DWR_SKU_ITEM p,
DWR_ORG_BSNS_UNIT s
WHERE li.TRX_NBR = t.TRX_NBR
AND li.DAY_KEY = t.DAY_KEY
AND li.SKU_ITEM_KEY = p.sku_item_key
AND t.BSNS_UNIT_KEY = s.ORG_BSNS_UNIT_KEY
AND li.ACTN_CD = 'Sale'
2014 Oracle Corporation. All Rights Reserved.

Page 98

Oracle Database In-Memory Workshop

SOFTWARE.HARDWARE.COMPLETE

AND p.SKU_ITEM_DESC LIKE 'Diet Pepsi%'


AND s.STATE IN ('AZ', 'CA', 'NM', 'TX')
GROUP BY p.SKU_ITEM_DESC;
-- Display the query plan
SELECT * FROM TABLE(DBMS_XPLAN.DISPLAY_CURSOR());
SET ECHO OFF

burwdhjj0bkpr, child number 2


------------------------------------SELECT /*+ PARALLEL (2) */ p.SKU_ITEM_DESC, SUM(li.EXTENDED_AMT) FROM
DWB_RTL_SLS_RETRN_LINE_ITEM li, DWB_RTL_TRX t, DWR_SKU_ITEM p,
DWR_ORG_BSNS_UNIT s WHERE li.TRX_NBR = t.TRX_NBR AND li.DAY_KEY =
t.DAY_KEY AND li.SKU_ITEM_KEY = p.sku_item_key AND t.BSNS_UNIT_KEY =
s.ORG_BSNS_UNIT_KEY AND li.ACTN_CD = 'Sale' AND p.SKU_ITEM_DESC LIKE
'Diet Pepsi%' AND s.STATE IN ('AZ', 'CA', 'NM', 'TX') GROUP BY
p.SKU_ITEM_DESC
Plan hash value: 3627717488
--------------------------------------------------------------------------------------------------------------------------------------------------------------------| Id | Operation
| Name
| Rows | Bytes |
Cost (%CPU)| Time | Pstart| Pstop |
TQ |IN-OUT| PQ Distrib |
--------------------------------------------------------------------------------------------------------------------------------------------------------------------|
0 | SELECT STATEMENT
|
|
|
|
19848 (100)|
|
|
|
|
|
|
|
1 | PX COORDINATOR
|
|
|
|
|
|
|
|
|
|
|
|
2 |
PX SEND QC (RANDOM)
| :TQ10002
|
13
| 1534 | 19848
(2)| 00:00:01 |
|
| Q1,02 | P->S | QC (RAND) |
|
3 |
HASH GROUP BY
|
|
13 |
1534 | 19848
(2)| 00:00:01 |
|
| Q1,02 | PCWP |
|
|
4 |
PX RECEIVE
|
|
13 |
1534 | 19848
(2)| 00:00:01 |
|
| Q1,02 | PCWP |
|
|
5 |
PX SEND HASH
| :TQ10001
|
13
| 1534 | 19848
(2)| 00:00:01 |
|
| Q1,01 | P->P | HASH
|
|
6 |
HASH GROUP BY
|
|
13 |
1534 | 19848
(2)| 00:00:01 |
|
| Q1,01 | PCWP |
|
|* 7 |
HASH JOIN
|
| 1139 |
131K| 19847
(2)| 00:00:01 | |
| Q1,01 | PCWP |
|
|* 8 |
TABLE ACCESS INMEMORY FULL
| DWR_ORG_BSNS_UNIT
|
198
| 1980 |
2
(0)| 00:00:01 |
|
| Q1,01 | PCWP |
|
|
9 |
PX PARTITION RANGE ALL
|
| 7556 |
796K| 19845
(2)| 00:00:01 |
1 |1048575| Q1,01 | PCWC |
|
|* 10 |
HASH JOIN
|
| 7556 |
796K|
19845
(2)| 00:00:01 | |
| Q1,01 | PCWP |
|
| 11 |
JOIN FILTER CREATE
| :BF0000
| 7556
|
531K| 17828
(2)| 00:00:01 |
|
| Q1,01 | PCWP |
|
|* 12 |
HASH JOIN
|
| 7556 |
531K| 17828
(2)| 00:00:01 | |
| Q1,01 | PCWP |
|
2014 Oracle Corporation. All Rights Reserved.

Page 99

Oracle Database In-Memory Workshop

SOFTWARE.HARDWARE.COMPLETE

| 13 |
BUFFER SORT
|
|
|
|
|
|
|
| Q1,01 | PCWC |
|
| 14 |
JOIN FILTER CREATE
| :BF0001
|
15
|
390 |
59
(2)| 00:00:01 |
|
| Q1,01 | PCWP |
|
| 15 |
PX RECEIVE
|
|
15 |
390 |
59
(2)| 00:00:01 |
|
| Q1,01 | PCWP |
|
| 16 |
PX SEND BROADCAST
| :TQ10000
|
15
|
390 |
59
(2)| 00:00:01 |
|
| Q1,00 | P->P | BROADCAST |
| 17 |
PX BLOCK ITERATOR
|
|
15 |
390 |
59
(2)| 00:00:01 |
|
| Q1,00 | PCWC |
|
|* 18 |
TABLE ACCESS INMEMORY FULL| DWR_SKU_ITEM
|
15 |
390 |
59
(2)| 00:00:01 | |
| Q1,00 | PCWP |
|
| 19 |
JOIN FILTER USE
| :BF0001
|
27M| 1204M| 17734
(1)| 00:00:01 |
|
| Q1,01 | PCWP |
|
|* 20 |
TABLE ACCESS INMEMORY FULL
| DWB_RTL_SLS_RETRN_LINE_ITEM |
27M| 1204M| 17734
(1)| 00:00:01 |
1 |1048575| Q1,01 | PCWP |
|
| 21 |
JOIN FILTER USE
| :BF0000
| 1834K|
62M| 2015
(1)| 00:00:01 |
|
| Q1,01 | PCWP |
|
|* 22 |
TABLE ACCESS INMEMORY FULL
| DWB_RTL_TRX
| 1834K|
62M| 2015
(1)| 00:00:01 |
1 |1048575| Q1,01 | PCWP |
|
--------------------------------------------------------------------------------------------------------------------------------------------------------------------Predicate Information (identified by operation id):
--------------------------------------------------7 - access("T"."BSNS_UNIT_KEY"="S"."ORG_BSNS_UNIT_KEY")
8 - inmemory(("S"."STATE"='AZ' OR "S"."STATE"='CA' OR "S"."STATE"='NM' OR
"S"."STATE"='TX'))
filter(("S"."STATE"='AZ' OR "S"."STATE"='CA' OR "S"."STATE"='NM' OR
"S"."STATE"='TX'))
10 - access("LI"."DAY_KEY"="T"."DAY_KEY" AND "LI"."TRX_NBR"="T"."TRX_NBR")
12 - access("LI"."SKU_ITEM_KEY"="P"."SKU_ITEM_KEY")
18 - inmemory(:Z>=:Z AND :Z<=:Z AND "P"."SKU_ITEM_DESC" LIKE 'Diet Pepsi%')
filter("P"."SKU_ITEM_DESC" LIKE 'Diet Pepsi%')
20 - inmemory(("LI"."ACTN_CD"='Sale' AND
SYS_OP_BLOOM_FILTER(:BF0000,"LI"."SKU_ITEM_KEY")))
filter(("LI"."ACTN_CD"='Sale' AND
SYS_OP_BLOOM_FILTER(:BF0000,"LI"."SKU_ITEM_KEY")))
22 - inmemory(SYS_OP_BLOOM_FILTER(:BF0000,"T"."TRX_NBR"))
filter(SYS_OP_BLOOM_FILTER(:BF0000,"T"."TRX_NBR"))
Note
----- dynamic statistics used: dynamic sampling (level=AUTO)
- Degree of Parallelism is 2 because of hint
- statistics feedback used for this statement

7. You will see that bloom filters were created again (highlighted above). Oracle Database is
not limited to just one bloom filter per scan. It is possible to apply multiple bloom filters on a
single query when appropriate. The above plan uses two bloom filters, one for
DWB_RTL_SLS_RETRN_LINE_ITEM and the second for DWB_RT_TRX.
8. Using multiple bloom filters we scan only the necessary columns for the fact tables,
2014 Oracle Corporation. All Rights Reserved.

Page 100

Oracle Database In-Memory Workshop

SOFTWARE.HARDWARE.COMPLETE

meaning we are able to benefit by eliminating rows during the scan rather than waiting for
the join to do it.

7.3.

EXECUTION STATISTICS OF THE COMPLEX QUERY

You may be wondering if all of the benefits we saw during the table scan tests in the previous
lesson are still relevant now that we are executing joins. The answer is a definite YES! The
bloom filters created for the joins benefit from the In-Memory storage index and the min/max
pruning it provides. You can see just how beneficial it provides by looking at the execution
statistics for our previous query.

LAB STEPS
1. In the previous SQL*Plus session reconnect as the user RTL to initialize session statistics.
CONNECT RTL/rtl
2. Execute the previous query against the IM column store once again, but this time to
capture the session statistics.
-- IM Column Store query
SELECT /*+ PARALLEL (2) */ p.SKU_ITEM_DESC,
SUM(li.EXTENDED_AMT)
FROM DWB_RTL_SLS_RETRN_LINE_ITEM li,
DWB_RTL_TRX t,
DWR_SKU_ITEM p,
DWR_ORG_BSNS_UNIT s
WHERE li.TRX_NBR = t.TRX_NBR
AND li.DAY_KEY = t.DAY_KEY
AND li.SKU_ITEM_KEY = p.sku_item_key
AND t.BSNS_UNIT_KEY = s.ORG_BSNS_UNIT_KEY
AND li.ACTN_CD = 'Sale'
AND p.SKU_ITEM_DESC LIKE 'Diet Pepsi%'
AND s.STATE IN ('AZ', 'CA', 'NM', 'TX')
GROUP BY p.SKU_ITEM_DESC;
3. Capture the value of the relevant session statistics (see below). Since we had reconnected
as RTL user, these stats were all reinitialized to zero. The values displayed by the below
SQL are the values consumed by the last SQL.
SELECT DISPLAY_NAME, VALUE
2014 Oracle Corporation. All Rights Reserved.

Page 101

Oracle Database In-Memory Workshop

SOFTWARE.HARDWARE.COMPLETE

FROM V$MYSTAT m, V$STATNAME n


WHERE m.STATISTIC# = n.STATISTIC#
AND n.DISPLAY_NAME IN (
'IM scan segments minmax eligible',
'IM scan CUs pruned',
'IM scan CUs columns accessed');

SQL> SELECT DISPLAY_NAME, VALUE


FROM V$MYSTAT m, V$STATNAME n
WHERE m.STATISTIC# = n.STATISTIC#
AND n.DISPLAY_NAME IN ('IM scan segments minmax eligible', 'IM scan CUs
pruned','IM scan CUs columns accessed');
IM scan CUs columns accessed
IM scan CUs pruned
IM scan segments minmax eligible

309
0
2

Elapsed: 00:00:00.00

4. Notice in the above output that IM scan segments minmax eligible is only 2. This means
that the storage indexes have helped to execute the previous query.

7.4.

VECTOR GROUP BY

In order to further speed up operations Oracle has introduced a new Optimizer transformation,
called the Vector Group By. This transformation is a two-part process not dissimilar to that of
star transformation. First, the dimension tables are scanned and any where clause predicates
are applied. A new data structure called a key vector is created based on the results of these
scans. The key vector is similar to a bloom filter as it allows the join predicates to be applied as
additional filter predicates during the scan of the fact table, but it also enables us to conduct
the group by or aggregation during the scan of the fact table instead of having to do it
afterwards.
The second part of the execution plan sees the results of the fact table scan being joined back
to the temporary tables created as part of the scan of the dimension tables. These temporary
tables contain the payload columns (columns need in the select list) from the dimension table.
The combination of these two phases dramatically improves the efficiency of a multiple table
join with complex aggregations. Both phases are visible in the execution plan of our query.

2014 Oracle Corporation. All Rights Reserved.

Page 102

Oracle Database In-Memory Workshop

SOFTWARE.HARDWARE.COMPLETE

LAB STEPS
1. In the previous SQL*Plus session reconnect as the user RTL to initialize session statistics.
CONNECT RTL/rtl
2. Lets take a look at Vector Group By in action. Execute the lab query against the IM
column store. This time specify the VECTOR_TRANSFORM hint to kick-in the Vector Group
By.
SET TIMING ON
-- IM Column Store query
SELECT /*+ PARALLEL (2) VECTOR_TRANSFORM */ p.SKU_ITEM_DESC,
SUM(li.EXTENDED_AMT)
FROM DWB_RTL_SLS_RETRN_LINE_ITEM li,
DWB_RTL_TRX t,
DWR_SKU_ITEM p,
DWR_ORG_BSNS_UNIT s
WHERE li.TRX_NBR = t.TRX_NBR
AND li.DAY_KEY = t.DAY_KEY
AND li.SKU_ITEM_KEY = p.sku_item_key
AND t.BSNS_UNIT_KEY = s.ORG_BSNS_UNIT_KEY
AND li.ACTN_CD = 'Sale'
AND p.SKU_ITEM_DESC LIKE 'Diet Pepsi%'
AND s.STATE IN ('AZ', 'CA', 'NM', 'TX')
GROUP BY p.SKU_ITEM_DESC;
SET TIMING OFF
3. Execute the lab query against the buffer cache and observe the runtime.
ALTER SESSION SET INMEMORY_QUERY = DISABLE;
SET TIMING ON
-- Buffer cache query
SELECT /*+ PARALLEL (2) */ p.SKU_ITEM_DESC,
SUM(li.EXTENDED_AMT)
FROM DWB_RTL_SLS_RETRN_LINE_ITEM li,
DWB_RTL_TRX t,
DWR_SKU_ITEM p,
DWR_ORG_BSNS_UNIT s
WHERE li.TRX_NBR = t.TRX_NBR
AND li.DAY_KEY = t.DAY_KEY
AND li.SKU_ITEM_KEY = p.sku_item_key
AND t.BSNS_UNIT_KEY = s.ORG_BSNS_UNIT_KEY
2014 Oracle Corporation. All Rights Reserved.

Page 103

Oracle Database In-Memory Workshop

SOFTWARE.HARDWARE.COMPLETE

AND li.ACTN_CD = 'Sale'


AND p.SKU_ITEM_DESC LIKE 'Diet Pepsi%'
AND s.STATE IN ('AZ', 'CA', 'NM', 'TX')
GROUP BY p.SKU_ITEM_DESC;
SET TIMING OFF
ALTER SESSION SET INMEMORY_QUERY = ENABLE;
4. The IM column store continues to out-perform the buffer cache query. Examine the
execution plan for the query by rerunning it against the IM column store.
SET
SET
SET
SET

PAGES 0
LINES 200
TIMING ON
ECHO ON

-- IM Column Store query


SELECT /*+ PARALLEL (2) VECTOR_TRANSFORM */ p.SKU_ITEM_DESC,
SUM(li.EXTENDED_AMT)
FROM DWB_RTL_SLS_RETRN_LINE_ITEM li,
DWB_RTL_TRX t,
DWR_SKU_ITEM p,
DWR_ORG_BSNS_UNIT s
WHERE li.TRX_NBR = t.TRX_NBR
AND li.DAY_KEY = t.DAY_KEY
AND li.SKU_ITEM_KEY = p.sku_item_key
AND t.BSNS_UNIT_KEY = s.ORG_BSNS_UNIT_KEY
AND li.ACTN_CD = 'Sale'
AND p.SKU_ITEM_DESC LIKE 'Diet Pepsi%'
AND s.STATE IN ('AZ', 'CA', 'NM', 'TX')
GROUP BY p.SKU_ITEM_DESC;
-- Display the query plan
SELECT * FROM TABLE(DBMS_XPLAN.DISPLAY_CURSOR());
SET ECHO OFF
a6zga2h5ndrgw, child number 1
------------------------------------SELECT /*+ PARALLEL (2) VECTOR_TRANSFORM */ p.SKU_ITEM_DESC,
SUM(li.EXTENDED_AMT) FROM DWB_RTL_SLS_RETRN_LINE_ITEM li, DWB_RTL_TRX
t, DWR_SKU_ITEM p, DWR_ORG_BSNS_UNIT s WHERE li.TRX_NBR = t.TRX_NBR AND
li.DAY_KEY = t.DAY_KEY AND li.SKU_ITEM_KEY = p.sku_item_key AND
t.BSNS_UNIT_KEY = s.ORG_BSNS_UNIT_KEY AND li.ACTN_CD = 'Sale' AND
p.SKU_ITEM_DESC LIKE 'Diet Pepsi%' AND s.STATE IN ('AZ', 'CA', 'NM',
'TX') GROUP BY p.SKU_ITEM_DESC
Plan hash value: 2567947823
2014 Oracle Corporation. All Rights Reserved.

Page 104

Oracle Database In-Memory Workshop

SOFTWARE.HARDWARE.COMPLETE

----------------------------------------------------------------------------------------------------------------------------------------------------------------------| Id | Operation
| Name
| Rows |
Bytes | Cost (%CPU)| Time
| Pstart| Pstop |
TQ |IN-OUT| PQ Distrib
|
----------------------------------------------------------------------------------------------------------------------------------------------------------------------|
0 | SELECT STATEMENT
|
|
|
| 20309 (100)|
|
|
|
|
|
|
|
1 | TEMP TABLE TRANSFORMATION
|
|
|
|
|
|
|
|
|
|
|
|
2 |
LOAD AS SELECT
|
|
|
|
|
|
|
|
|
|
|
|
3 |
PX COORDINATOR
|
|
|
|
|
|
|
|
|
|
|
|
4 |
PX SEND QC (RANDOM)
| :TQ10001
|
1 |
50 | 2421 (17)| 00:00:01 |
|
| Q1,01 | P->S | QC (RAND)
|
|
5 |
HASH GROUP BY
|
|
1 | 50 | 2421 (17)| 00:00:01 |
|
| Q1,01 | PCWP |
|
|
6 |
PX RECEIVE
|
|
1 | 50 | 2421 (17)| 00:00:01 |
|
| Q1,01 | PCWP |
|
|
7 |
PX SEND HASH
| :TQ10000
|
1 |
50 | 2421 (17)| 00:00:01 |
|
| Q1,00 | P->P | HASH
|
|
8 |
VECTOR GROUP BY
|
|
1 |
50 | 2421 (17)| 00:00:01 |
|
| Q1,00 | PCWP |
|
|
9 |
HASH GROUP BY
|
|
1 | 50 | 2421 (17)| 00:00:01 |
|
| Q1,00 | PCWP |
|
| 10 |
KEY VECTOR CREATE BUFFERED
| :KV0000
|
270K| 12M| 2421 (17)| 00:00:01 |
|
| Q1,00 | PCWC |
|
|* 11 |
HASH JOIN
|
|
270K| 11M| 2019
(1)| 00:00:01 |
|
| Q1,00 | PCWP |
|
| 12 |
JOIN FILTER CREATE
| :BF0000
|
198 | 1980 |
2
(0)| 00:00:01 |
|
| Q1,00 | PCWP |
|
|* 13 |
TABLE ACCESS INMEMORY FULL
| DWR_ORG_BSNS_UNIT
|
198 | 1980 |
2
(0)| 00:00:01 |
|
| Q1,00 | PCWP |
|
| 14 |
JOIN FILTER USE
| :BF0000
|
1834K|
62M| 2015
(1)| 00:00:01 |
|
| Q1,00 | PCWP |
|
| 15 |
PX BLOCK ITERATOR
|
|
1834K|
62M| 2015
(1)| 00:00:01 |
1 |1048575| Q1,00 | PCWC |
|
|* 16 |
TABLE ACCESS INMEMORY FULL
| DWB_RTL_TRX
|
1834K|
62M| 2015
(1)| 00:00:01 |
1 |1048575| Q1,00 | PCWP |
|
| 17 |
LOAD AS SELECT
|
|
|
|
|
|
|
|
|
|
|
| 18 |
PX COORDINATOR
|
|
|
|
|
|
|
|
|
|
|
| 19 |
PX SEND QC (RANDOM)
| :TQ20001
|
1 |
30 | 60
(4)| 00:00:01 |
|
| Q2,01 | P->S | QC (RAND)
2014 Oracle Corporation. All Rights Reserved.

Page 105

Oracle Database In-Memory Workshop


|
|
|

|
20 |

SOFTWARE.HARDWARE.COMPLETE

1 |

BUFFER SORT
30 | 60
(4)| 00:00:01 |

1 |

VECTOR GROUP BY
30 | 60
(4)| 00:00:01 |

1 |

KEY VECTOR CREATE BUFFERED


30 | 60
(4)| 00:00:01 |

|
21 |
|
22 |

|
23 |
26
| 24 |
26
| 25 |
1
|
|* 26 |
1
|
| 27 |
|

|
|

TABLE ACCESS INMEMORY FULL


26 | 59
(2)| 00:00:01 |

PX COORDINATOR
|
|
|
|
| 28 |
PX SEND QC (RANDOM)
13 | 1820 | 17828
(2)| 00:00:01
(RAND)
|
| 29 |
HASH GROUP BY
13 | 1820 | 17828
(2)| 00:00:01
|
| 30 |
PX RECEIVE
13 | 1820 | 17828
(2)| 00:00:01
|
| 31 |
PX SEND HASH
1820 | 17828
(2)| 00:00:01 |
|
| 32 |
HASH GROUP BY
13 | 1820 | 17828
(2)| 00:00:01
|
|* 33 |
HASH JOIN
1820 | 17827
(2)| 00:00:01 |
|
|* 34 |
HASH JOIN
1482 | 17825
(2)| 00:00:01 |
|
| 35 |
TABLE ACCESS FULL
|
1 | 50 |
2
(0)| 00:00:01 |
|
| 36 |
VIEW
13 |
832 | 17823
(2)| 00:00:01
|
| 37 |
HASH GROUP BY
702 | 17823
(2)| 00:00:01 |
|
|
| 38 |
PX RECEIVE
13 |
702 | 17823
(2)| 00:00:01
|
| 39 |
PX SEND HASH
| 17823
(2)| 00:00:01 |
|
|
| 40 |
VECTOR GROUP BY
13 |
702 | 17823
(2)| 00:00:01
|
| 41 |
HASH GROUP BY
13 |
702 | 17823
(2)| 00:00:01
|

Q2,01 | PCWP |

| :KV0001
| Q2,01 | PCWP |

|
Q2,01 | PCWP |
| :TQ20000
|
| Q2,00 | P->P | HASH
|
|
| Q2,00 | PCWC |
|

1 |
|
1 |
|
|

| DWR_SKU_ITEM
| Q2,00 | PCWP |
|

2014 Oracle Corporation. All Rights Reserved.

Q2,01 | PCWP |

PX RECEIVE
|
59
(2)| 00:00:01 |
|
PX SEND HASH
59
(2)| 00:00:01 |
|
PX BLOCK ITERATOR
26 | 59
(2)| 00:00:01 |

|
|

|
|
|
| :TQ30002
|
|
| Q3,02 | P->S | QC
|

|
|
|

|
|

Q3,02 | PCWP |

Q3,02 | PCWP |

|
|
|
|
|

| :TQ30001
| 13 |
Q3,01 | P->P | HASH
|
|
|
|
| Q3,01 | PCWP |
|

13 |
|
| 13 |
| Q3,01 | PCWP |
|
| SYS_TEMP_0FD9D6686_1A9828
|
| Q3,01 | PCWP |
|

Q3,01 | PCWP |

| VW_VT_0CBA499D
|
|
| Q3,01 | PCWP |

Q3,01 | PCWP |
|
|
|
|

13 |

|
|
Q3,01 | PCWP |

| :TQ30000
| 13 |
702
Q3,00 | P->P | HASH
|
|
|
|
|
| Q3,00 | PCWP |
|
|

|
|

Q3,00 | PCWP |
Page 106

Oracle Database In-Memory Workshop


|

42 |
13 |

KEY VECTOR USE


702 | 17823
(2)| 00:00:01 |

SOFTWARE.HARDWARE.COMPLETE

| :KV0000
|
|

|
Q3,00 | PCWC |

|
| 43 |
KEY VECTOR USE
| :KV0001
| 13 |
650 | 17711
(1)| 00:00:01 |
|
| Q3,00 | PCWC |
|
| 44 |
PX BLOCK ITERATOR
|
|
1139 | 52394 | 17711
(1)| 00:00:01 |
1 |1048575| Q3,00 | PCWC |
|
|* 45 |
TABLE ACCESS INMEMORY FULL| DWB_RTL_SLS_RETRN_LINE_ITEM
| 1139 | 52394 | 17711
(1)| 00:00:01 | 1 |1048575| Q3,00 | PCWP |
|
| 46 |
TABLE ACCESS FULL
| SYS_TEMP_0FD9D6687_1A9828
|
1 | 26 |
2
(0)| 00:00:01 |
|
| Q3,01 | PCWP |
|
----------------------------------------------------------------------------------------------------------------------------------------------------------------------Predicate Information (identified by operation id):
--------------------------------------------------11 - access("T"."BSNS_UNIT_KEY"="S"."ORG_BSNS_UNIT_KEY")
13 - inmemory(("S"."STATE"='AZ' OR "S"."STATE"='CA' OR "S"."STATE"='NM' OR
"S"."STATE"='TX'))
filter(("S"."STATE"='AZ' OR "S"."STATE"='CA' OR "S"."STATE"='NM' OR
"S"."STATE"='TX'))
16 - inmemory(:Z>=:Z AND :Z<=:Z AND
SYS_OP_BLOOM_FILTER(:BF0000,"T"."BSNS_UNIT_KEY"))
filter(SYS_OP_BLOOM_FILTER(:BF0000,"T"."BSNS_UNIT_KEY"))
26 - inmemory(:Z>=:Z AND :Z<=:Z AND "P"."SKU_ITEM_DESC" LIKE 'Diet Pepsi%')
filter("P"."SKU_ITEM_DESC" LIKE 'Diet Pepsi%')
33 - access("ITEM_12"=INTERNAL_FUNCTION("C0") AND "ITEM_13"="C2")
34 - access("ITEM_9"=INTERNAL_FUNCTION("C0") AND "ITEM_10"="C2" AND
"ITEM_11"="C3")
45 - inmemory(:Z>=:Z AND :Z<=:Z AND ("LI"."ACTN_CD"='Sale' AND
SYS_OP_KEY_VECTOR_FILTER("LI"."SKU_ITEM_KEY",:KV0001) AND
SYS_OP_KEY_VECTOR_FILTER("LI"."DAY_KEY","LI"."TRX_NBR",:KV0000)))
filter(("LI"."ACTN_CD"='Sale' AND
SYS_OP_KEY_VECTOR_FILTER("LI"."SKU_ITEM_KEY",:KV0001) AND
SYS_OP_KEY_VECTOR_FILTER("LI"."DAY_KEY","LI"."TRX_NBR",:KV0000)))
Note
----- dynamic statistics used: dynamic sampling (level=AUTO)
- Degree of Parallelism is 2 because of hint
- statistics feedback used for this statement
- vector transformation used for this statement

5. Observe that Vector Group By was used for this query (highlighted above).

7.5.

SUMMARY

In this lesson you have observed queries containing joins and aggregations and their
performance comparisons. You also had an opportunity to see just how efficiently a join that
automatically gets converted to a bloom filter, can be executed on the IM column store.
2014 Oracle Corporation. All Rights Reserved.

Page 107

Oracle Database In-Memory Workshop

SOFTWARE.HARDWARE.COMPLETE

You also got to see just how sophisticated the Oracle Optimizer has become over the last 30
years, when it used a combination of complex query transformations to find the optimal
execution plan for a star query.
Finally, you got an opportunity to see the new vector group by transformation in action. This
new transformation allows us to not only convert joins to filter applied as part of a scan but also
to complete all aggregation operations as part of the scan of the fact table.

2014 Oracle Corporation. All Rights Reserved.

Page 108

Oracle Database In-Memory Workshop

8.

SOFTWARE.HARDWARE.COMPLETE

DML AND THE IM COLUMN STORE

It is clear by now that the IM column store can dramatically improve performance of all types of
queries but very few database environments are read-only. For the IM column store to be truly
effective in modern database environments it has to handle both bulk data loads AND online
transaction processing (OLTP).
This lesson demonstrates how the Oracle Database In-Memory is the only in-memory column
store that can handle both bulk data loads and online transaction processing today.

8.1.

BULK DATA LOADS

Bulk data loads occur most commonly in Data Warehouse environments and are typically
conducted as a direct path load. A direct path load parses the input data, converts the data for
each input field to its corresponding Oracle data type, and then builds a column array structure
for the data. These column array structures are used to format Oracle data blocks and build
index keys. The newly formatted database blocks are then written directly to the database,
bypassing the standard SQL processing engine and the database buffer cache.
Once the load operation (direct path or non-direct path) has been committed, the IM column
store is instantly aware it does not have all of the data populated for the object. The size of the
missing data will be visible in the BYTES_NOT_POPULATED column of V$IM_SEGMENTS. If the
object has a PRIORITY specified on it then the newly added data will be automatically
populated into the IM column store. Otherwise the next time the object is queried, the
background worker processes will be triggered to begin populating the missing data, assuming
there is free space in the IM column store.

8.1.1.

DATA LOADS SCENARIO 1

In this scenario, you will create a new table called SALES1 with default PRIORITY (i.e. NONE)
and perform non-direct Path data loads.

LAB STEPS
1. Using SQL*Plus, connect as LABUSER.
CONNECT LABUSER/labuser
2014 Oracle Corporation. All Rights Reserved.

Page 109

Oracle Database In-Memory Workshop

SOFTWARE.HARDWARE.COMPLETE

2. Create a new SALES1 table as an empty copy of SALES.


CREATE TABLE SALES1 AS SELECT * FROM SALES WHERE 1=2;
3. Alter the SALES1 table and enable it for the IM Column Store.
Note: The INMEMORY clause could also be specified during CTAS (Create Table as Select)
step itself, for example, via CREATE TABLE INMEMORY AS SELECT
ALTER TABLE SALES1 INMEMORY;
4. Load data into SALES1 via a bulk load operation (non-direct path). Do NOT COMMIT the
transaction yet.
INSERT INTO SALES1
SELECT * FROM SALES WHERE ROWNUM <=10000;

SQL> INSERT INTO SALES1 SELECT * FROM SALES WHERE ROWNUM <=10000;
10000 rows created.

5. Check if the SALES1 table got populated into the IM column store by querying
V$IM_SEGMENTS. What do you observe?
SELECT * FROM V$IM_SEGMENTS WHERE SEGMENT_NAME = 'SALES1';
SQL> SELECT * FROM V$IM_SEGMENTS WHERE SEGMENT_NAME = 'SALES1';
no rows selected

6. As the data was not committed, the IM column store will not be able to see the changes
and hence cannot be populated to the column store. COMMIT the changes so they are
visible to the column store.
COMMIT;
SQL> COMMIT;
Commit complete.

7. Recheck V$IM_SEGMENTS.
2014 Oracle Corporation. All Rights Reserved.

Page 110

Oracle Database In-Memory Workshop

SOFTWARE.HARDWARE.COMPLETE

SELECT * FROM V$IM_SEGMENTS WHERE SEGMENT_NAME = 'SALES1';

SQL> SELECT * FROM V$IM_SEGMENTS WHERE SEGMENT_NAME = 'SALES1';


no rows selected

8. Notice that SALES1 still did not get populated even though you had performed a COMMIT.
Why?
9. This is because the initial population is only triggered by querying the table via full table
scan, using DBMS_INMEMORY.POPULATE or by specifying the PRIORITY clause, none of
which was done in this case.
10. Next, check the following session statistics:
IM populate segments requested. The number of times the session has requested for
In-Memory population of a segment.
IM transactions. Transactions issued by the session to In-Memory tables (i.e. the
number of times COMMITs have been issued).
IM transactions rows journaled. Count of rows logged in the Transaction Journal by
the session. Transaction Journal is discussed in the DML section.
SELECT DISPLAY_NAME, VALUE
FROM V$MYSTAT m, V$STATNAME n
WHERE m.STATISTIC# = n.STATISTIC#
AND n.DISPLAY_NAME IN (
'IM populate segments requested',
'IM transactions',
'IM transactions rows journaled');

DISPLAY_NAME
-----------------------------------------IM transactions
IM transactions rows journaled
IM populate segments requested

VALUE
-------1
10000
0

11. In the above output, observe the following:


IM populate segments requested. Segment population requested should be 0, as the
2014 Oracle Corporation. All Rights Reserved.

Page 111

Oracle Database In-Memory Workshop

SOFTWARE.HARDWARE.COMPLETE

column store population has not been triggered.


IM transactions. There was one COMMIT issued.
IM transactions rows journaled. The total number of rows loaded in the session so far
is 10000.
12. Lets manually trigger a population using DBMS_INMEMORY.POPULATE procedure.
EXEC DBMS_INMEMORY.POPULATE('LABUSER','SALES1',NULL);

SQL> EXEC DBMS_INMEMORY.POPULATE('LABUSER','SALES1',NULL);


PL/SQL procedure successfully completed.

13. Check the population status now. You may need to run the below query a few times until
you see an entry for SALES1 with BYTES_NOT_POPULATED as 0.
COL SEGMENT_NAME FORMAT A20
SELECT SEGMENT_NAME, POPULATE_STATUS, BYTES, BYTES_NOT_POPULATED
FROM V$IM_SEGMENTS WHERE SEGMENT_NAME = 'SALES1';

SEGMENT_NAME
POPULATE_
BYTES BYTES_NOT_POPULATED
-------------------- --------- ---------- ------------------SALES1
COMPLETED
458752
0

14. Check the session statistic IM populate segments requested. What do you observe?
SELECT DISPLAY_NAME, VALUE
FROM V$MYSTAT m, V$STATNAME n
WHERE m.STATISTIC# = n.STATISTIC#
AND n.DISPLAY_NAME IN (
'IM populate segments requested');
DISPLAY_NAME
-----------------------------------------IM populate segments requested

VALUE
-------1

15. IM populate segments requested is now 1, i.e. reflecting the population request initiated
by DBMS_INMEMORY.POPULATE.

2014 Oracle Corporation. All Rights Reserved.

Page 112

Oracle Database In-Memory Workshop

SOFTWARE.HARDWARE.COMPLETE

16. Using V$IM_SEGMENTS_DETAIL, check the number of extents and blocks for SALES1,
both on disk and in-memory. Note that the number of blocks loaded in-memory (i.e.
mapped to IMCUs) may be different from on-disk blocks as only the used blocks get
populated into the column store.
COL OBJECT_NAME FORMAT A20
SELECT a.OBJECT_NAME, b.MEMBYTES, b.EXTENTS, b.BLOCKS,
b.DATABLOCKS, b.BLOCKSINMEM, b.BYTES
FROM V$IM_SEGMENTS_DETAIL b, DBA_OBJECTS a
WHERE a.DATA_OBJECT_ID = b.DATAOBJ
AND a.OBJECT_NAME = 'SALES1';
SQL> COL OBJECT_NAME FORMAT A10
SQL> SELECT a.OBJECT_NAME, b.MEMBYTES, b.EXTENTS, b.BLOCKS, b.DATABLOCKS,
b.BLOCKSINMEM, b.BYTES FROM V$IM_SEGMENTS_DETAIL b, DBA_OBJECTS a WHERE
a.DATA_OBJECT_ID = b.DATAOBJ AND a.OBJECT_NAME = 'SALES1';
OBJECT_NAM
MEMBYTES
EXTENTS
BLOCKS DATABLOCKS BLOCKSINMEM BYTES
---------- ---------- ---------- ---------- ---------- ----------- -----SALES1
1179648
7
56
50
50 458752

17. From the above output, observe that SALES1 so far has 7 extents, 56 allocated on-disk
blocks (BLOCKS) and 50 used blocks (DATABLOCKS), out of which all 50 have been loaded
to the IM column store (BLOCKSINMEM).

8.1.2.

DATA LOADS SCENARIO 2

In this scenario, you will load a few additional rows into SALES1 and observe the column store
population.

LAB STEPS
1. In the previous SQL*Plus session connected as LABUSER, run the following steps:
2. Load a few rows into SALES1 via IAS (Insert as Select). Commit the changes so they
become visible to the IM column store.
INSERT INTO SALES1
SELECT *
FROM SALES
WHERE ROWNUM <=1000;
2014 Oracle Corporation. All Rights Reserved.

Page 113

Oracle Database In-Memory Workshop

SOFTWARE.HARDWARE.COMPLETE

COMMIT;
3. Check the session statistics once again and observe the change.
SELECT DISPLAY_NAME, VALUE
FROM V$MYSTAT m, V$STATNAME n
WHERE m.STATISTIC# = n.STATISTIC#
AND n.DISPLAY_NAME IN (
'IM populate segments requested',
'IM transactions',
'IM transactions rows journaled');

DISPLAY_NAME
-----------------------------------------IM transactions
IM transactions rows journaled
IM populate segments requested

VALUE
-------2
11000
1

4. From the above output, the IM transactions are now incremented to 2 (one additional due
to the recent COMMIT) and the number of IM transactions rows journaled are now 11000
(reflecting the newly added 1000 rows on top of 10000).
5. Check if the rows that just got inserted resulted in new extents being added to the on-disk
table.
COL OBJECT_NAME FORMAT A20
SELECT a.OBJECT_NAME, b.MEMBYTES, b.EXTENTS, b.BLOCKS,
b.DATABLOCKS, b.BLOCKSINMEM, b.BYTES
FROM V$IM_SEGMENTS_DETAIL b, DBA_OBJECTS a
WHERE a.DATA_OBJECT_ID = b.DATAOBJ
AND a.OBJECT_NAME = 'SALES1';

SQL> COL OBJECT_NAME FORMAT A10


SQL> SELECT a.OBJECT_NAME, b.MEMBYTES, b.EXTENTS, b.BLOCKS, b.DATABLOCKS,
b.BLOCKSINMEM, b.BYTES FROM V$IM_SEGMENTS_DETAIL b, DBA_OBJECTS a WHERE
a.DATA_OBJECT_ID = b.DATAOBJ AND a.OBJECT_NAME = 'SALES1';
OBJECT_NAM
MEMBYTES
EXTENTS
BLOCKS DATABLOCKS BLOCKSINMEM BYTES
---------- ---------- ---------- ---------- ---------- ----------- -----SALES1
1179648
7
56
50
50 458752

6. As you observe from the above output, no new extents were added as only a few rows
2014 Oracle Corporation. All Rights Reserved.

Page 114

Oracle Database In-Memory Workshop

SOFTWARE.HARDWARE.COMPLETE

were loaded (1000 rows). The table hasnt grown its on-disk footprint, and still has 7
extents, 50 DATABLOCKS and 50 BLOCKSINMEM.
7. If the table would have grown its on-disk footprint, the rows in the new extents will not be
automatically populated into the column store, unless a non-default PRIOIRTY is specified
or the table gets accessed, or the procedure DBMS_INMEMORY.PROPULATE is used.
8. If the new rows get added to existing extents/blocks, the new rows should be populated to
the IM column store via the trickle repopulate process (discussed later), even when a
default PRIORITY is specified on the table.
9. Check the V$IM_SEGMENTS view and observe the value in BYTES_NOT_POPULATED
column. Do you think a 0 in this column indicate that all the new rows have been added to
the column store?
COL SEGMENT_NAME FORMAT A20
SELECT SEGMENT_NAME, POPULATE_STATUS, BYTES, BYTES_NOT_POPULATED
FROM V$IM_SEGMENTS WHERE SEGMENT_NAME = 'SALES1';

SEGMENT_NAME
POPULATE_
BYTES BYTES_NOT_POPULATED
-------------------- --------- ---------- ------------------SALES1
COMPLETED
458752
0

10. BYTES_NOT_POPULATED only indicates the bytes in the new extents that got added to the
segment and have not been populated to the column store. If the new rows get inserted
into the existing extents, BYTES_NOT_POPULATED will still be 0 and new rows may still be
not populated. This how the V$IM_SEGMENTS view behaves currently.
11. Next, check if the newly added rows got populated to the IM column store using
V$IM_HEADER view. This view contains details about all IMCUs (incl. split IMCUs) for all
segments that are loaded into the column store.
Note: You may have to run the below query a few times in order to for
TRICKLE_REPOPULATE to be set to 1.
COL OBJECT_NAME FORMAT A10
2014 Oracle Corporation. All Rights Reserved.

Page 115

Oracle Database In-Memory Workshop

SOFTWARE.HARDWARE.COMPLETE

SELECT b.OBJECT_NAME, a.PREPOPULATED, a.REPOPULATED,


a.TRICKLE_REPOPULATED, a.NUM_DISK_EXTENTS, a.NUM_BLOCKS,
a.NUM_ROWS, a.NUM_COLS
FROM V$IM_HEADER a, DBA_OBJECTS b
WHERE a.OBJD = b.DATA_OBJECT_ID
AND b.OBJECT_NAME = 'SALES1';

SQL> COL OBJECT_NAME FORMAT A10 SELECT b.OBJECT_NAME, a.PREPOPULATED,


a.REPOPULATED, a.TRICKLE_REPOPULATED, a.NUM_DISK_EXTENTS, a.NUM_BLOCKS,
a.NUM_ROWS, a.NUM_COLS FROM V$IM_HEADER a, DBA_OBJECTS b WHERE a.OBJD =
b.DATA_OBJECT_ID AND b.OBJECT_NAME = 'SALES1';
OBJECT_NAM PREPOPULATED REPOPULATED TRICKLE_REPOPULATED NUM_DISK_EXTENTS
NUM_BLOCKS
NUM_ROWS
NUM_COLS
---------- ------------ ----------- ------------------- ------------------------- ---------- ---------SALES1
7

50

11000

12. Below are the observations from the above output:


There is only one IMCU (evident from the presence of only a single row in the output).
The number of on disk rows mapped to this IMCU is 11000, which means that the
newly added 1000 rows were also recorded in the journal.
A total of 50 disk extents have been mapped to this IMCU.
The REPOPULATED flag and the TRICKLE_REPOPULATED flag for this IMCU has been
set to 1 (indicating that the trickle repopulate process has synchronized the changes).
The trickle repopulate process must have populated the last 1000 rows.

8.1.3.

DATA LOADS SCENARIO 3

In this scenario, you perform another load (using direct path) into SALES1 and observe the
column store population.

LAB STEPS
1. Run the following steps in the previous SQL*Plus session connected as LABUSER.
2014 Oracle Corporation. All Rights Reserved.

Page 116

Oracle Database In-Memory Workshop

SOFTWARE.HARDWARE.COMPLETE

2. Load 10000 more rows into SALES1 via a direct path load (using the APPEND hint). Commit
the changes.
Note: The use of direct path load guarantees that the new rows get added to new extents
thereby requiring a repopulation.
INSERT /*+APPEND*/ INTO SALES1
SELECT *
FROM SALES
WHERE ROWNUM <=10000;
COMMIT;
3. Check if the rows that just got inserted resulted in new extents added to the on-disk table.
COL OBJECT_NAME FORMAT A20
SELECT a.OBJECT_NAME, b.MEMBYTES, b.EXTENTS, b.BLOCKS,
b.DATABLOCKS, b.BLOCKSINMEM, b.BYTES
FROM V$IM_SEGMENTS_DETAIL b, DBA_OBJECTS a
WHERE a.DATA_OBJECT_ID = b.DATAOBJ
AND a.OBJECT_NAME = 'SALES1';

SQL> COL OBJECT_NAME FORMAT A10


SQL> SELECT a.OBJECT_NAME, b.MEMBYTES, b.EXTENTS, b.BLOCKS, b.DATABLOCKS,
b.BLOCKSINMEM, b.BYTES FROM V$IM_SEGMENTS_DETAIL b, DBA_OBJECTS a WHERE
a.DATA_OBJECT_ID = b.DATAOBJ AND a.OBJECT_NAME = 'SALES1';
OBJECT_NAM
MEMBYTES
EXTENTS
BLOCKS DATABLOCKS BLOCKSINMEM BYTES
---------- ---------- ---------- ---------- ---------- ----------- -----SALES1
1179648
10
80
66
50
655360

4. As you observe from the above output, new extents were added to the disk. The SALES1
table now has 10 extents, 66 used blocks on disk (DATABLOCKS), out of which 50 blocks
are in memory (BLOCKSINMEM). The 16 blocks (66 - 50) have yet to be populated to the
column store.
5. Check the V$IM_SEGMENTS view and observe the BYTES_NOT_POPULATED column.
COL SEGMENT_NAME FORMAT A20
SELECT SEGMENT_NAME, POPULATE_STATUS, BYTES, BYTES_NOT_POPULATED
FROM V$IM_SEGMENTS WHERE SEGMENT_NAME = 'SALES1';
2014 Oracle Corporation. All Rights Reserved.

Page 117

Oracle Database In-Memory Workshop

SOFTWARE.HARDWARE.COMPLETE

SEGMENT_NAME
POPULATE_
BYTES BYTES_NOT_POPULATED
-------------------- --------- -------- ------------------SALES1
COMPLETED
655360
131072

6. BYTES_NOT_POPULATED shows that the segment is not fully populated. Note that the
POPULATE_STATUS still says COMPLETE. As discussed earlier, POPULATE_STATUS only
shows the initial population status and not repopulation.
7. As the table has grown its on-disk footprint and the table has PRIOIRTY of NONE, the rows
in the new extents will not be automatically populated into the column store.
8. Manually trigger the population, but this time, use the DBMS_INMEMORY.REPOPULATE
procedure instead of DBMS_INMEMORY.POPULATE. Use FORCE=>FALSE to indicate a
repopulation.
EXEC DBMS_INMEMORY.REPOPULATE('LABUSER', 'SALES1', NULL,
FORCE=>FALSE);

SQL> EXEC DBMS_INMEMORY.REPOPULATE('LABUSER', 'SALES1', NULL, FORCE=>FALSE);


PL/SQL procedure successfully completed.

9. Check the population status. You will notice that the data is still not populated (i.e.
BYTES_NOT_POPULATED is not 0). This is because the REPOPULATE procedure with the
FORCE=>FALSE parameter is for repopulating changed data within the IMCU (not for new
IMCUs).
SELECT SEGMENT_NAME, POPULATE_STATUS, BYTES, BYTES_NOT_POPULATED
FROM V$IM_SEGMENTS WHERE SEGMENT_NAME = 'SALES1';

SQL> SELECT SEGMENT_NAME, POPULATE_STATUS, BYTES, BYTES_NOT_POPULATED


FROM V$IM_SEGMENTS WHERE SEGMENT_NAME = 'SALES1';
2
SEGMENT_NAME
-------------------------------------------------------------------------------POPULATE_
BYTES BYTES_NOT_POPULATED
--------- ---------- ------------------SALES1
COMPLETED
655360
131072

10. Manually trigger the population using DBMS_INMEMORY.REPOPULATE procedure with


2014 Oracle Corporation. All Rights Reserved.

Page 118

Oracle Database In-Memory Workshop

SOFTWARE.HARDWARE.COMPLETE

FORCE=>TRUE. Using FORCE=>TRUE will work the same way as POPULATE, i.e. forces a
population of unpopulated disk extents into IMCUs.
EXEC DBMS_INMEMORY.REPOPULATE('LABUSER', 'SALES1', NULL,
FORCE=>TRUE);

SQL> EXEC DBMS_INMEMORY.REPOPULATE('LABUSER', 'SALES1', NULL, FORCE=>TRUE);


PL/SQL procedure successfully completed.

11. Check the population status. You should now see the new data is populated.
SELECT SEGMENT_NAME, POPULATE_STATUS, BYTES, BYTES_NOT_POPULATED
FROM V$IM_SEGMENTS WHERE SEGMENT_NAME = 'SALES1';
SQL> SELECT SEGMENT_NAME, POPULATE_STATUS, BYTES, BYTES_NOT_POPULATED
FROM V$IM_SEGMENTS WHERE SEGMENT_NAME = 'SALES1';
2
SEGMENT_NAME POPULATE_STATUS BYTES
BYTES_NOT_POPULATED
------------ --------------- ---------- ------------------SALES1
COMPLETED
655360
0

8.1.4.

DATA LOADS SCENARIO 4

In this scenario, you will ALTER the SALES1 table to have a HIGH PRIORITY and then
perform another direct path data load. Observe the column store population in this case.

LAB STEPS
1. Run the following steps in the previous SQL*Plus session connected as LABUSER.
2. Alter SALES1 table to have a In-Memory PRIORITY of HIGH.
ALTER TABLE SALES1 INMEMORY PRIORITY HIGH;
3. Wait until the table gets loaded to the IM Column Store before proceeding. Use the SQL
below to ensure BYTES_NOT_POPULATED is 0.
SELECT SEGMENT_NAME, POPULATE_STATUS, BYTES, BYTES_NOT_POPULATED
FROM V$IM_SEGMENTS WHERE SEGMENT_NAME = 'SALES1';

2014 Oracle Corporation. All Rights Reserved.

Page 119

Oracle Database In-Memory Workshop

SOFTWARE.HARDWARE.COMPLETE

SQL> SELECT SEGMENT_NAME, POPULATE_STATUS, BYTES, BYTES_NOT_POPULATED


FROM V$IM_SEGMENTS WHERE SEGMENT_NAME = 'SALES1';
2
SEGMENT_NAME POPULATE_STATUS BYTES
BYTES_NOT_POPULATED
------------ --------------- ---------- ------------------SALES1
COMPLETED
851968
0

4. Next, load 10000 more rows into SALES1 via a direct path load and commit the changes.
The COMMIT may trigger a repopulation task (not initial population) for the new rows when
a non-default PRIORITY is specified. In fact, the repopulation depends on several other
factors as well, such as the number of rows inserted, the number of times dirty rows are
accessed, and other internal system thresholds, and these factors are all required for
repopulation to start (trickle repopulation is different though).
INSERT /*+APPEND*/ INTO SALES1
SELECT *
FROM SALES
WHERE ROWNUM <=10000;
COMMIT;
5. Check the V$IM_SEGMENTS view and observe the BYTES_NOT_POPULATED column.
COL SEGMENT_NAME FORMAT A20
SELECT SEGMENT_NAME, POPULATE_STATUS, BYTES, BYTES_NOT_POPULATED
FROM V$IM_SEGMENTS WHERE SEGMENT_NAME = 'SALES1';
SEGMENT_NAME
POPULATE_
BYTES BYTES_NOT_POPULATED
-------------------- --------- -------- ------------------SALES1
COMPLETED
786432
131072

6. If you take a sufficiently long pause between Steps 4 and 5, you may see
BYTES_NOT_POPULATED has gone back to 0 as the repopulation task may have finished.
The repopulation is immediately triggered upon COMMIT, as discussed earlier.
7. Check if the repopulation task finished by rerunning the query against V$IM_SEGMENTS.
COL SEGMENT_NAME FORMAT A20
SELECT SEGMENT_NAME, POPULATE_STATUS, BYTES, BYTES_NOT_POPULATED
FROM V$IM_SEGMENTS WHERE SEGMENT_NAME = 'SALES1';

2014 Oracle Corporation. All Rights Reserved.

Page 120

Oracle Database In-Memory Workshop

SOFTWARE.HARDWARE.COMPLETE

SEGMENT_NAME
POPULATE_
BYTES BYTES_NOT_POPULATED
-------------------- --------- -------- ------------------SALES1
COMPLETED 1048576
0

8. Clean up the schema by dropping SALES1.


DROP TABLE SALES1;

8.2.

TRANSACTION PROCESSING

Single row data change operations (DML) execute via the buffer cache (OLTP style changes),
just as they do without Oracle Database In-Memory enabled. If the object undergoing DML
operations is populated in the IM column store, then the changes are reflected in the IM
column store as they occur. The buffer cache and the column store are kept transactionally
consistent via the In-Memory Transaction Manager (the component in charge of
synchronizing the row-format and the column-format stores). All logging is done on the base
table just as it was done before, and no additional logging is needed for the In-Memory Column
store.
For each IMCU in the IM column store, a transaction journal is automatically created and
maintained (see Figure 8.1). When a DML statement changes a row in the object that is
populated into the IM column store, the corresponding entries for that row is marked stale in
the IMCU and a copy of the new version of the row is added to the in-memory transaction
journal. The original entries in the IMCU are not immediately replaced in order to provide read
consistency and maintain data compression. Any transaction executing against this object in
the IM column store that started before the DML occurred, needs to see the original version of
the entries. Read consistency in the IM column store is managed via System Change Numbers
(SCNs) just as it is without Database In-Memory enabled.
When a query with a newer SCN is executed against the object, it will read all of the entries for
the columns in the IMCU except the stale entries. The stale entries will be retrieved either from
the transaction journal or from the base table (buffer cache).

2014 Oracle Corporation. All Rights Reserved.

Page 121

Oracle Database In-Memory Workshop

SOFTWARE.HARDWARE.COMPLETE

Figure 8.1. Each IMCU in the IM column store contains a subset of rows from an object & a
transaction journal

8.2.1.

ABOUT THE WORKLOAD

The workload consists of a mix of read-only queries and a set of DML (bulk loads, inserts,
updates and deletes) transactions, configured to run concurrently against the RTL schema.
The read-only query workload consists of 27 different types of SELECTS, each of varying
degree of complexity involving basic lookups, filters, aggregations, group by operations and
multi-table joins, from all the tables in the RTL schema. You may examine the query workload
by browsing the SQLs contained in the directory
/home/oracle/labs/lesson8/rtl_queries.
The DML workload consists of a mix of bulk inserts, single row inserts, updates and deletes.
The bulk insert workload consists of new rows that will be added to the
DWB_RTL_SLS_RETRN_LINE_ITEM table. The new rows are generated from existing rows but
for new line items therefore mimicking a new sale captured in the line item fact table. The bulk
insert workload will be committed only once, i.e. after the load is complete.
The single row inserts are also generated from existing rows in a similar fashion as the bulk
inserts, with the only difference that when this workload is executed, it executes each insert as
a separate transaction, committing at every step.
The workload generates bulk load and DML transactions with the following counts (this
distribution is configurable):
2014 Oracle Corporation. All Rights Reserved.

Page 122

Oracle Database In-Memory Workshop

SOFTWARE.HARDWARE.COMPLETE

Bulk Loads: 9,000 rows


DML: 1000 rows
o

INSERTS: 70%

UPDATES: 20%

DELETES: 10%

Note: The LABUSER schema is used to store temporary tables that will be built during the
workload setup phase. These tables are used later during the execution phase of the workload
when the workload gets run in the RTL schema.

8.2.2.

DML WORKLOAD SETUP

The workload needs to be setup prior to executing it. The setup process generates temporary
tables that hold new transactions for the DWB_RTL_SLS_RETRN_LINE_ITEM table. The
transactions are generated by selecting existing data from
DWB_RTL_SLS_RETRN_LINE_ITEM and modifying a few of the column attributes. The setup
process also creates temporary tables to hold the execution time of the workload SQLs.
Note: Please be advised that because the workload is running in a VM, the runtimes of the
queries may widely differ in your environment, based on the type of CPU, disk speed, etc.
Remember, the theme of this lab is to demonstrate that data can be loaded and manipulated
without substantial impact to the queries, and not to showcase a performance benchmark.

LAB STEPS
1. Start a new Terminal window and browse to /home/oracle/labs/lesson8 directory.
$> cd /home/oracle/labs/lesson8
2. Run the setup.sh script. This script creates temporary tables in the LABUSER schema
(prefixed with WRKLD_*) that will be used to generate transactions and capture execution
times. Ensure that the script runs successfully by looking at the count of rows inserted
(highlighted in the output below).

2014 Oracle Corporation. All Rights Reserved.

Page 123

Oracle Database In-Memory Workshop

SOFTWARE.HARDWARE.COMPLETE

Note: You may see the DROP TABLE errors when running this script for the first time,
which can be ignored.
$> ./setup.sh

[oracle@db12cvm1 lesson8]$ ./setup.sh


Setting up the workload..
SQL*Plus: Release 12.1.0.2.0 Production on Mon Oct 6 00:57:40 2014
Copyright (c) 1982, 2014, Oracle.

All rights reserved.

SQL> Connected.
SQL> SQL> SQL> SQL> SQL> SQL> SQL>
Session altered.
Elapsed: 00:00:00.00
SQL>
Session altered.
Elapsed: 00:00:00.00
SQL> SQL> DROP TABLE wrkld_tmp PURGE
*
ERROR at line 1:
ORA-00942: table or view does not exist
Elapsed: 00:00:00.03
SQL> DROP TABLE wrkld_keys PURGE
*
ERROR at line 1:
ORA-00942: table or view does not exist
Elapsed: 00:00:00.00
SQL> DROP TABLE wrkld_results PURGE
*
ERROR at line 1:
ORA-00942: table or view does not exist
Elapsed: 00:00:00.00
SQL> DROP TABLE wrkld_rtl_single_inserts PURGE
*
ERROR at line 1:
ORA-00942: table or view does not exist
Elapsed: 00:00:00.00
SQL> DROP TABLE wrkld_rtl_bulk_inserts PURGE
*
ERROR at line 1:
ORA-00942: table or view does not exist

2014 Oracle Corporation. All Rights Reserved.

Page 124

Oracle Database In-Memory Workshop


Elapsed: 00:00:00.01
SQL> SQL>
2
3
Table created.

Elapsed: 00:00:00.06
SQL> SQL>
2
3
Table created.

Elapsed: 00:00:00.01
SQL> SQL>
2
3
Table created.

SOFTWARE.HARDWARE.COMPLETE

Elapsed: 00:00:00.01
SQL> SQL>
2
Table created.
Elapsed: 00:00:00.29
SQL> SQL>
2
Table created.
Elapsed: 00:00:00.04
SQL> SQL>
2
3
10000 rows created.

Elapsed: 00:00:21.85
SQL> SQL>
Commit complete.
Elapsed: 00:00:00.01
SQL> SQL>
2
3
9000 rows updated.
Elapsed: 00:00:00.31
SQL> SQL>
Commit complete.
Elapsed: 00:00:00.00
SQL> SQL>
2
3
700 rows updated.
Elapsed: 00:00:00.08
SQL> SQL>
Commit complete.
Elapsed: 00:00:00.00
SQL> SQL>
2
3
200 rows updated.
Elapsed: 00:00:00.07
SQL> SQL>
Commit complete.
Elapsed: 00:00:00.01
SQL> SQL>
2
3
100 rows updated.
Elapsed: 00:00:00.00
SQL> SQL>
Commit complete.
2014 Oracle Corporation. All Rights Reserved.

Page 125

Oracle Database In-Memory Workshop


Elapsed: 00:00:00.01
SQL> SQL>
2
3
9000 rows created.

SOFTWARE.HARDWARE.COMPLETE

Elapsed: 00:00:05.73
SQL> SQL>
Commit complete.
Elapsed: 00:00:00.00
SQL> Disconnected from Oracle Database 12c Enterprise Edition Release 12.1.0.2.0
- 64bit Production
With the Partitioning, OLAP, Advanced Analytics and Real Application Testing
options
Start Time: Mon Oct 6 00:57:40 CDT 2014
End Time: Mon Oct 6 00:58:08 CDT 2014

3. Next, you need to populate the tables in RTL schema to the IM column store, as these
tables are the ones involved in the workload.
4. In a SQL*Plus session, connect as the RTL user.
CONNECT RTL/rtl
5. Enable all tables in the RTL schema for the IM column store using ALTER TABLE
INMEMORY.
Note: The RTL tables may already be resident in the column store.
ALTER
ALTER
ALTER
ALTER
ALTER

TABLE
TABLE
TABLE
TABLE
TABLE

DWB_RTL_SLS_RETRN_LINE_ITEM INMEMORY;
DWB_RTL_TNDR_LI INMEMORY;
DWB_RTL_TRX INMEMORY;
DWR_ORG_BSNS_UNIT INMEMORY;
DWR_SKU_ITEM INMEMORY;

6. Prior to populating the RTL tables, ensure that there are no other objects loaded into the inmemory area. Use the query below to find the objects that are currently resident in the inmemory area.
COL OWNER FORMAT A15
COL SEGMENT_NAME FORMAT A20
SELECT OWNER, SEGMENT_NAME, INMEMORY_SIZE, POPULATE_STATUS
FROM V$IM_SEGMENTS;

2014 Oracle Corporation. All Rights Reserved.

Page 126

Oracle Database In-Memory Workshop

SOFTWARE.HARDWARE.COMPLETE

SQL> SELECT OWNER, SEGMENT_NAME, INMEMORY_SIZE, POPULATE_STATUS


FROM V$IM_SEGMENTS;
OWNER
SEGMENT_NAME
INMEMORY_SIZE POPULATE_
----------- -------------------- ------------- --------LABUSER
SALES1
1179648 COMPLETED

7. If the above query returns segments owned other than the RTL user, then you need to
disable them to flush them out. Use the below SQL as an example. Substitute
LABUSER.SALES with tables that were output from the previous query.
ALTER TABLE LABUSER.SALES NO INMEMORY;
8. Check the IM column store once again, and ensure that all tables are flushed out, i.e. no
rows should be returned from the below SQL.
COL OWNER FORMAT A15
COL SEGMENT_NAME FORMAT A20
SELECT OWNER, SEGMENT_NAME, INMEMORY_SIZE, POPULATE_STATUS
FROM V$IM_SEGMENTS;
9. Populate the RTL tables by execute the following COUNT(*) queries on each of the tables.
SELECT
SELECT
SELECT
SELECT
SELECT

COUNT(*)
COUNT(*)
COUNT(*)
COUNT(*)
COUNT(*)

FROM
FROM
FROM
FROM
FROM

DWB_RTL_SLS_RETRN_LINE_ITEM;
DWB_RTL_TNDR_LI;
DWB_RTL_TRX;
DWR_ORG_BSNS_UNIT;
DWR_SKU_ITEM;

10. Check if all tables and partitions are completely populated by looking at the
POPULATE_STATUS column of V$IM_SEGMENTS. Wait until all tables get populated before
proceeding to the next lab (i.e. your output should be similar to the highlighted output from
below query).
COL OWNER FORMAT A15
COL SEGMENT_NAME FORMAT A20
SET PAGES 100
SELECT OWNER, SEGMENT_NAME, INMEMORY_SIZE, POPULATE_STATUS
FROM V$IM_SEGMENTS;

SQL> COL OWNER FORMAT A15


2014 Oracle Corporation. All Rights Reserved.

Page 127

Oracle Database In-Memory Workshop

SOFTWARE.HARDWARE.COMPLETE

SQL> COL SEGMENT_NAME FORMAT A20


SQL> SET PAGES 100
SQL> SELECT OWNER, SEGMENT_NAME, INMEMORY_SIZE, POPULATE_STATUS
FROM V$IM_SEGMENTS;
OWNER
----------RTL
RTL
RTL
RTL
RTL
RTL
RTL
RTL
RTL
RTL
RTL

SEGMENT_NAME
INMEMORY_SIZE POPULATE_
-------------------------------- --------DWB_RTL_SLS_RETRN_LINE_ITEM
178520064 COMPLETED
DWR_SKU_ITEM
5373952 COMPLETED
DWB_RTL_TNDR_LI
23265280 COMPLETED
DWB_RTL_TRX
23265280 COMPLETED
DWB_RTL_SLS_RETRN_LINE_ITEM
178520064 COMPLETED
DWR_ORG_BSNS_UNIT
1179648 COMPLETED
DWB_RTL_TNDR_LI
23265280 COMPLETED
DWB_RTL_TRX
23265280 COMPLETED
DWB_RTL_SLS_RETRN_LINE_ITEM
179568640 COMPLETED
DWB_RTL_TNDR_LI
23265280 COMPLETED
DWB_RTL_TRX
23265280 COMPLETED

11 rows selected.

8.2.3.

RUN THE DML WORKLOAD

Now that you have setup the temporary schema objects required to generated transactions
and loaded the RTL tables, its now time to run the different workload scenarios for this lesson.

LAB STEPS
1. All performance comparison tests require a baseline to be established. We will establish a
baseline by executing the 27-query workload without any concurrent DML or bulk loads.
2. The script run_wrkld_rtl_queries.sh will automatically execute the read-only query
workload and record the response time for each query in the new table WRKLD_RESULTS
(in the LABUSER schema). As discussed earlier, the query workload consists of SQL scripts
residing in rtl_queries subdirectory.
3. To establish a baseline, execute run_wrkld_rtl_queries.sh script from the directory
/home/oracle/labs/lesson8. Wait until the script completes successfully before
proceeding to the next step.
cd /home/oracle/labs/lesson8
./run_wrkld_rtl_queries.sh

2014 Oracle Corporation. All Rights Reserved.

Page 128

Oracle Database In-Memory Workshop

SOFTWARE.HARDWARE.COMPLETE

[oracle@db12cvm1 lesson8]$ ./run_wrkld_rtl_queries.sh


Start Time: Mon Oct 6 01:12:28 CDT 2014
End TIme: Mon Oct 6 01:13:30 CDT 2014

4. In a SQL*Plus session, connect as the LABUSER user. You will use this session for the
remainder of this lesson so it will help to keep this session connected.
CONNECT LABUSER/labuser
5. Run the following query to confirm that the response times from the baseline run were
recorded correctly. You should see query runtimes captured only in the BASELINE column.
SET
SET
COL
COL
COL
COL
SET

PAGES 999
LINES 150
BASELINE FORMAT 00.00
WITH_DML FORMAT 00.00
WITH_BULK_LOAD FORMAT 00.00
WITH_ALL FORMAT 00.00
ECHO ON

SELECT S1.RESULT AS BASELINE, S2.RESULT AS WITH_BULK_LOAD,


S3.RESULT AS WITH_DML, S4.RESULT AS WITH_ALL
FROM
(SELECT RESULT, QUERY_NUM FROM WRKLD_RESULTS WHERE STEP_NUM=1)
(SELECT RESULT, QUERY_NUM FROM WRKLD_RESULTS WHERE STEP_NUM=2)
(SELECT RESULT, QUERY_NUM FROM WRKLD_RESULTS WHERE STEP_NUM=3)
(SELECT RESULT, QUERY_NUM FROM WRKLD_RESULTS WHERE STEP_NUM=4)
WHERE S1.QUERY_NUM=S2.QUERY_NUM (+)
AND S1.QUERY_NUM=S3.QUERY_NUM (+)
AND S1.QUERY_NUM=S4.QUERY_NUM (+);

S1,
S2,
S3,
S4

BASELINE WITH_BULK_LOAD WITH_DML WITH_ALL


-------- -------------- -------- -------16.95
00.19
05.97
00.19
06.19
00.32
00.19
00.16
00.13
00.24
00.16
00.35
00.21
00.02
03.75
00.11
2014 Oracle Corporation. All Rights Reserved.

Page 129

Oracle Database In-Memory Workshop

SOFTWARE.HARDWARE.COMPLETE

01.65
00.29
00.03
00.21
00.13
02.96
00.31
00.24
00.21
02.49
37.87
27 rows selected.

6. Now, lets rerun the query workload while we also execute a bulk insert workload (bulk
load) on the DWB_RTL_SLS_RETRN_LINE_ITEM table. The bulk insert will load 9000 rows.
Note: With a bulk load all of the data is inserted into the table in a single transaction (only
one commit). That means no data will be visible to the session doing the queries until the
bulk load completes. This is the typical nature of a bulk load done in a data warehouse or
an operational store.
7. The script run_wrkld_rtl_bulk_load.sh will automatically execute the read-only
query workload, along with the bulk inserts. Similar to the baseline run, the response time
for each query is recorded in the WRKLD_RESULTS table.
8. Run the run_wrkld_rtl_bulk_load.sh script from /home/oracle/labs/lesson8.
./run_wrkld_rtl_bulk_load.sh
9. In the SQL*Plus session, connected as the LABUSER user, run the following query to
select runtimes from the WRKLD_RESULTS table. You should now see the BASELINE and
WITH_BULK_LOAD columns populated.
SET
SET
COL
COL
COL
COL
SET

PAGES 999
LINES 150
BASELINE FORMAT 00.00
WITH_DML FORMAT 00.00
WITH_BULK_LOAD FORMAT 00.00
WITH_ALL FORMAT 00.00
ECHO ON

SELECT S1.RESULT AS BASELINE, S2.RESULT AS WITH_BULK_LOAD,


S3.RESULT AS WITH_DML, S4.RESULT AS WITH_ALL
2014 Oracle Corporation. All Rights Reserved.

Page 130

Oracle Database In-Memory Workshop

FROM
(SELECT RESULT, QUERY_NUM FROM WRKLD_RESULTS
(SELECT RESULT, QUERY_NUM FROM WRKLD_RESULTS
(SELECT RESULT, QUERY_NUM FROM WRKLD_RESULTS
(SELECT RESULT, QUERY_NUM FROM WRKLD_RESULTS
WHERE S1.QUERY_NUM=S2.QUERY_NUM (+)
AND S1.QUERY_NUM=S3.QUERY_NUM (+)
AND S1.QUERY_NUM=S4.QUERY_NUM (+);

SOFTWARE.HARDWARE.COMPLETE

WHERE
WHERE
WHERE
WHERE

STEP_NUM=1)
STEP_NUM=2)
STEP_NUM=3)
STEP_NUM=4)

S1,
S2,
S3,
S4

BASELINE WITH_BULK_LOAD WITH_DML WITH_ALL


-------- -------------- -------- -------16.95
16.49
00.19
00.60
05.97
05.80
00.19
00.28
06.19
06.28
00.32
00.27
00.19
00.59
00.16
00.38
00.13
00.26
00.24
00.44
00.16
00.79
00.35
00.55
00.21
00.73
00.02
00.02
03.75
03.44
00.11
00.33
01.65
01.71
00.29
00.36
00.03
00.03
00.21
00.36
00.13
00.11
02.96
03.03
00.31
00.38
00.24
00.46
02.49
03.13
00.21
00.21
37.87
34.28
27 rows selected.

10. In the next part of our comparison, you will rerun the query workload while also execute a
set of more OLTP-style DML commands (INSERTS, DELETES, UPDATES). There are a
total of 1000 DML commands in the workload (700 inserts, 200 updates, and 100 deletes),
running a variety of DML against DWB_RTL_SLS_RETRN_LINE_ITEM. Each command
commits immediately and none of the transactions are rolled back.
Note: As each DML command commits immediately, the session executing the queries will
see the information immediately after the commit.
2014 Oracle Corporation. All Rights Reserved.

Page 131

Oracle Database In-Memory Workshop

SOFTWARE.HARDWARE.COMPLETE

11. To kick off both the query workload and the OLTP style DML, run the
run_wrkld_rtl_dml.sh script from /home/oracle/labs/lesson8.
./run_wrkld_rtl_dml.sh
12. Connected as the LABUSER, run the following query to confirm the response times were
correctly recorded in the WRKLD_RESULTS table. You should now see the BASELINE,
WITH_BULK_LOAD and WITH_DML columns populated.
SET
SET
COL
COL
COL
COL
SET

PAGES 999
LINES 150
BASELINE FORMAT 00.00
WITH_DML FORMAT 00.00
WITH_BULK_LOAD FORMAT 00.00
WITH_ALL FORMAT 00.00
ECHO ON

SELECT S1.RESULT AS BASELINE, S2.RESULT AS WITH_BULK_LOAD,


S3.RESULT AS WITH_DML, S4.RESULT AS WITH_ALL
FROM
(SELECT RESULT, QUERY_NUM FROM WRKLD_RESULTS WHERE STEP_NUM=1)
(SELECT RESULT, QUERY_NUM FROM WRKLD_RESULTS WHERE STEP_NUM=2)
(SELECT RESULT, QUERY_NUM FROM WRKLD_RESULTS WHERE STEP_NUM=3)
(SELECT RESULT, QUERY_NUM FROM WRKLD_RESULTS WHERE STEP_NUM=4)
WHERE S1.QUERY_NUM=S2.QUERY_NUM (+)
AND S1.QUERY_NUM=S3.QUERY_NUM (+)
AND S1.QUERY_NUM=S4.QUERY_NUM (+);

S1,
S2,
S3,
S4

BASELINE WITH_BULK_LOAD WITH_DML WITH_ALL


-------- -------------- -------- -------16.95
16.49
16.60
00.19
00.60
00.47
05.97
05.80
05.72
00.19
00.28
00.29
06.19
06.28
07.40
00.32
00.27
00.29
00.19
00.59
00.43
00.16
00.38
00.39
00.13
00.26
00.48
00.24
00.44
00.45
00.16
00.79
00.40
00.35
00.55
00.54
00.21
00.73
00.44
00.02
00.02
00.01
03.75
03.44
03.49
00.11
00.33
00.33
01.65
01.71
01.72
00.29
00.36
00.41
00.03
00.03
00.02
2014 Oracle Corporation. All Rights Reserved.

Page 132

Oracle Database In-Memory Workshop


00.21
00.13
02.96
00.31
00.24
00.21
02.49
37.87

00.36
00.11
03.03
00.38
00.46
00.21
03.13
34.28

SOFTWARE.HARDWARE.COMPLETE

00.37
00.11
02.90
00.39
00.44
00.20
02.49
36.63

27 rows selected.

13. Finally, run all the three workloads (bulk loads, dml and query) simultaneously using
run_wrkld_rtl_all.sh script. This allows you to compare the response time for each
query across the three-performance runs; baseline, bulk loads, and single record DML.
./run_wrkld_rtl_all.sh
14. Run the following query connected as the LABUSER and confirm the response times
recorded in the WRKLD_RESULTS table.
SET
SET
COL
COL
COL
COL
SET

PAGES 999
LINES 150
BASELINE FORMAT 00.00
WITH_DML FORMAT 00.00
WITH_BULK_LOAD FORMAT 00.00
WITH_ALL FORMAT 00.00
ECHO ON

SELECT S1.RESULT AS BASELINE, S2.RESULT AS WITH_BULK_LOAD,


S3.RESULT AS WITH_DML, S4.RESULT AS WITH_ALL
FROM
(SELECT RESULT, QUERY_NUM FROM WRKLD_RESULTS WHERE STEP_NUM=1)
(SELECT RESULT, QUERY_NUM FROM WRKLD_RESULTS WHERE STEP_NUM=2)
(SELECT RESULT, QUERY_NUM FROM WRKLD_RESULTS WHERE STEP_NUM=3)
(SELECT RESULT, QUERY_NUM FROM WRKLD_RESULTS WHERE STEP_NUM=4)
WHERE S1.QUERY_NUM=S2.QUERY_NUM (+)
AND S1.QUERY_NUM=S3.QUERY_NUM (+)
AND S1.QUERY_NUM=S4.QUERY_NUM (+);

S1,
S2,
S3,
S4

BASELINE WITH_BULK_LOAD WITH_DML WITH_ALL


-------- -------------- -------- -------00.13
00.26
00.48
00.50
00.16
00.79
00.40
00.68
00.19
00.60
00.47
00.43
00.19
00.59
00.43
00.45
00.21
00.73
00.44
00.51
02.49
03.13
02.49
00.47
00.29
00.36
00.41
00.38
2014 Oracle Corporation. All Rights Reserved.

Page 133

Oracle Database In-Memory Workshop


00.02
00.13
06.19
00.21
03.75
02.96
00.03
05.97
00.21
01.65
00.32
00.11
00.24
00.19
00.31
00.16
00.35
00.24
16.95
37.87

00.02
00.11
06.28
00.21
03.44
03.03
00.03
05.80
00.36
01.71
00.27
00.33
00.46
00.28
00.38
00.38
00.55
00.44
16.49
34.28

00.01
00.11
07.40
00.20
03.49
02.90
00.02
05.72
00.37
01.72
00.29
00.33
00.44
00.29
00.39
00.39
00.54
00.45
16.60
36.63

SOFTWARE.HARDWARE.COMPLETE

00.01
00.10
06.30
00.19
03.48
02.86
00.01
05.77
00.36
01.77
00.28
00.33
00.46
00.28
00.40
00.22
00.64
00.79
09.90
29.82

27 rows selected.

15. What is your observation from these runs? Do you see a sizeable degradation in
performance when compared to the baseline run after adding the DML workload, or they
are all about the same? As mentioned earlier, there will be subtle variations but that is
mainly because your VM environment may have different performance characteristics than
others, and may be a bit unpredictable at times.

8.3.

SUMMARY

One of the most commonly asked questions about the new In-Memory Column Store is the
impact of DML to the query workload utilizing the IM column store. This lesson demonstrated
just how little impact DML has on the performance of the IM column store.
Remember, new data added as part of a bulk load operation is only visible after the session
performing the DML commits. If the bulk load is done using a direct path operation, the data is
written directly to disk and bypasses the buffer cache and the IM column store. The next query
that accesses that data will trigger the newly inserted data to be populated into the column
store, unless the table is configured with a non-default PRIORITY.
Single row change done via the buffer cache (OLTP style changes), are typically committed
immediately and are reflected in the column store as they occur. The buffer cache and the
column store are kept transactionally consistent.
2014 Oracle Corporation. All Rights Reserved.

Page 134

Oracle Database In-Memory Workshop

9.

SOFTWARE.HARDWARE.COMPLETE

DATA PUMP AND THE IM COLUMN STORE

Data Pump provides the following two options for importing objects and setting up their inmemory attributes at import time:
Importing In-Memory Database Objects
Overriding the In-Memory Clause of Database Objects

9.1.

IMPORTING IN-MEMORY DATABASE OBJECTS

You can import database objects that were enabled for the IM column store using IMPDPs
TRANSFORM clause with the INMEMORY option. As you may already know, the TRANSFORM
clause enables you to alter object creation DDL at the time of import.
When the TRANSFORM=INMEMORY:Y option is specified (the default value) on import, then
Data Pump keeps the IM column store clause for all objects that have one. When those
objects are recreated at import time, Data Pump generates the IM column store clause that
matches the setting for those objects at export time.
When the TRANSFORM=INMEMORY:N option is specified, Data Pump drops the IM column
store clause from all objects that have one.
If there is no IM column store clause for an object that is stored in a tablespace, then the object
may inherit the IM column store clause from the tablespace if clause is specified at the
tablespace level. Therefore, if you are migrating a database and want the new database to use
IM column store features, you could pre-create the tablespaces with the appropriate IM column
store clause and then use TRANSFORM=INMEMORY:N on the import command. The object
would then inherit the IM column store clause from the new pre-created tablespace.
Note: The INMEMORY transform is available only in Oracle Database 12c Release 1 (12.1.0.2)
or later.

LAB STEPS
1. Connect using SQL*Plus as LABUSER.

2014 Oracle Corporation. All Rights Reserved.

Page 135

Oracle Database In-Memory Workshop

SOFTWARE.HARDWARE.COMPLETE

sqlplus LABUSER/labuser
2. Alter the table COSTS and enable it for INMEMORY with default compression and PRIORITY
HIGH.
ALTER TABLE COSTS INMEMORY PRIORITY HIGH;
3. Check if the In-Memory attributes are correctly set, prior to exporting the table. The table
should be set with in-memory compression option of FOR QUERY LOW, and in-memory
priority of HIGH.
SELECT TABLE_NAME, INMEMORY_COMPRESSION, INMEMORY_PRIORITY,
INMEMORY_DISTRIBUTE
FROM DBA_TABLES
WHERE TABLE_NAME = 'COSTS';
4. Open another terminal session. At the OS prompt, export the COSTS table using data pump
export EXPDP.
expdp LABUSER/labuser tables=COSTS dumpfile=costs.dmp
oracle@db12cvm1 Desktop]$ expdp LABUSER/labuser tables=COSTS dumpfile=costs.dmp
Export: Release 12.1.0.2.0 - Production on Tue Sep 30 10:48:09 2014
Copyright (c) 1982, 2014, Oracle and/or its affiliates.

All rights reserved.

Connected to: Oracle Database 12c Enterprise Edition Release 12.1.0.2.0 - 64bit
Production
With the Partitioning, OLAP, Advanced Analytics and Real Application Testing
options
Starting "LABUSER"."SYS_EXPORT_TABLE_01": LABUSER/******** tables=COSTS
dumpfile=costs.dmp
Estimate in progress using BLOCKS method...
Processing object type TABLE_EXPORT/TABLE/TABLE_DATA
Total estimation using BLOCKS method: 256 KB
Processing object type TABLE_EXPORT/TABLE/TABLE
Processing object type TABLE_EXPORT/TABLE/STATISTICS/TABLE_STATISTICS
Processing object type TABLE_EXPORT/TABLE/STATISTICS/MARKER
. . exported "LABUSER"."COSTS"
214.6 KB
2000 rows
Master table "LABUSER"."SYS_EXPORT_TABLE_01" successfully loaded/unloaded
******************************************************************************
Dump file set for LABUSER.SYS_EXPORT_TABLE_01 is:
/u01/app/oracle/admin/orcl/dpdump/costs.dmp
Job "LABUSER"."SYS_EXPORT_TABLE_01" successfully completed at Tue Sep 30
10:48:37 2014 elapsed 0 00:00:23

5. Verify the creation of dump file.


2014 Oracle Corporation. All Rights Reserved.

Page 136

Oracle Database In-Memory Workshop

SOFTWARE.HARDWARE.COMPLETE

ls -l $ORACLE_BASE/admin/orcl/dpdump/costs.dmp

[oracle@db12cvm1 Desktop]$ ls -l $ORACLE_BASE/admin/orcl/dpdump/costs.dmp


-rw-r-----. 1 oracle oinstall 380928 Sep 30 10:48
/u01/app/oracle/admin/orcl/dpdump/costs.dmp

6. From the SQL*Plus session connected as the LABUSER, drop the COSTS table.
DROP TABLE COSTS;
7. Using IMPDP, import the COSTS table back using TRANSFORM:INMEMORY=Y clause. This
clause will keep all the in-memory attributes of the table that were present at export time.
Note that the default value of INMEMORY is Y so this example is behavior of this clause is
the same as not specifying the clause. Run the following command at the OS prompt.
impdp LABUSER/labuser DUMPFILE=costs.dmp TRANSFORM=INMEMORY:Y

[oracle@db12cvm1 dpdump]$ impdp labuser/labuser DUMPFILE=costs.dmp


TRANSFORM=INMEMORY:Y
Import: Release 12.1.0.2.0 - Production on Sun Nov 9 09:48:16 2014
Copyright (c) 1982, 2014, Oracle and/or its affiliates.

All rights reserved.

Connected to: Oracle Database 12c Enterprise Edition Release 12.1.0.2.0 - 64bit
Production
With the Partitioning, OLAP, Advanced Analytics and Real Application Testing
options
Master table "LABUSER"."SYS_IMPORT_FULL_01" successfully loaded/unloaded
Starting "LABUSER"."SYS_IMPORT_FULL_01": labuser/******** DUMPFILE=costs.dmp
Processing object type TABLE_EXPORT/TABLE/TABLE
Processing object type TABLE_EXPORT/TABLE/TABLE_DATA
. . imported "LABUSER"."COSTS"
2.420 MB
82112 rows
Processing object type TABLE_EXPORT/TABLE/CONSTRAINT/REF_CONSTRAINT
Processing object type TABLE_EXPORT/TABLE/STATISTICS/TABLE_STATISTICS
Processing object type TABLE_EXPORT/TABLE/STATISTICS/MARKER
Job "LABUSER"."SYS_IMPORT_FULL_01" successfully completed at Sun Nov 9 09:48:29
2014 elapsed 0 00:00:12

8. From the SQL*Plus session connected as the LABUSER, check the COSTS table has been
imported with the same attributes as they existed prior to its export, i.e. compression of FOR
QUERY LOW, and PRIORITY of HIGH.
SELECT TABLE_NAME, INMEMORY_COMPRESSION, INMEMORY_PRIORITY,
INMEMORY_DISTRIBUTE
2014 Oracle Corporation. All Rights Reserved.

Page 137

Oracle Database In-Memory Workshop

SOFTWARE.HARDWARE.COMPLETE

FROM DBA_TABLES
WHERE TABLE_NAME = 'COSTS';
9. Drop the COSTS table again.
DROP TABLE COSTS PURGE;
10. Import the COSTS table back using TRANSFORM:INMEMORY=N clause. This clause will not
apply the In-Memory clause while creating the table at import time.
impdp LABUSER/labuser DUMPFILE=costs.dmp TRANSFORM=INMEMORY:N
11. From the labuser SQL*Plus session, check the tables in-memory attributes once again
and verify that they are not set as per the import transform clause.
SELECT TABLE_NAME, INMEMORY_COMPRESSION, INMEMORY_PRIORITY,
INMEMORY_DISTRIBUTE
FROM DBA_TABLES
WHERE TABLE_NAME = 'COSTS';
12. Drop the COSTS table again.
DROP TABLE COSTS PURGE;
13. Modify the LAB_DATA tablespace default in-memory attributes as follows:
ALTER TABLESPACE LAB_DATA DEFAULT INMEMORY;
14. Import the COSTS table back using TRANSFORM:INMEMORY=N clause. As you know now,
this clause will not apply the tables in-memory clause while creating the table at import
time.
impdp LABUSER/labuser DUMPFILE=costs.dmp TRANSFORM=INMEMORY:N
15. From the labuser SQL*Plus session, check COSTS in-memory attributes. As you would
observe, the attributes are inherited from the tablespace attributes.
SELECT TABLE_NAME, INMEMORY_COMPRESSION, INMEMORY_PRIORITY,
INMEMORY_DISTRIBUTE
FROM DBA_TABLES
WHERE TABLE_NAME = 'COSTS';

2014 Oracle Corporation. All Rights Reserved.

Page 138

Oracle Database In-Memory Workshop

SOFTWARE.HARDWARE.COMPLETE

16. This feature is quite useful for migration purposes where you like to control the attributes at
the destination tablespace level, instead of altering individual tables in-memory clauses.

9.2.

OVERRIDING THE IN-MEMORY CLAUSE OF DATABASE OBJECTS

You can also use the TRANSFORM=INMEMORY_CLAUSE:string option to override the IM


column store clause for a database object in the dump file during import. For example, you can
use this option to change the IM column store compression for a database object being
imported. Data Pump uses the contents of the string as the INMEMORY_CLAUSE for all objects
being imported that have an IM column store clause in their DDL.
Note: The INMEMORY_CLAUSE transform is available only in Oracle Database 12c Release 1
(12.1.0.2) or later.

LAB STEPS
1. Connect using SQL*Plus as LABUSER.
sqlplus LABUSER/labuser
2. Drop the COSTS table.
DROP TABLE COSTS PURGE;
3. Import the COSTS table using TRANSFORM:INMEMORY_CLAUSE:NO INMEMORY clause.
This clause will alter the in-memory clause of COSTS table and changes it to NO
INMEMORY, which is quite useful for overriding the objects in-memory clause that existed at
export time.
impdp LABUSER/labuser DUMPFILE=costs.dmp TRANSFORM=
INMEMORY_CLAUSE:\"NO INMEMORY\"
4. From the labusers SQL*Plus session, check the COSTS table attributes. The table should
be a NO INMEMORY table.
SELECT TABLE_NAME, INMEMORY_COMPRESSION, INMEMORY_PRIORITY,
INMEMORY_DISTRIBUTE
FROM DBA_TABLES
WHERE TABLE_NAME = 'COSTS';
2014 Oracle Corporation. All Rights Reserved.

Page 139

Oracle Database In-Memory Workshop

SOFTWARE.HARDWARE.COMPLETE

5. Drop the COSTS table.


DROP TABLE COSTS PURGE;
6. Import the COSTS table again with explicit INMEMORY attributes such as compression of
CAPACITY HIGH and PRIORITY of MEDIUM, using TRANSFORM:INMEMORY_CLAUSE to
explicitly set these parameters.
impdp LABUSER/labuser DUMPFILE=costs.dmp TRANSFORM=INMEMORY_CLAUSE:
\"INMEMORY MEMCOMPRESS FOR CAPACITY HIGH PRIORITY MEDIUM\"
7. Check the table has been reimported as an INMEMORY table with the desired attributes.
SELECT TABLE_NAME, INMEMORY_COMPRESSION, INMEMORY_PRIORITY,
INMEMORY_DISTRIBUTE
FROM DBA_TABLES
WHERE TABLE_NAME = 'COSTS';

9.3.

SUMMARY

We have demonstrated yet another useful feature for the in-memory option, which is the ability
of Data Pump to manipulate the in-memory attributes at import time. This feature comes very
handy for moving/migrating tables and enabling them for in-memory, either on an individual
basis or in bulk.

2014 Oracle Corporation. All Rights Reserved.

Page 140

Das könnte Ihnen auch gefallen