In-Memory Expressions (IM expressions) provide the ability to materialize simple expressions and store them in the In-Memory column store (IM column store) so that they only have to be calculated once, not each time they are accessed. They are also treated like any other column in the IM column store so the database can scan and filter those columns and take advantage of all Database In-Memory query optimizations like SIMD vector processing and IM storage indexes. The Database In-Memory Guide defines an In-Memory Expression as “… a combination of one or more values, operators, and SQL or PL/SQL functions (DETERMINISTIC only) that resolve to a value.” I often tell people when I’m presenting the feature that “the fastest way to do something is to not do it at all”[1], but the next fastest way to do something is to do it only once. I think that’s the easiest way to think about In-Memory Expressions.
There are actually two types of IM expressions, a user-defined In-Memory virtual column (IM virtual column) that meets the requirements of an IM expression, and automatically detected IM expressions which are stored as a hidden virtual column when captured. The automatically detected IM expressions are captured in the new Expression Statistics Store (ESS). IM expressions are fully documented in the In-Memory Guide so I’m not going to repeat that documentation here. Instead, let’s take a look at what an IM expression is, how to create them, and why IM expressions are one of the high-performance features of Database In-Memory. In this post, we will look at how to create user-defined IM virtual columns and how they can significantly improve query performance. In the next post, we will explore automatically detected IM expressions and the details of how they work.
Let’s start with an example. In our other blog posts, and in our Hands On Labs, we use a modified Star Schema Benchmark (SSB) schema. Many of the queries that we use have expressions in them. The following is an example:
SELECT lo_shipmode, SUM(lo_ordtotalprice), SUM(lo_ordtotalprice - (lo_ordtotalprice*(lo_discount/100)) + lo_tax) discount_price FROM LINEORDER GROUP BY lo_shipmode ORDER BY lo_shipmode;
The following shows how the query ran on my test system:

Notice that the query ran in 2.69 seconds. The execution plan shows in-memory access:

And the session statistics confirm that we accessed the IM column store:

Notice the following expression in the query:
(lo_ordtotalprice - (lo_ordtotalprice*(lo_discount/100)) + lo_tax)
This expression is simply an arithmetic expression to find the total price charged with discount and tax included, and meets our criteria that we defined at the beginning of the post. We will create a virtual column and re-populate the LINEORDER table to see what difference it makes.
To start we need to check a couple of things. To make sure that we populate virtual columns in the IM column store we need to ensure that the initialization parameter INMEMORY_VIRTUAL_COLUMNS is set to ENABLE or MANUAL. The default is MANUAL which means that you must explicitly set the virtual columns as INMEMORY enabled. In this test environment I have set it to ENABLE to automatically populate any virtual columns in tables we populate into the IM column store:

Next, we will add a virtual column to the LINEORDER table for the expression we identified above and re-populate the table:

We can verify that the LINEORDER table has been fully populated by querying the V$IM_SEGMENTS view:

Now let’s re-run our query and see if there is any difference:

Notice that now the query runs in only 1.30 seconds! The query ran in 2.69 seconds without the IM expression. The session statistics show that we accessed IM expressions:

Notice the statistics that start with “IM scan EU …”. IM expressions are stored in the IM column store in In-Memory Expression Units (IMEUs) rather than IMCUs, and the statistics for accessing IM expressions all show “EU” for “Expression Unit”.
This simple example shows that even relatively simple expressions can be computationally expensive, and the more frequently they are executed the more savings in CPU resources IM expressions will provide. There’s much more to IM expressions and in the next post we will explore automatically detected IM expressions, and then in the final post we will take a look at some of the internal details of IM expressions.
Original publish date: August 16, 2017
[1] I attribute this to Cary Millsap since he was the first person I heard say this phrase in describing Oracle performance.
