跑步王在 COSCUP 2015 的 PostgreSQL、JSON、GIS

剛剛看到跑步王COSCUP 2015 的「COSCUP 2015 - 使用 PostgreSQL, NoSQL 和 GIS 一次滿足 - Ronny Wang」這份錄影資料:

前半段講 JSON、JSONB (JSON Types) 以及 PostgreSQLIndexes on Expressions 以及 Partial Indexes

後半段講 GIS 的部份也很讚,不過就偏地圖應用了 :p

Amazon DynamoDB 筆記

Amazon DynamoDB 頁面上的介紹:

Amazon DynamoDB is a fast and flexible NoSQL database service for all applications that need consistent, single-digit millisecond latency at any scale.

資料型態的部份就跳過去了,這篇筆記的重點在於 index 的部份 (了解他如何 scale),尤其是對 RDBMS 有了解的人要如何從他所設計的架構理解 DynamoDB 的 index。

理論基礎是 Amazon 在 2007 年丟出的論文「Dynamo: Amazon’s Highly Available Key-value Store」,這篇論文影響了很多 open source project。

DynamoDB 的 index 有 Primary Key、Local Secondary Index Key (LSI) 以及 Global Index Key (GSI),在「DynamoDB Data Model」這篇有介紹。

這邊會拿 Blogger.com 這種多人的 Blog Hosting 當例子:

  • 一個 user 可以有很多 blog。(table user)
  • 一個 blog 可以有很多 post。(table blog)
  • 一篇 post 可以有很多 comment。(table post)

接下來就從 Primary Key 開始講。

Primary Key

Primary Key 保證唯一,這也是 DynamoDB 裡面可以達到 RDBMS 的 UNIQUE KEY 效果的最佳方式。

有兩種 Primary Key 的型態,一種叫做 Hash,另外一種叫做 Hash-Range。

兩種都需要指定某一個欄位是 Hash-based column,當作切割 (partition) 的依據。

第一種:Hash

以 table user 來說,可以拿 user_id 來當作 Hash-based column,裡面有 blog_id 的 list。

以 table blog 來說,可以拿 blog_id 來當作 Hash-based column,裡面有 post_id 的 list。

要注意的是,如果表格 PK 是 Hash,那麼就不能使用 LSI 與 GSI 了。只有另外一種型態 (Hash-Range) 才可以用 LSI 與 GSI。

相對的,Hash-based 的表格因為功能有限,效率通常很好 XDDD

第二種:Hash-Range

其實 Hash-Range 是一種別的 LSI,兩者最大的差異就是唯一性了。

另外一種 Primary Key 是 Hash-Range,他需要指定兩個欄位,其中其中 Hash 的欄位就如同上面的解釋,當作資料切割的依據。這邊的唯一性是指 (Hash column, Range column) 唯一,而非只有 Hash 唯一或是 Range 唯一。

剛剛說到需要指定的另外一個欄位,被稱為「Range」的原因是因為他可以有效率的以 hash + range query 查詢資料。

以 table post 來說,可以拿 blog_id 當作 Hash-based column,再拿 post_id 當作 Range-based column,等下我們介紹 LSI 時再拿發表時間欄位排序。

同理,table comment 可以拿 (post_id, commend_id) 當 PK。

Query

PK 是 Hash 的當然就是指定 Hash-based column 直接查,條件只能是等號。

PK 是 Hash-Range 的除了可以用 Hash-based column 直接查 (還是只能用等號),另外可以用 Hash-based column + Range-based column 查。

以 SQL 的想法就像是 WHERE hash_col = 123 AND range_col BETWEEN (123, 456) 的感覺。反正 Hash-based column 一定要等號。

講到這邊,其實讀過上面提到的 Amazon 那篇論文應該就大概有感覺架構是怎麼搞的了:(這是推敲出來的,未必是實際架構)

  • 用 Hash-based column 切 consistent hash ring 塞到不同機器上。PK 是 Hash 的到這邊就搞定了。
  • PK 是 Hash-Range 的,還是照上面一條提到的,用 Hash-based column 切開,所以同樣的 Hash-based column 的資料都會塞到同一台機器上,於是就可以用有效率的 ordered tree 來存放 Range-based column 的資料,這樣就可以提供 query 了。

當然,考慮到需要實做 rebalance 機制以逐步擴充,這邊 consistent hash ring 的部份的作法可以更細膩,不過就不是這篇要談的重點了。

接下來要講重頭戲 LSI 與 GSI 了。

Local Secondary Index (LSI) 與 Global Secondary Index (GSI)

前面有提到 LSI 與 GSI 必須 PK 是 Hash-Range 的情況下能用,兩者都不強制唯一性。

LSI 與 GSI 都是 (Hash-column based, Range-column based) 的形式,差別在 LSI 的 Hash-column based column 必須跟 PK 的相同,GSI 的可以不用一樣。

所以對於 table post 可以加一個 LSI (blog_id, post_datetime),就可以用 WHERE blog_id = 123 ORDER BY post_datetime DESC 拉出對應的文章了。

同理,table comment 是 (post_id, comment_datetime)。

PostgreSQL 對 NoSQL 的看法...

二月的時候 PostgreSQL 的人在 FOSDEM PGDay 2013 上發表了對 NoSQL 的看法 (PDF 投影片):「PostgreSQL as a Schemaless Database.」。

先說明,這投影片相當酸 XD

不過這份投影片說明了大多數人的問題:

  • 其實大多用 NoSQL 的人不知道在用什麼...
  • 就算你知道你在用什麼,你用得很爽的功能其實在「傳統的」「SQL 架構」下效能通常都會更好...

另外我建議可以看看維基百科上的 Entity-attribute-value model,大多數你想用 NoSQL 的情況在這個 case 下就可以解決,而且效能相當好。

換 NoSQL 前的建議...

原文是「Medium Data: things to try before abandoning SQL」,放棄 SQL 前應該要嘗試的事情,原文一開始就用粗體說明帶有強烈的偏見 XD

First, my thesis: a lot of less-experienced developers are using big data and NoSQL technologies because they are new and cool, and because SQL is old and hard. A lot of these people would save themselves time and effort by learning more about SQL and tuning their databases and hardware just a little bit.

文章寫的相當概念性,主要是說明幾件事情:

  • 其實 SQL 可以解決大部分的事情,大家都知道 SQL 的瓶頸在哪裡,有哪些 workaround 可以避開。
  • 不要因為 MySQL 做不到就覺得 SQL 不好用,在這種情況下,PostgreSQL 的功能與成熟度很值得看看。
  • 不要用 Oracle 官方版本的 MySQL... XD
  • 通常可以用 cache 解決的就用 cache 試著解看看,雖然 invalidate 問題不太好處哩... XD
  • 如果是 Read 數量太多,可以用 replication 解決不少問題。
  • 試著去理解 index 的「原理」,也就是資料結構,這對於要怎麼用 index 絕對有強力的幫助。
  • 當上面都做完而發現還是不夠的時候就 sharding 吧。

分散式系統的建言...

「分散式系統」(Distributed System) 是個老詞彙,但跟最近當紅詞彙「雲」、「NoSQL」常常相關。也因此「雲」與「NoSQL」常常遇到的都是分散式系統遇到 (並且討論過) 的問題...

而「Notes on Distributed Systems for Young Bloods」這篇寫的好血淚 XDDD 除了講理論面的東西以外,也把實務面會遇到的問題拿出來講...

首先要先知道「Fallacies of Distributed Computing」,在分散式系統裡,能假設的事情實在太少,要處理的事情太多。而「CAP theorem」也是個必讀的主題,從 Amazon 丟出「Dynamo: Amazon's Highly Available Key-value Store」這篇經典的 paper 後讓更多人知道這個理論。

熟悉上面兩個主題後,接下來就是血淚史... XD

garbage collection pauses make masters “disappear”

啊,GC 讓 master 不見... (NameNode... XDDD)

Writing robust distributed systems costs more than writing robust single-machine systems.

Robust, open source distributed systems are much less common than robust, single-machine systems.

這兩條... XD

Oh, and Paxos really is very hard to implement

Paxos... XD

If you can fit your problem in memory, it’s probably trivial.

(噴飯)

“It’s slow” is the hardest problem you’ll ever debug.

連問題都找不到嗎... XD

撇開這些碎碎念的部份,就算對 distributed system 沒那麼熟,這篇文章也提到了很多「解決的方向」以及「關鍵字」讓你找資料,對於實際操作時會有很大的幫助。

MySQL HandlerSocket 的情況...

前幾天 jnlinOSDC.TW 2011 上面講了「HandlerSocket – A NoSQL Plugin for MySQL」,剛好 Percona 的 Ryan Lowe 也提到了「What’s up with HandlerSocket?」,試著分析 (並猜測) HandlerSocket 為什麼沒有被廣泛使用。

除了技術的問題外,最主要在於運作:Open Source 不是把程式丟出來就覺得沒事了,要僅可能讓使用者容易使用。

比較好運作方式是在重大的 bug 修掉之後就推出 minor version release,一方面讓一些願意整合的單位有「基準」可以整合 (像是 Percona 這樣的公司),另外一方面可以讓 community 感覺是個有在動的 project...

像是文章裡提到的兩個 bug,一個在今年年初已經修正 (write invalidate),另外一個大約兩個禮拜前修正了 (insert auto-increment),只是很多人不太清楚而已。

目前這個專案的感覺跟 Facebook 丟出來的 memcached 還蠻像的:「facebook / memcached」,Facebook memcached 的情況是很明顯「老闆說要 open source,我就丟出來吧」的感覺,原來的 community 也懶的理他,看一看有沒有可以用的 code 可以整合,然後繼續發展自己的...

Percona Server 支援 HandlerSocket

Percona 前天推出的 Percona Server 5.1.52-12.3 宣佈支援 HandlerSocket,在 InnoDB 的基礎上面提供 memcached 等級的效能... (不過還不曉得在碰到 I/O 時會掉多少)

HandlerSocket 拿 InnoDB 當作 Key-Value store 的底層,需要的時候還可以透過上層的 SQL 存取,然後 Percona 也跳下去,因為現有的資料庫就可以拿來用,可以預期會有很多人跳下去玩...