資料型別(Data Types)‎ > ‎Hstore‎ > ‎

被世人忽略的key-value存儲

The key value store everyone ignored
    Wilson.G 星期五, 08/31/2012 - 15:18 發佈

我發現PostgreSQL是一款一直被人們忽視的偉大的關聯型資料庫管理系統。它甚至還擁有一個偉大的發佈者/訂閱者係統(或是PostgreSQL術語中的LISTEN / NOTIFY),而很多人可能用的是Redis, RabbitMQ等。對那些只用過MySQL的人們,我只是想讓他們去嘗試一下Postgres。

我將把目光集中在真正符合ACID的key value存儲上,而不是benchmark上。Postgres佔據了存儲引擎的優勢,並擁有 key value 存儲的頂級擴展模組。所以我的計劃是弄一張hstore資料類型的柱形圖,它有相應的自由結構存儲。想想這個模型的多個對比。它可以是一個像Cassandra一樣行key能作表的主Key的列簇存儲,表中hstore類型的每一列可以被想像成一個超級列,hstore條目中的每個key可以是一個列名。類似地你可以把他想像成Redis中的Hash結構(HSET,HDEL)或是2、3級的MongoDB存儲(幾乎不需要修改)。儘管與你的NoSQL存儲結構相似(當用了一些小技巧後),這給了我一個機會向你展示一些真實瑣碎的例子。

讓我們先來安裝系統。在我的實驗裡我將使用Postgres 9.1,並從源編譯它。一旦進入源目錄你可以:. /configure && make install以安裝你的Postgres。別忘了在contrib目錄下安裝extensions:cd . /contrib && make install。一旦你將其安裝,你可以創建自己的資料庫叢集並啟動伺服器(提示:使用initdb和pg_ctl)。然後啟動psql並保證安裝了hstore extension:

CREATE EXTENSION hstore;
SELECT ' foo=>bar' : : hstore;

如果一切正常你將會看到一個表格輸出。現在我們準備做一些DDL。我創建了一個名為my-store的表,如下:

CREATE TABLE my_store
(
id character varying(1024) NOT NULL,
doc hstore,
CONSTRAINT my_store_pkey PRIMARY KEY (id)
)
WITH (
OIDS=FALSE
) ;

    CREATE INDEX my_store_doc_idx_gist
    ON my_store
    USING gist
    (doc) ;


正如你所見,我建了一個hstore列型的表和一個GiST索引(?,?&,?|等運算符)。你可以檢查文件以查看可用運算符的不同類型。現在我有一個建好的資料庫和一些表,我用一個來自一個Twitter流大約115K行的簡單腳本去填充它。現在請記住它是現實生活中的資料,我對查詢已收集的資料中的一些基本資訊比較感興趣。比如說,多少人在使用hash標籤,或者在mention某人,或是在tweets裡發佈鏈接?為了做這個我用tweep和psycopg2寫了一個簡單的python腳本,並運行了數個小時。我為存儲中每條有哈希標籤的tweet添加了一個『has_hashtagsh: t' key value對。同樣地我引入了『has_urls' 和 『has_mentions'如果tweet中有的話。接下來我將使用這些keys連同我的GiST索引去查詢我的表。

在填入了115,142條tweets的數據後,數據庫增長到239691780 bytes(即228MB)。現在,有趣的部分來了。一個存儲下結合關係型和key value類型的功效所能獲得的東西徹底打動了我。打個比方,我想查詢在1323446095的unix時間戳裡所有發出的tweets(由於我將時間戳存儲為下面我查詢的字符串):

SELECT doc -> ' text' as tweet, doc -> ' created_at'
as created_at
FROM my_store
WHERE doc @> ' created_at=>00001323446095' ;

我可以增添一個簡單的計數或任何其它知名的SQL聚合函數,無需因任何特定事情而把我的資料存儲複雜化,如映射規約或學習一種新語言的困擾。注意我把我的時間戳的值用0填充因為我只存儲字符串作為值。另外,我還用了@>運算符,那將使用GiST去行使一個快速位圖索引掃瞄代替順序掃瞄。這對初學者非常棒。讓我們試著找出所有帶hash標籤的tweets:

SELECT doc -> ' text' as tweet, doc -> ' created_at'
as created_at
FROM my_store
WHERE doc @> ' has_hashtags=>: t' ;

是的,查詢整個資料庫並提取完整資料(你八成不會那麼做因為你page了資料)在平均僅360毫秒內出來14689行。因為我們有SQL在手,讓我們來點更複雜的查詢,同樣的事情使用不同的運算符,並且用『created_at'將資料排序:

SELECT doc -> ' text' as tweet, doc -> ' created_at'
as created_at
FROM my_store
WHERE doc @> ' has_hashtags=>: t' AND doc ?
' has_urls'
ORDER BY doc -> ' created_at' DESC;


這聽起來蠻有意思!但還不止是這些:Postgres還有其他的運算符。比如說,你還能找出同時有哈希標籤,鏈接和mentions的tweet:

SELECT doc -> ' text' as tweet, doc -> ' created_at'
as created_at
FROM my_store
WHERE doc @> ' has_hashtags=>: t' AND doc ?|
ARRAY[ ' has_urls' , ' has_mentions' ]

它能做的還遠遠不止這些!Hstore伴隨所有你可以用來查詢hash存儲的運算符和索引系統類型。在文檔中將其找出。現在,儘管NoSQL很火爆,我認為我們有充分的例子和理由證明關聯型資料庫管理系統仍是很多市場巨頭(像Facebook這種眾所周知的)的一個核心部分。Postgres又給了我一個別忽視關聯型資料庫管理系統的原因。所以,如果你轉向了某些文檔存儲的陣營,僅僅因為關聯型資料庫管理系統不提供它們;請再三思考一下!你可以得到同樣堅如磐石的自由結構系統。

注意
在PostgreSQL 8.2之前,它所含的運算符@>和<@被分別命名為@和~。這些名字現在仍然可用,但是不推薦使用,且將逐漸被移除。注意那些舊名稱從之前遵循的核心幾何資料類型的慣例中撤銷了!另外請注意→運算符也不推薦使用,在未來某個版本中可能被剔除。使用hstore(text,text)函數代替。

有關作者
Zohaib Sibte Hassan(暱稱maxpert)是一位DooPHP的貢獻者和微框架MiMViC的創始人。他在Bumpin社交媒體擔任高級軟體工程師。他解讀了NoSQL,NodeJS,及其他的一些專業術語。關注他的博客
http://blog.creapptives.com/

原文和討論串: http://blog.creapptives.com/post/14062057061/the-key-value-store-everyone-ignored-postgresql

簡中譯文: http://www.postgres.org.cn/?q=content/%E8%A2%AB%E4%B8%96%E4%BA%BA%E5%BF%BD%E7%95%A5%E7%9A%84key-value%E5%AD%98%E5%82%A8-0
Comments