日本熟妇hd丰满老熟妇,中文字幕一区二区三区在线不卡 ,亚洲成片在线观看,免费女同在线一区二区

SQL管理物化視圖

實時物化視圖將對明細表的數據進行預先聚合,存儲為物化視圖,通過查詢物化視圖,減少計算量,顯著提升查詢性能。本文為您介紹在Hologres中如何使用物化視圖。

背景信息

Hologres實時物化視圖不需要手動刷新物化數據,明細表實時寫入,會實時反映在對物化視圖的查詢上,寫入即可見,寫入即聚合。

結構圖在實時物化視圖中,實時寫入的表叫明細表,也稱Base Table,用戶的Insert、Update、Delete都執行在明細表上,物化視圖基于明細表的聚合規則定義,當明細表發生變更時,變更會實時同步到物化視圖中。當前僅支持Insert類變更,后續會逐步增加更多類型的變更。

使用限制

  • 當前實時物化視圖不支持對明細表進行Delete或Update操作,所以需要將明細表設置appendonly屬性,當前對明細表任何的Delete或Update操作會提示: Table XXX is append-only。Flink實時寫入時mutateType也只支持InsertOrIgnore。

  • 當前不支持異步創建物化視圖,需要創建明細表的同時創建基于該表的物化視圖。

  • 當前僅支持單表的物化視圖,不支持CTE、多表JOIN、子查詢、不支持WHERE條件、ORDER BY、LIMIT、HAVING語句。

  • 實時物化視圖的GROUP BY Key和Value都不支持表達式,比如不支持SUM(CASE WHEN COND THEN A ELSE B END)SUM(col1 + col2)GROUP BY date_trunc('hour', ts)

  • 每張明細表最多創建10個物化視圖,物化視圖數量和資源消耗成正比。

  • 如果基于分區表創建物化視圖,物化視圖的GROUP BY Key必須包含分區表的分區列,且不能對分區表的子表創建物化視圖,只能針對分區表父表創建。

  • 如果基于分區表創建物化視圖,不支持ATTACH PARTITION至父表語法,支持CREATE TABLE PARTITION OF語法。

  • 對于創建了物化視圖的明細表,暫不支持DROP COLUMN

  • 物化視圖的底層數據與明細表的TTL一致,不可以手動設置物化視圖的TTL,否則會出現物化視圖數據和明細表數據不一致的情況。

支持的聚合函數

物化視圖當前支持如下聚合函數。

  • SUM

  • COUNT

  • AVG

  • MIN

  • MAX

  • RB_BUILD_CARDINALITY_AGG(只支持BIGINT,需創建Extension roaringbitmap)

SQL示例

  • 創建實時物化視圖

    BEGIN;
    CREATE TABLE base_sales(
      day text not null,
      hour int ,
      ts timestamptz,
      amount float,
      pk text not null primary key
    );
    CALL SET_TABLE_PROPERTY('base_sales', 'mutate_type', 'appendonly');
    
    --當實時物化視圖被Drop后,可以取消明細表的appendonly屬性,執行以下命令
    --CALL SET_TABLE_PROPERTY('base_sales', 'mutate_type', 'none');
    
    CREATE MATERIALIZED VIEW mv_sales AS
      SELECT
        day,
        hour,
        avg(amount) AS amount_avg
      FROM base_sales
      GROUP BY day, hour;
    
    COMMIT;
    
    insert into base_sales values(to_char(now(),'YYYYMMDD'),'12',now(),100,'pk1');
    insert into base_sales values(to_char(now(),'YYYYMMDD'),'12',now(),200,'pk2');
    insert into base_sales values(to_char(now(),'YYYYMMDD'),'12',now(),300,'pk3');
  • 分區表創建物化視圖

    BEGIN;
    CREATE TABLE base_sales_p(
      day text not null,
      hour int,
      ts timestamptz,
      amount float,
      pk text not null,
      primary key (day, pk)
    ) partition by list(day);
    CALL SET_TABLE_PROPERTY('base_sales_p', 'mutate_type', 'appendonly');
    
    --day是分區列,要出現在視圖的group by的條件中
    CREATE MATERIALIZED VIEW mv_sales_p AS
      SELECT
        day,
        hour,
        avg(amount) AS amount_avg
      FROM base_sales_p
      GROUP BY day, hour;
    COMMIT;
    
    create table base_sales_20220101 partition of base_sales_p for values in('20220101');
  • 查詢物化視圖

    SELECT * FROM mv_sales WHERE day = to_char(now(),'YYYYMMDD') AND hour = 12;
  • 刪除物化視圖

    DROP MATERIALIZED VIEW mv_sales;
  • 查詢物化視圖占用存儲空間

    select pg_relation_size('mv_sales');
  • 查詢所有物化視圖底層占用空間

    SELECT schemaname || '.' || matviewname AS mv_full_name,
    pg_size_pretty(pg_relation_size('"' || schemaname || '"."' || matviewname || '"')) AS mv_size,
    pg_relation_size('"' || schemaname || '"."' || matviewname || '"') AS  order_size
    FROM pg_matviews
    ORDER BY order_size DESC;

使用物化視圖提升精確UV計算性能

精確UV計算是計算復雜度非常高的算子,通常是系統的性能瓶頸部分。Hologres支持RB_BUILD_CARDINALITY_AGG聚合函數,通過利用RoaringBitmap數據結構,可以對BIGINT類數據(通常是表示業務ID字段)進行物化視圖預聚合,實現UV統計實時去重,可按照如下方式創建物化視圖,當前僅支持BIGINT類字段的聚合去重。

--UV計算依賴RoaringBitmap數據類型,需要提前創建RoaringBitmap extension
CREATE EXTENSION if not exists roaringbitmap;

BEGIN;
CREATE TABLE base_sales_r(
  day text not null,
  hour int ,
  ts timestamptz,
  amount float,
  userid bigint,
  pk text not null primary key
);
CALL SET_TABLE_PROPERTY('base_sales_r', 'mutate_type', 'appendonly');

CREATE MATERIALIZED VIEW mv_sales_r AS
  SELECT
    day,
    hour,
    avg(amount) AS amount_avg,
    rb_build_cardinality_agg(userid) as user_count
  FROM base_sales_r
  GROUP BY day, hour;

COMMIT;

insert into base_sales_r values(to_char(now(),'YYYYMMDD'),'12',now(),100,1,'pk1');
insert into base_sales_r values(to_char(now(),'YYYYMMDD'),'12',now(),200,2,'pk2');
insert into base_sales_r values(to_char(now(),'YYYYMMDD'),'12',now(),300,3,'pk3');
select user_count as UV from mv_sales_r where day = to_char(now(),'YYYYMMDD') AND hour = 12;

通過rb_build_cardinality_agg計算去重數,mv_sales_ruser_count代表userid去重數,查詢user_count可獲得去重數。

使用物化視圖支持多維度聚合查詢

假設定義了上述的mv_sales物化視圖,且明細表base_sales中當前含有以下明細數據。

Day

Hour

Amount

PK

20210101

12

2

pk1

20210101

12

4

pk2

20210101

13

6

pk3

直接查詢sales_mv將會有如下結果。

postgres=> select * from mv_sales;
    day    |   hour  |   amount_avg
-----------+---------+--------------
  20210101 |    12   |     3
  20210101 |    13   |     6

這時如果想更改查詢物化視圖的聚合維度,例如使用維度day進行avg聚合計算,則會得到的會是一個錯誤的結果,因為avg的avg不等于total的avg。

postgres=> select day, avg(amount_avg) from mv_sales group by day;
    day    |   avg
-----------+--------
  20210101 |   4.5

這時候一種辦法是再建一張以day為維度進行聚合的物化視圖,但這樣會導致物化視圖的數量膨脹,Hologres提供了一種基于聚合中間狀態的實現,使得用戶僅用一張物化視圖,實現不同維度聚合查詢。這里以Avg為例,修改聚合視圖的定義如下。

BEGIN;
CREATE TABLE base_sales(
  day text not null,
  hour int ,
  ts timestamptz,
  amount float,
  pk text not null primary key
);
CALL SET_TABLE_PROPERTY('base_sales', 'mutate_type', 'appendonly');

CREATE MATERIALIZED VIEW mv_sales_partial AS
  SELECT
    day,
    hour,
    avg(amount) as avg,
    avg_partial(amount) AS amt_avg_partial
  FROM base_sales
  GROUP BY day, hour;

COMMIT;

原先的avg聚合函數重新定義為avg_partial聚合函數,amount_avg_partial列存儲的是聚合結果的中間狀態,查詢時需要修改查詢函數,將avg聚合函數改寫為avg_final最終聚合函數,聲明是對聚合結果中間狀態的最終聚合。

postgres=> select day, avg(avg) as avg_avg, avg_final(amt_avg_partial) as real_avg from mv_sales_partial group by day;
    day    |   avg_avg |  real_avg
-----------+-----------+----------
  20210101 |    4.5    |     4

目前支持以下聚合函數及對應的partial聚合函數。

普通聚合函數

Partial聚合函數

最終聚合函數

AVG

AVG_PARTIAL

AVG_FINAL

RB_BUILD_CARDINALITY_AGG

RB_BUILD_AGG

RB_OR_CARDINALITY_AGG

TTL說明

如果明細表設置了TTL,并創建了物化視圖,那么在TTL臨界點附近的數據,Hologres無法保證明細表和物化視圖查詢結果的一致性,查詢TTL臨界點附近的物化視圖數據的結果,是個未定義行為。下面以明細表base_sales_table和物化視圖sales_mv為例。

base_sales_table設置了TTL,如果數據由于TTL到期被回收掉,那么此時查詢明細表的結果如下所示。

postgres=> SELECT
    day,
    hour,
    avg(amount) AS amount_avg
  FROM base_sales
  GROUP BY day, hour;

--查詢結果
    day    |   hour  |   amount_avg
-----------+---------+--------------
  20210101 |    12   |     4
  20210101 |    13   |     6

但是由于被回收的數據,已經物化到了物化視圖的數據中,所以查詢物化視圖時有可能得到的結果如下。

postgres=> select * from mv_sales;
--查詢結果
    day    |   hour  |   amount_avg
-----------+---------+--------------
  20210101 |    12   |     3
  20210101 |    13   |     6

此時查詢結果不一致,建議改進方案如下。

  • 明細表不要設置TTL。

  • 明細表設置TTL,但是物化視圖的GROUP BY含有數據的時間字段,且查詢物化視圖的時候,不會去查詢在TTL臨界點附近的數據。

  • 明細表建成分區表,不設置TTL,回收數據通過刪除(Drop)分區表來實現。

實時物化視圖使用最佳實踐

  • 建表時建議將物化視圖的GROUP BY Key設置為明細表的Distribution Key,這樣能進一步提升數據的壓縮率,提升查詢性能。

  • 查詢時建議將查詢物化視圖時常用的過濾條件,放在GROUP BY Key的前列(符合Clustering Key左匹配原則)。

物化視圖的智能路由

查詢時不需要顯式指定物化視圖表名稱,可以像之前一樣基于基礎表進行查詢。如果有匹配的物化視圖表,優化器會智能路由到最佳的物化視圖表來加速查詢。在查詢時,物化視圖表的選擇規則如下:

  • 選擇包含所有查詢列或可以通過間接計算得到的物化視圖表。

  • 選擇GROUP BY列字段包含原始查詢GROUP BY所有列的物化視圖表。

  • 當有多個物化視圖表符合條件時,選擇GROUP BY列字段少的物化視圖表。

當前支持智能路由的聚合函數有SUM、COUNT、MIN和MAX。