Oracle ---- Star Transformation

今天講一個小衆Case,Oracle數據庫的「Star Transformation」。數據庫

根據關係數據庫的範式理論,表在設計過程當中會盡可能下降耦合和冗餘。
因而,大多數的數據庫都是這樣設計的。緩存

例:
在一個銷售系統中,通常都會涉及到這樣幾種數據:產品,分類,廠家,賣家,買家等等。session

下面是表設計:數據庫設計

產品表:產品ID,產品名,價格。
分類表:分類ID,分類名。
廠家表:廠家ID,廠家名。
賣家表:賣家ID,賣家名。
買家表:買家ID,買家名。
銷售記錄表:時間,產品ID,分類ID,廠家ID,賣家ID,買家ID,其餘。

使用上面的數據庫設計,基本能夠知足銷售數據的快速記錄,更新等平常處理。
可是,隨着銷售記錄的增長,作下面的銷售彙總報表的時候就會很是慢,由於報表是須要把銷售記錄的各類ID轉換成實際名字給人看的。優化

Select 產品名, sum(價格)
  from 銷售記錄表 t1, 產品表 t2, 分類表 t3, 廠家表 t4, 賣家表 t5, 買家表 t6
where t1.產品ID = t2.產品ID
   and t1.分類ID = t3.分類ID
   and t1.廠家ID = t4.廠家ID
   and t1.賣家ID = t5.賣家ID
   and t1.買家ID = t6.買家ID
   and t2.產品名 = <aaaa>
   and t3.分類名 = <bbbb>
   and t4.廠家名 = <cccc>
   and t5.賣家名 = <dddd>
   and t6.買家名 = <eeee>;

如何解決這個問題呢?
聰明的ORACLE工程師設計了「Star Schema」和「Star Transformation」。spa

首先,什麼是「Star Schema」呢?
上面的例子裏,咱們能夠發如今全部的表中,只有「銷售記錄表」一個「事實表」(Fact Table)。其餘的表都只是"參照表"(Dimension Table)。結構能夠用下面的圖表示。設計

image.png

這就是一個典型的「Star Schema」。code

那什麼又是「Star Transformation」呢?orm

「Star Transformation」是ORACLE爲了解決上面問題,結合ORACLE數據庫特有的「Bitmap」索引而做出的優化。索引

「Star Transformation」是如何實現的呢?

  1. 在「Fact Table」的檢索列上創建Bitmap索引。
  2. 經過檢索列上的Bitmap索引操做( BITMAP AND/OR)拿到「Fact Table」的RowID,從而避免」FULL SCAN「。

如今我用」Example Schemas「的幾個表來演示一下。

  1. 取得」Star Transformation「沒有啓用時的執行計劃。

    SQL> show parameter star_transformation_enabled
    
       NAME                                 TYPE                              VALUE
       ------------------------------------ --------------------------------- ------------------------------
       star_transformation_enabled          string                            FALSE
    
       SQL> set autot on
       SQL> set autot traceonly exp
       SQL> set lin 180 pages 9999
       SQL> r
         1  SELECT c.cust_city,
         2   t.calendar_quarter_desc,
         3   SUM(s.amount_sold) sales_amount
         4  FROM sh.sales s,
         5   sh.times t,
         6   sh.customers c,
         7   sh.channels ch
         8  WHERE s.time_id = t.time_id
         9  AND s.cust_id = c.cust_id
       10  AND s.channel_id = ch.channel_id
       11  AND c.cust_state_province = 'CA'
       12  AND ch.channel_desc = 'Internet'
       13  AND t.calendar_quarter_desc IN ('1999-01','1999-02')
       14* GROUP BY c.cust_city, t.calendar_quarter_desc
    
       実行計畫
       ----------------------------------------------------------
       Plan hash value: 1865285285 
       ------------------------------------------------------------------------------------------------------------
       | Id  | Operation                      | Name      | Rows  | Bytes | Cost (%CPU)| Time     | Pstart| Pstop | ------------------------------------------------------------------------------------------------------------
       |   0 | SELECT STATEMENT               |           |   405 | 30780 |   955   (2)| 00:00:12 |       |       |
       |   1 |  HASH GROUP BY                 |           |   405 | 30780 |   955   (2)| 00:00:12 |       |       |
       |*  2 |   HASH JOIN                    |           |  1558 |   115K|   954   (2)| 00:00:12 |       |       |
       |   3 |    PART JOIN FILTER CREATE     | :BF0000   |   183 |  2928 |    18   (0)| 00:00:01 |       |       |
       |*  4 |     TABLE ACCESS FULL          | TIMES     |   183 |  2928 |    18   (0)| 00:00:01 |       |       |
       |*  5 |    HASH JOIN                   |           | 12456 |   729K|   935   (2)| 00:00:12 |       |       |
       |   6 |     MERGE JOIN CARTESIAN       |           |   383 | 14937 |   408   (1)| 00:00:05 |       |       |
       |*  7 |      TABLE ACCESS FULL         | CHANNELS  |     1 |    13 |     3   (0)| 00:00:01 |       |       |
       |   8 |      BUFFER SORT               |           |   383 |  9958 |   405   (1)| 00:00:05 |       |       |
       |*  9 |       TABLE ACCESS FULL        | CUSTOMERS |   383 |  9958 |   405   (1)| 00:00:05 |       |       |
       |  10 |     PARTITION RANGE JOIN-FILTER|           |   918K|    18M|   525   (2)| 00:00:07 |:BF0000|:BF0000|
       |  11 |      TABLE ACCESS FULL         | SALES     |   918K|    18M|   525   (2)| 00:00:07 |:BF0000|:BF0000|
       ------------------------------------------------------------------------------------------------------------
  2. 取得」Star Transformation「啓用時的執行計劃。

    SQL> alter session set star_transformation_enabled='true';
       セッションが変更されました。
       SQL> SELECT c.cust_city,
       t.calendar_quarter_desc,
       SUM(s.amount_sold) sales_amount
       FROM sh.sales s,
       sh.times t,
       sh.customers c,
       sh.channels ch
       WHERE s.time_id = t.time_id
       AND s.cust_id = c.cust_id
       AND s.channel_id = ch.channel_id
       AND c.cust_state_province = 'CA'
       AND ch.channel_desc = 'Internet'
       AND t.calendar_quarter_desc IN ('1999-01','1999-02')
       GROUP BY c.cust_city, t.calendar_quarter_desc;
    
       実行計畫
       ----------------------------------------------------------
       Plan hash value: 2164696140
       --------------------------------------------------------------------------------------------------------------------------------
       | Id  | Operation                          | Name                      | Rows  | Bytes | Cost (%CPU)| Time     | Pstart| Pstop |
       --------------------------------------------------------------------------------------------------------------------------------
    
       |   0 | SELECT STATEMENT                   |                           |   542 | 30894 |   533   (1)| 00:00:07 |       |       |
       |   1 |  TEMP TABLE TRANSFORMATION         |                           |       |       |            |          |       |       |
       |   2 |   LOAD AS SELECT                   | SYS_TEMP_0FD9D6609_340EC8 |       |       |            |          |       |       |
       |*  3 |    TABLE ACCESS FULL               | CUSTOMERS                 |   383 |  9958 |   405   (1)| 00:00:05 |       |       |
       |   4 |   HASH GROUP BY                    |                           |   542 | 30894 |   128   (1)| 00:00:02 |       |       |
       |*  5 |    HASH JOIN                       |                           |  1949 |   108K|   127   (0)| 00:00:02 |       |       |
       |   6 |     TABLE ACCESS FULL              | SYS_TEMP_0FD9D6609_340EC8 |   383 |  5745 |     2   (0)| 00:00:01 |       |       |
       |*  7 |     HASH JOIN                      |                           |  1949 | 81858 |   125   (0)| 00:00:02 |       |       |
       |*  8 |      TABLE ACCESS FULL             | TIMES                     |   183 |  2928 |    18   (0)| 00:00:01 |       |       |
       |   9 |      VIEW                          | VW_ST_A3F94988            |  1953 | 50778 |   107   (0)| 00:00:02 |       |       |
       |  10 |       NESTED LOOPS                 |                           |  1953 |   108K|    84   (0)| 00:00:02 |       |       |
       |  11 |        PARTITION RANGE SUBQUERY    |                           |  1952 | 54676 |    54   (0)| 00:00:01 |KEY(SQ)|KEY(SQ)|
       |  12 |         BITMAP CONVERSION TO ROWIDS|                           |  1952 | 54676 |    54   (0)| 00:00:01 |       |       |
       |  13 |          BITMAP AND                |                           |       |       |            |          |       |       |
       |  14 |           BITMAP MERGE             |                           |       |       |            |          |       |       |
       |  15 |            BITMAP KEY ITERATION    |                           |       |       |            |          |       |       |
       |  16 |             BUFFER SORT            |                           |       |       |            |          |       |       |
       |* 17 |              TABLE ACCESS FULL     | CHANNELS                  |     1 |    13 |     3   (0)| 00:00:01 |       |       |
       |* 18 |             BITMAP INDEX RANGE SCAN| SALES_CHANNEL_BIX         |       |       |            |          |KEY(SQ)|KEY(SQ)|
       |  19 |           BITMAP MERGE             |                           |       |       |            |          |       |       |
       |  20 |            BITMAP KEY ITERATION    |                           |       |       |            |          |       |       |
       |  21 |             BUFFER SORT            |                           |       |       |            |          |       |       |
       |* 22 |              TABLE ACCESS FULL     | TIMES                     |   183 |  2928 |    18   (0)| 00:00:01 |       |       |
       |* 23 |             BITMAP INDEX RANGE SCAN| SALES_TIME_BIX            |       |       |            |          |KEY(SQ)|KEY(SQ)|
       |  24 |           BITMAP MERGE             |                           |       |       |            |          |       |       |
       |  25 |            BITMAP KEY ITERATION    |                           |       |       |            |          |       |       |
       |  26 |             BUFFER SORT            |                           |       |       |            |          |       |       |
       |  27 |              TABLE ACCESS FULL     | SYS_TEMP_0FD9D6609_340EC8 |   383 |  1915 |     2   (0)| 00:00:01 |       |       |
       |* 28 |             BITMAP INDEX RANGE SCAN| SALES_CUST_BIX            |       |       |            |          |KEY(SQ)|KEY(SQ)|
       |  29 |        TABLE ACCESS BY USER ROWID  | SALES                     |     1 |    29 |    53   (0)| 00:00:01 | ROWID | ROWID |

簡單的比較一下上面兩個執行計劃就能夠發現」Star Transformation「啓用後,Access的記錄數和COST都大幅下降了。

在看一下CBO的動做,咱們能夠看到啓用」Star Transformation「後,上面的SQL文被轉換成了下面的SQL文:

SELECT
        "T1" . "C1" "CUST_CITY"
        ,"T" . "CALENDAR_QUARTER_DESC" "CALENDAR_QUARTER_DESC"
        ,SUM (
            "VW_ST_A3F94988" . "ITEM_3"
        ) "SALES_AMOUNT"
    FROM
        (
            SELECT
                    /*+ ORDERED USE_NL ("SYS_CP_S") NOPARALLEL ("S") */ "SYS_CP_S" . "CUST_ID" "ITEM_1"
                    ,"SYS_CP_S" . "TIME_ID" "ITEM_2"
                    ,"SYS_CP_S" . "AMOUNT_SOLD" "ITEM_3"
                FROM
                    "SH" . "SALES" "S"
                    ,"SH" . "SALES" "SYS_CP_S"
                WHERE
                    "S" . ROWID = "SYS_CP_S" . ROWID
                    AND "S" . "CUST_ID" = ANY (
                        SELECT
                                /*+ SEMIJOIN_DRIVER CACHE_TEMP_TABLE ("T1") */ "T1" . "C0" "C0"
                            FROM
                                "SYS" . "SYS_TEMP_0FD9D660B_340EC8" "T1"
                    )
                    AND "S" . "CHANNEL_ID" = ANY (
                        SELECT
                                /*+ SEMIJOIN_DRIVER */ "CH" . "CHANNEL_ID" "ITEM_1"
                            FROM
                                "SH" . "CHANNELS" "CH"
                            WHERE
                                "CH" . "CHANNEL_DESC" = 'Internet'
                    )
                    AND "S" . "TIME_ID" = ANY (
                        SELECT
                                /*+ SEMIJOIN_DRIVER */ "T" . "TIME_ID" "ITEM_1"
                            FROM
                                "SH" . "TIMES" "T"
                            WHERE
                                "T" . "CALENDAR_QUARTER_DESC" = '1999-01'
                                OR "T" . "CALENDAR_QUARTER_DESC" = '1999-02'
                    )
        ) "VW_ST_A3F94988"
        ,"SH" . "TIMES" "T"
        ,"SYS" . "SYS_TEMP_0FD9D660B_340EC8" "T1"
    WHERE
        "VW_ST_A3F94988" . "ITEM_2" = "T" . "TIME_ID"
        AND "VW_ST_A3F94988" . "ITEM_1" = "T1" . "C0"
        AND (
            "T" . "CALENDAR_QUARTER_DESC" = '1999-01'
            OR "T" . "CALENDAR_QUARTER_DESC" = '1999-02'
        )
    GROUP BY
        "T1" . "C1"
        ,"T" . "CALENDAR_QUARTER_DESC"

你們是否注意到了有一個臨時表「SYS_TEMP_0FD9D660B_340EC8」被使用了呢?

這個轉換咱們上面沒有提到,實際這是一個」Star Transformation「的附加功能,他把屬於「c.cust_state_province = 'CA'」的「customers」 緩存到一個臨時表中,避免了在和「sales」表數據結合是再次對」TABLE ACCESS FULL CUSTOMERS「

咱們看看若是不使用臨時表的狀況。

SQL> alter session set star_transformation_enabled='temp_disable';
セッションが変更されました。
SQL> SELECT c.cust_city,
t.calendar_quarter_desc,
SUM(s.amount_sold) sales_amount
  2    3    4  FROM sh.sales s,
  5   sh.times t,
  6   sh.customers c,
  7   sh.channels ch
WHERE s.time_id = t.time_id
AND s.cust_id = c.cust_id
AND s.channel_id = ch.channel_id
AND c.cust_state_province = 'CA'
AND ch.channel_desc = 'Internet'
AND t.calendar_quarter_desc IN ('1999-01','1999-02')
GROUP BY c.cust_city, t.calendar_quarter_desc;
  8    9   10   11   12   13   14

実行計畫
----------------------------------------------------------
Plan hash value: 2346071880
-----------------------------------------------------------------------------------------------------------------------
| Id  | Operation                         | Name              | Rows  | Bytes | Cost (%CPU)| Time     | Pstart| Pstop |
-----------------------------------------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT                  |                   |   405 | 27540 |  1337   (1)| 00:00:17 |       |       |
|   1 |  HASH GROUP BY                    |                   |   405 | 27540 |  1337   (1)| 00:00:17 |       |       |
|*  2 |   HASH JOIN                       |                   |  1948 |   129K|  1336   (1)| 00:00:17 |       |       |
|*  3 |    TABLE ACCESS FULL              | CUSTOMERS         |   383 |  9958 |   405   (1)| 00:00:05 |       |       |
|*  4 |    HASH JOIN                      |                   |  1949 | 81858 |   931   (1)| 00:00:12 |       |       |
|*  5 |     TABLE ACCESS FULL             | TIMES             |   183 |  2928 |    18   (0)| 00:00:01 |       |       |
|   6 |     VIEW                          | VW_ST_B1772830    |  1953 | 50778 |   913   (1)| 00:00:11 |       |       |
|   7 |      NESTED LOOPS                 |                   |  1953 |   108K|   487   (1)| 00:00:06 |       |       |
|   8 |       PARTITION RANGE SUBQUERY    |                   |  1952 | 54676 |   457   (1)| 00:00:06 |KEY(SQ)|KEY(SQ)|
|   9 |        BITMAP CONVERSION TO ROWIDS|                   |  1952 | 54676 |   457   (1)| 00:00:06 |       |       |
|  10 |         BITMAP AND                |                   |       |       |            |          |       |       |
|  11 |          BITMAP MERGE             |                   |       |       |            |          |       |       |
|  12 |           BITMAP KEY ITERATION    |                   |       |       |            |          |       |       |
|  13 |            BUFFER SORT            |                   |       |       |            |          |       |       |
|* 14 |             TABLE ACCESS FULL     | CHANNELS          |     1 |    13 |     3   (0)| 00:00:01 |       |       |
|* 15 |            BITMAP INDEX RANGE SCAN| SALES_CHANNEL_BIX |       |       |            |          |KEY(SQ)|KEY(SQ)|
|  16 |          BITMAP MERGE             |                   |       |       |            |          |       |       |
|  17 |           BITMAP KEY ITERATION    |                   |       |       |            |          |       |       |
|  18 |            BUFFER SORT            |                   |       |       |            |          |       |       |
|* 19 |             TABLE ACCESS FULL     | TIMES             |   183 |  2928 |    18   (0)| 00:00:01 |       |       |
|* 20 |            BITMAP INDEX RANGE SCAN| SALES_TIME_BIX    |       |       |            |          |KEY(SQ)|KEY(SQ)|
|  21 |          BITMAP MERGE             |                   |       |       |            |          |       |       |
|  22 |           BITMAP KEY ITERATION    |                   |       |       |            |          |       |       |
|  23 |            BUFFER SORT            |                   |       |       |            |          |       |       |
|* 24 |             TABLE ACCESS FULL     | CUSTOMERS         |   383 |  6128 |   405   (1)| 00:00:05 |       |       |
|* 25 |            BITMAP INDEX RANGE SCAN| SALES_CUST_BIX    |       |       |            |          |KEY(SQ)|KEY(SQ)|
|  26 |       TABLE ACCESS BY USER ROWID  | SALES             |     1 |    29 |   456   (1)| 00:00:06 | ROWID | ROWID |
-----------------------------------------------------------------------------------------------------------------------

是否是在24行,和「sales」表數據結合是再次對」TABLE ACCESS FULL CUSTOMERS「了呢。

最後,咱們來總結一下如何啓用」Star Transformation「。

1.  參數「star_transformation_enabled」設成「True」或「temp_disable」。
2.  "Fact Table"的檢索列上有Bitmap索引。

以上。

2021/04/01 @ Dalian

相關文章
相關標籤/搜索