IMO的查询优化三大特性:

  • 列式存储索引(In-Memory Storage Index)
  • 列式存储的联立(In-Memory Join)
  • 列式存储的聚合( In-Memory Aggregation)

In-Memory Storage Index:

  • 查询V$IM_COL_CU视图,可以查看到IMCU的具体状态。
  • 可以看到在IMCU的数据字典里记录了其最小值、最大值、长度条目数等信息。
SQL> select objd, tsn, length, dictionary_entries entries,
  2    minimum_value minval, maximum_value maxval
  3    from v$im_col_cu;
OBJD  TSN LENGTH   ENTRIES MINVAL         MAXVAL
----- --- -------- ------- -------------- ---------------
92937   6  6648708  533688 C40C365A21     C50A082A2F0A
92937   6   744758     951 31             373030303137
……
92937   6      984       3 3031           3032
92937   6  2303894  157580 786E0C0E021019 78950A0F0A3601
  • IMCU会记录这些内容,是因为Oracle在数据加载时会自动创建各个列的列式索引,并会自动维护,这也是前言实例中为什么列式存储性能会提升600多倍的关键所在。
  • 列式索引的存在,就避免了传统索引的创建,可以不必创建任何传统索引,在谓词过滤查询过程中,同样获得较大优势,也充分避免DML操作的索引维护成本。

12cIMO_10

In-Memory Join:

  • 在IMO列式存储中,当发生表和表的联立时,引进了布隆过滤器(Bloom Filters)。
  • 当两个表发生联立的时候,特别是一个小表对一个大表发生哈希联立(Hash Join)的时候, Bloom Filters 的优势就非常明显了。
  • 如下执行计划所示,其中DATE_DIM为维度表(小表),LINEORDER为事实表(大表)。

12cIMO_11

IMO联立查询优化案例:

12cIMO_12

--二大表有条件:

SQL> select count(x.test_id)
  2    from alex.alex_test        t,
  3         alex.alex_sales       x
  4   where t.test_id = x.test_id
  5   and x.test_id like '11%';
 
二大表有条件内存扫描:
--------------------------------------------------------------------
| Id  | Operation                     | Name                       |
--------------------------------------------------------------------
|   0 | SELECT STATEMENT              |                            |
|   1 |  SORT AGGREGATE               |                            |
|*  2 |   HASH JOIN                   |                            |
|   3 |    JOIN FILTER CREATE         | :BF0000                    |
|*  4 |     TABLE ACCESS INMEMORY FULL| ALEX_SALES                 |
|   5 |    JOIN FILTER USE            | :BF0000                    |
|*  6 |     TABLE ACCESS INMEMORY FULL| ALEX_TEST                  |
--------------------------------------------------------------------

In-Memory Aggregation :

  • 维度表(小表)与事实表(大表)的聚合计算在数据仓库的应用中是最为常见的,IMO基于SIMD矢量处理特点对列式存储的聚合计算也做了相对程度的优化。
  • 如下是一个三个表的IM聚合过程,Stores、Products为维度表,Sales为事实表。
  • 事实表的大小至少为维度的10倍,随着维度越多聚合越复杂,该方法的效率将越高。

12cIMO_13

1.IM内存扫描表Stores和Products,根据谓词过滤出结果。
2.两个表分布生成一个新的数据结构“Key Vector”,有些类似于Bloom Filter,但更加优化。
3.根据各维度的Key Vector,在PGA中生成一个新的二维矢量数据的数据结构(In-Memory Accumulator),也可以成为临时表。
4.应用各维度的Key Vector,IM扫描表Sales,并与临时表进行哈希联立,输出最终结果。

IMO聚合查询优化案例:

12cIMO_14

--3表星型聚合

SQL> SELECT o.org_id, c.cy_id, SUM(assigned_task_id)
  2    FROM tmrlifedata.ntl_org_id                 o,
  3         tmrlifedata.ntl_created_by             c,
  4         tmrlifedata.ntl_assigned_task_inactive t
  5   WHERE t.assigned_org_id = o.assigned_org_id
  6     AND t.created_by = c.created_by
  7     AND o.assigned_org_id like '1011%'
  8     AND c.created_by like 'Z%'
  9   GROUP BY o.org_id, c.cy_id;
--------------------------------------------------------------------------
| Id  | Operation                           | Name                       |
--------------------------------------------------------------------------
|   0 | SELECT STATEMENT                    |                            |
|   1 |  TEMP TABLE TRANSFORMATION          |                            |  第一阶段
|   2 |   LOAD AS SELECT                    | SYS_TEMP_0FD9D66E7_9322468|
|   3 |    VECTOR GROUP BY                  |                            |
|   4 |     KEY VECTOR CREATE BUFFERED      | :KV0000                    |
|   5 |      TABLE ACCESS INMEMORY FULL     | NTL_ORG_ID                 |
|   6 |   LOAD AS SELECT                    | SYS_TEMP_0FD9D66E8_9322468|
|   7 |    VECTOR GROUP BY                  |                            |
|   8 |     KEY VECTOR CREATE BUFFERED      | :KV0001                    |
|   9 |      TABLE ACCESS INMEMORY FULL     | NTL_CREATED_BY             |
|  10 |   HASH GROUP BY                     |                            |  第二阶段
|* 11 |    HASH JOIN                        |                            |
|* 12 |     TABLE ACCESS FULL               | SYS_TEMP_0FD9D66E7_9322468 |
|* 13 |     HASH JOIN                       |                            |
|  14 |      TABLE ACCESS FULL              | SYS_TEMP_0FD9D66E8_9322468 |
|  15 |      VIEW                           | VW_VT_1B35BA0F             |
|  16 |       VECTOR GROUP BY               |                            |
|  17 |        HASH GROUP BY                |                            |
|  18 |         KEY VECTOR USE              | :KV0001                    |
|  19 |          KEY VECTOR USE             | :KV0000                    |
|* 20 |           TABLE ACCESS INMEMORY FULL| NTL_ASSIGNED_TASK_INACTIVE |
--------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
   5 - inmemory(""O"".""ASSIGNED_ORG_ID"" LIKE '1011%')
       filter(""O"".""ASSIGNED_ORG_ID"" LIKE '1011%')
   9 - inmemory(""C"".""CREATED_BY"" LIKE 'Z%')
       filter(""C"".""CREATED_BY"" LIKE 'Z%')
  11 - access(""ITEM_8""=INTERNAL_FUNCTION(""C0"") AND ""ITEM_9""=""C2"")
  12 - filter(""C2"" IS NOT NULL)
  13 - access(""ITEM_10""=INTERNAL_FUNCTION(""C0"") AND ""ITEM_11""=""C2"")
  20 - inmemory(""T"".""CREATED_BY"" LIKE 'Z%' AND ""T"".""ASSIGNED_ORG_ID"" LIKE '1011%' AND
              SYS_OP_KEY_VECTOR_FILTER(""T"".""CREATED_BY"",:KV0001) AND
              SYS_OP_KEY_VECTOR_FILTER(""T"".""ASSIGNED_ORG_ID"",:KV0000))
       filter(""T"".""CREATED_BY"" LIKE 'Z%' AND ""T"".""ASSIGNED_ORG_ID"" LIKE '1011%' AND
              SYS_OP_KEY_VECTOR_FILTER(""T"".""CREATED_BY"",:KV0001) AND
              SYS_OP_KEY_VECTOR_FILTER(""T"".""ASSIGNED_ORG_ID"",:KV0000))
Trackback

2 comments untill now

  1. Hi ,
    我想模拟VECTOR GROUP BY 这个执行计划。
    但是手里没有星型模型的结构以及数据,看到你的文章,觉得很不错。
    想借用这个模型。能否将这几张表涉及的数据发下呢?

    tmrlifedata.ntl_org_id o,
    tmrlifedata.ntl_created_by c,
    tmrlifedata.ntl_assigned_task_inactive

    谢谢!

  2. 麻袋爸爸 @ 2016-10-12 17:23

    这个数据量是非常大的,无法发送,还是需要你自己写程序模拟的。

Add your comment now

切换到手机版