Cassandra 3.0 的新特性介紹: 物化視圖

jopen 9年前發布 | 7K 次閱讀 Cassandra

Cassandra 數據模型的基本規則 涉及到一些基于運行于列表中的查詢的手動非規范化數據。目前,不通過特定分區鍵來查詢欄的唯一方法是使用二級指標, 但是它們不能代替新表數據的非規范性,就像它們不適合高基數數據。高基數二級指標查詢通常需要環中各個節點的響應,這樣就會增加每個請求的延遲。相反,客 戶端的非規范化和多獨立表的使用,意味著同樣的代碼可以為不同的用戶重寫。在 3.0 版本中,Cassandra 將引入新的特性 —— 物化視圖。物化視圖可以處理自動化服務端的非規范化,移除客戶端處理非規范化的需求,并且能確保基庫(base)和視圖數據的最終一致性。這個非規范化允許每個視圖數據的超快速查詢使用正常的 Cassandra 讀取路徑。

一個例子

作為一個物化視圖如何使用的例子,假設我們跟蹤了幾個游戲的高分玩家。我們有幾個需要得到回答的疑問:

  1. 給定一個游戲,誰的分數會最高?分數是多少?

  2. 給定一個游戲和一天時間,誰的分數會最高?分數是多少?

  3. 給定一個游戲和一個月時間,誰的分數會最高?分數是多少?

物 化視圖保證了每個 CQL 行對應的基庫和視圖,所以我們需要確保視圖需要的每個 CQL 行會反映在基礎列表的主鍵上。對于第一個查詢,我們需要這個游戲、玩家、和他們最高的分數。對于第二個查詢,我們需要游戲、玩家、他們最高分數,還有一 天、一個月、一年的最高分數。對于最終的查詢,我們需要第二個查詢除了天數之外的所有數據。第二個查詢的數據是最嚴格的,所以它決定了我們使用的主鍵。用 戶可以在某天刷新他們的高分,所以我們只要在特定的日期中跟蹤最高分就行了。

CREATE TABLE scores
(
  user TEXT,
  game TEXT,
  year INT,
  month INT,
  day INT,
  score INT,
  PRIMARY KEY (user, game, year, month, day)
)

然后,我們會創建一個展示全時間段高分的視圖。為了創建物化視圖,我們提供了一個簡單的選擇狀態和這個視圖所要用到的主鍵。指定的 CLUSTERING ORDER BY 可以讓我們反轉高分的排序,這樣我們就可以簡單地選擇每個分區的第一項就能獲取最高分數。

CREATE MATERIALIZED VIEW alltimehigh AS
       SELECT user FROM scores
       PRIMARY KEY (game, score)
       WITH CLUSTERING ORDER BY (score desc)

為了查詢一天之中的高分,我們創建了一個聚合了游戲標題和數據的物化視圖,這樣就能讓單個分區包含每個日期的值。對于月的最高分,我們也是這么做的。

CREATE MATERIALIZED VIEW dailyhigh AS
       SELECT user FROM scores
       PRIMARY KEY ((game, year, month, day), score)
       WITH CLUSTERING ORDER BY (score DESC)
 
CREATE MATERIALIZED VIEW monthlyhigh AS
       SELECT user FROM scores
       PRIMARY KEY ((game, year, month), score)
       WITH CLUSTERING ORDER BY (score DESC)

我們在物化視圖中加入了數據。我們只在分數列表中插入數據,并且 Cassandra 會填充相應的物化視圖。

INSERT INTO scores (user, game, year, month, day, score) VALUES ('pcmanus', 'Coup', 2015, 05, 01, 4000)
INSERT INTO scores (user, game, year, month, day, score) VALUES ('jbellis', 'Coup', 2015, 05, 03, 1750)
INSERT INTO scores (user, game, year, month, day, score) VALUES ('yukim', 'Coup', 2015, 05, 03, 2250)
INSERT INTO scores (user, game, year, month, day, score) VALUES ('tjake', 'Coup', 2015, 05, 03, 500)
INSERT INTO scores (user, game, year, month, day, score) VALUES ('jmckenzie', 'Coup', 2015, 06, 01, 2000)
INSERT INTO scores (user, game, year, month, day, score) VALUES ('iamaleksey', 'Coup', 2015, 06, 01, 2500)
INSERT INTO scores (user, game, year, month, day, score) VALUES ('tjake', 'Coup', 2015, 06, 02, 1000)
INSERT INTO scores (user, game, year, month, day, score) VALUES ('pcmanus', 'Coup', 2015, 06, 02, 2000)

現在我們可以查詢用戶在游戲中獲得最高分:

SELECT user , score FROM alltimehigh WHERE game = 'Coup' LIMIT 1
user       | score
-----------+-------
    pcmanus |  4000

每日最高分:

SELECT user , score FROM dailyhigh WHERE game = 'Coup' AND year = 2015 AND month = 06 AND day = 01 LIMIT 1
user       | score
-----------+-------
iamaleksey |  2500

所有的項都拷貝到了全時段高分物化視圖中:

SELECT user , score FROM alltimehigh WHERE game = 'Coup'
user       | score
-----------+-------
    pcmanus |  4000
iamaleksey |  2500
      yukim |  2250
  jmckenzie |  2000
    pcmanus |  2000
    jbellis |  1750
      tjake |  1000
      tjake |   500


因為視圖中每個 CQL 行都對應著基庫中 CQL 行,“pcmanus”和“tjake”在高分列表中出現了多次,同樣也在相應日期的基表中出現了多次。

我們也可以從基表中刪除行,并且物化視圖上的記錄也會被刪除。我們刪除分數列表的 tjake 行:

DELETE FROM scores WHERE user = 'tjake'

現在,查找所有的分數,tjake 項就找不到了。

SELECT user , score FROM alltimehigh WHERE game = 'Coup'
user       | score
-----------+-------
    pcmanus |  4000
iamaleksey |  2500
      yukim |  2250
  jmckenzie |  2000
    pcmanus |  2000
    jbellis |  1750


當刪除事件發生時,物化視圖會在基表中查詢所有刪除掉的值,并且會為每個物化視圖行建立墓碑(tombstone),因為在視圖中需要建立墓碑的值不會包含在基表的墓碑中。對于獨立的基礎墓碑,會產生兩個視圖墓碑;一個用于(tjake, 1000),一個用于(tjake, 500)。

它是怎樣工作的?

Cassandra 3.0 的新特性介紹: 物化視圖

Base Replica 執行本地數據的讀取動作是為了建立正確的更新視圖。如果視圖的主鍵在基表中被更新,一個墓碑就會被建立,以至于老的值就不會再視圖中顯示出來。 Batchlog 為基表所提供的數據提供等效額一致性。如果沒有 batchlog,視圖更新沒有應用而基庫更新了的話,視圖和基庫就不會一致。然而,使用 batchlog 會明顯增加開銷,尤其是因為 batchlog 必須得寫入兩次。

創建

當物化視圖建立而列表中的數據已經存在,一個構建進程就會開始填充物化視圖。因此,物化視圖可以在現有的列表上建立,但是會有段時間物化視圖無法返回所有結果。這個和二級指標的工作方式有點相似。構建完成時,每個節點的 system.built_materializedviews 列表會和視圖的名稱一起更新。

改變基表

當一個基圖被改變,物化視圖也會更新。如果物化視圖有 SELECT * 語句,任何增加的列會包括在物化視圖的列中。任何屬于 SELECT 語句而被刪除的列會從物化視圖中移除。如果基表中的列被改變,同樣的改變會發生在視圖列表中。如果基表被丟棄,任何相關的視圖也會被丟棄。

什么時候不能使用物化視圖

  • 物化視圖沒有正常列表所具有的寫性能。

    物化視圖需要額外的讀前寫(read-before-write)操作,同樣,在創建視圖更新前要檢查每個副本的數據一致性。這些額外的開銷可能會改變寫操作延遲。

  • 如果行在放入視圖之前要被組合,物化視圖會無法工作。物化視圖會創建一個基庫 CQL 行對應的視圖 CQL 行。

  • 低基數數據會在環周圍創建熱點。

    如果所有數據的分區鍵都是相同的,這些節點就會過載。在 alltimehigh 物化視圖上,如果我們儲存高分的唯一游戲是“Coup”,儲存“Coup”的唯一節點就會儲存任何數據。

  • 目前,只有簡單的 SELECT 語句被支持,但是已經有提議要增加對更復雜 SELECT 語句的支持

    WHERE 條款,ORDER BY,和函數在物化視圖中不可用。

  • 如果有大量的分區墓碑,那性能就會備受煎熬;物化視圖就必須查詢現有的全部值,并且為每個值創建一個墓碑。每個基表刪除的 CQL 行都會有個物化視圖的墓碑。

  • 物化視圖不支持 Thrift。

Via:DataStax Developer Blog

 本文由用戶 jopen 自行上傳分享,僅供網友學習交流。所有權歸原作者,若您的權利被侵害,請聯系管理員。
 轉載本站原創文章,請注明出處,并保留原始鏈接、圖片水印。
 本站是一個以用戶分享為主的開源技術平臺,歡迎各類分享!