Vertica中的projections

在vertica中,表只是一個邏輯上的概念,其真實數據其實是存儲在一個個的projection中。projections以優化查詢執行的格式存儲數據。與物化視圖類似,projections將結果集存儲在磁盤上,而不是在每次查詢時計算它們。您可以使用新數據或更新數據刷新projections。

projections提供以下好處:
1.壓縮和編碼數據以減少存儲空間。
Vertica儘可能對編碼數據進行操作,以避免解碼成本。壓縮和編碼的這種組合可優化磁盤空間,同時最大限度地提高查詢性能。
2.促進跨數據庫羣集的分發。
根據其大小,可以跨羣集節點對projections進行分段或複製。
例如,可以對大型表的projections進行分段並在所有節點上分佈。可以跨所有節點複製小表的未分段projections。
3.對最終用戶透明。
Vertica的查詢優化器會自動選擇執行給定查詢的最佳projections。
4.提供高可用性和恢復。
Vertica複製羣集中至少K + 1個節點上的表列。如果一臺計算機在K-Safe環境中出現故障,則數據庫將繼續使用其餘節點上的複製數據進行操作。當節點恢復正常操作時,它會自動查詢其他節點以恢復數據和丟失的對象。

projections與物化視圖

再回顧一下projection的定義:
A projection consists of a set of columns with the same sort order, defined by a column to sort by or a sequence of columns by which to sort. Like an index or materialized view in a traditional database, a projection accelerates query processing.

物化視圖:物化視圖是包括一個查詢結果的數據庫對象,它是遠程數據的的本地副本,或者用來生成基於數據表求和的彙總表。物化視圖和視圖類似,反映的是某個查詢的結果,但是和視圖僅保存SQL定義不同,物化視圖本身會存儲數據,因此是物化了的視圖。

對比項 Projections 物化視圖
定義 包含列數據 包含查詢結果
數據存儲 數據存儲在projections中 數據是從表中拷貝到物化視圖裏
創建方式 創建於:1. 在進行數據導入時自動創建。 2. Database designer的方式創建。3. 手動創建。 通過定義查詢或聲明的方式創建
更新 數據加載時會自動更新 有特定的更新流程
數據一致性 通常會包含最新的數據 可能會包含out-of-data的數據
索引 不必要也不存在 包含索引
創建projection

可通過手動創建及自動創建的方式去創建一個或多個projection。
projection的創建語句如下圖所示:
在這裏插入圖片描述
可通過vertica 自帶的Database Designer去自動創建並部署一些projection,以達到優化數據庫性能的目的。

projection的分類

有3類projection,分別是超級projections,查詢特定的projections,聚合projections。

超級projections

定義:包含表的所有列的projections。
對於數據庫中的每個表,Vertica 至少需要一個projections,即超級projections。如果CREATE PROJECTION 指定包括所有表列,則可以創建超級projections。一個表可以有多個超級projections。

在某些條件下,Vertica 會在創建表時立即自動創建表的超級projections。
對於普通表,當建表語句中包含以下內容中的某一個時,會自動創建super projection:

AS SELECT
ENCODED BY
ORDER BY
SEGMENTED BY / UNSEGMENTED
KSAFE

當建表語句不包含上面語句中的任何一個時,只有在通過insert或copy向表內導入數據時,纔會自動創建super projection。

查詢特定的projections

查詢特定的projections是僅包含表列子集以處理給定查詢的projections。查詢特定的projections可顯著提高已優化查詢的性能。
若想優化一些特定的查詢sql,可通過手動創建projections的方式進行優化,也可以通過提供具體查詢,利用Database Desinger去創建增量設計。

聚合projections

包括表達式或聚合函數(例如 SUM 和 COUNT)的查詢在使用已包含聚合數據的projections時, 其執行效率更高。

補充:在vertcia的8.0版本之前,還有一種projection,叫pre-join projections,從命名上可以看出,這種projection主要用於優化表之間的關聯。在8.0版本之後,pre-join projections 已被flatten table所替代。關於flatten table後面會進行介紹。

projections的分段

projections可以分爲未分段的projections和分段的projections。

分段是指跨羣集節點組織和分發數據,以便實現快速數據清除和提升查詢性能。分段的目的是使數據在多個數據庫節點上均勻分佈,以便所有節點均參與查詢執行。可通過 CREATE PROJECTION 語句的哈希分段子句來指定分段。

未分段的projections

在許多情況下,維度表相對較小,因此您無需對其進行分段。因此,您應該設計一個K-safe數據庫,以便在所有集羣節點上覆制其維度表的projections而不進行分段。您可以使用CREATE PROJECTION包含UNSEGMENTED ALL NODES的語句創建未分段的projections 。此子句指定在所有羣集節點上創建相同的projections實例。

CREATE PROJECTION store.store_dimension_proj (storekey, name, city, state) 
             AS SELECT store_key, store_name, store_city, store_state 
             FROM store.store_dimension 
             UNSEGMENTED ALL NODES;
CREATE PROJECTION
分段的projections

通常會爲大型事實表創建分段projections。Vertica將分段projections拆分爲相似大小的塊(段),並在羣集中均勻分佈這些段。系統K-safety確定在不同節點上創建和維護每個段的重複(夥伴)projections的數量。

您可以使用CREATE PROJECTION包含SEGMENTED BY子句的語句創建分段projections。

CREATE PROJECTION public.employee_dimension_super 
    AS SELECT * FROM public.employee_dimension
    ORDER BY employee_key
    SEGMENTED BY hash(employee_key) ALL NODES;

vertica會根據系統的ksafe值去創建projection的副本,假設某個vertica集羣的ksafe爲1,則在任意一個節點上,都會有兩個projection,其中一個projection爲原始的分段projection,另一個爲其他節點分段projection的副本。

SELECT projection_name FROM projections WHERE projection_basename='employee_dimension_super';
       projection_name
-----------------------------
 employee_dimension_super_b0
 employee_dimension_super_b1
(2 rows)

K-safe數據庫projections

可通過CREATE PROJECTION選項KSAFE設置各個projections的K-safety。projections K-safety必須大於等於數據庫 K-safety(可通過select get_design_ksafe()或者select * from system命令來查看k-safety)。如果您忽略設置 KSAFE,projections將從數據庫獲取Ksafety。

分段的projections

如果將數據庫 K-safety 設置爲 1,則數據庫的每個projections分段需要兩個實例(或夥伴實例)。以下 CREATE PROJECTION 爲事實數據表 store.store_orders_fact 定義分段projections:

CREATE PROJECTION store.store_orders_fact (prodkey, ordernum, storekey, total)
AS SELECT product_key, order_number, store_key, quantity_ordered*unit_price FROM store.store_orders_fact
SEGMENTED BY HASH(product_key, order_number) ALL NODES KSAFE 1; 
CREATE PROJECTION

CREATE PROJECTION 語句中的三個關鍵字適用於設置projections K-safety:
K-SAFE 1
將 K-safety 設置爲 1。Vertica 使用以下命名約定自動創建兩個projections實例:

projection-name_bn

其中, n 是介於 0 和 k 之間的值。由於 K-safety 設置爲 1, 因此
Vertica 將創建兩個projections:

store.store_orders_fact_b0
store.store_orders_fact_b1

ALL NODES
指定將projections跨所有羣集節點分段。
HASH
有助於確保分段projections數據在羣集上均勻分佈。

未分段的projections

在 K-safe 數據庫中, 使用包括關鍵字 UNSEGMENTED ALL NODES 的 CREATE PROJECTION 語句創建未分段projections。這些關鍵字指定在所有羣集節點上創建整個projections的相同實例。如果在單個節點上創建未分段投影,則Vertica認爲它不安全且不使用它。
以下示例展示瞭如何爲表 store.store_dimension 創建未分段projections:

CREATE PROJECTION store.store_dimension_proj (storekey, name, city, state) AS SELECT store_key, store_name, store_city, store_state
FROM store.store_dimension UNSEGMENTED ALL NODES;
CREATE PROJECTION

查看projections

1.簡單查看有哪些projections:

\dj

可在 \dj後接具體的projection名。
2.可以使用系統視圖projection來查看projections的詳細信息。

SELECT projection_name FROM projections WHERE projection_basename='employee_dimension_super';
       projection_name
-----------------------------
 employee_dimension_super_b0
 employee_dimension_super_b1
(2 rows)

3.使用PROJECTION_COLUMNS視圖,可以查看到關於projections列,如編碼類型,排序,統計的類型,並在其列統計信息的最後更新的時間信息。

刷新及刪除projections

刷新projections

CREATE PROJECTION 並不將數據加載到物理存儲中。如果錨表已經包含數據,請運行 START_REFRESH 來更新projections。更新projections可能比較耗時,具體視表中的數據量而定。projections處於最新狀態時, 仍會在 COPY、DELETE、INSERT, MERGE 或UPDATE 語句執行期間自動更新。

示例:

SELECT START_REFRESH();
             START_REFRESH
----------------------------------------
 Starting refresh background process.

(1 row)
或者使用refresh命令,有針對性的對某些表的projections進行刷新。
示例:

select refresh('dbd_test.web_returns, dbd_test.web_sales, dbd_test.catalog_sales, dbd_test.store_sales');

可以查詢PROJECTION_REFRESHESPROJECTIONS查看刷新操作的進度。您還可以調用Vertica函數GET_PROJECTIONS來查看給定表的投影刷新的最終狀態:

SELECT GET_PROJECTIONS('customer_dimension');
                                           GET_PROJECTIONS                                                                                                                                                                                                                            
----------------------------------------------------------------------------------------------------------
 Current system K is 1.
# of Nodes: 3.
Table public.customer_dimension has 2 projections.

Projection Name: [Segmented] [Seg Cols] [# of Buddies] [Buddy Projections] [Safe] [UptoDate] [Stats]
----------------------------------------------------------------------------------------------------
public.customer_dimension_b1 [Segmented: Yes] [Seg Cols: "public.customer_dimension.customer_key"] [K: 1] 
       [public.customer_dimension_b0] [Safe: Yes] [UptoDate: Yes] [Stats: RowCounts]
public.customer_dimension_b0 [Segmented: Yes] [Seg Cols: "public.customer_dimension.customer_key"] [K: 1] 
       [public.customer_dimension_b1] [Safe: Yes] [UptoDate: Yes] [Stats: RowCounts]

(1 row)
刪除projections

可通過 DROP PROJECTION 語句明確刪除projections。當您刪除projections的錨表時,projections也會被隱式刪除。
示例:

DROP PROJECTION 
dbd_test.dbgen_version_DBD_1_seg_99sql_1_b0, dbd_test.dbgen_version_DBD_1_seg_99sql_1_b1 CASCADE;

後記:曾經有一段時間,數據庫的k-safe變成0 了,即有的數據沒有副本,這個對於分佈式數據庫是很危險的,一旦一個節點宕機,整個集羣不可用。後來嘗試過查看有問題表的建表語句,拿出projection的創建語句,手動重建projection ,來修復k-safe,但是表太多了。最後集羣重新安裝。

參考:
vertica官方文檔9.1.x

Working with Projections

Physical Schema

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章