今天講一個小衆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)。結構能夠用下面的圖表示。設計
這就是一個典型的「Star Schema」。code
那什麼又是「Star Transformation」呢?orm
「Star Transformation」是ORACLE爲了解決上面問題,結合ORACLE數據庫特有的「Bitmap」索引而做出的優化。索引
「Star Transformation」是如何實現的呢?
如今我用」Example Schemas「的幾個表來演示一下。
取得」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| ------------------------------------------------------------------------------------------------------------
取得」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