天天看點

從微信小程式 到 資料庫"小程式" - 鬼知道我經曆了什麼

postgresql , 服務端程式設計接口 , pl language , 小程式 , 地球語言 , java , perl , python , php , tcl , r , go , julia

微信小程式最近比較火,大概以後大家都不需要安裝程式了,直接在微信中調用運作。跑在微信裡的小程式類似一個虛拟機或者一個docker容器,這是騰訊要分app store蛋糕的節奏嗎?

從技術角度來看,微信小程式帶來了幾個好處,不需要安裝軟體,使用者不需要進行軟體的版本管理,節省了一點點手機的空間,同時還降低了流氓軟體的可能,确實還不錯對吧。

不過接下來本文要給大家帶來的是資料庫"小程式",這是個什麼鬼呢?

在講資料庫"小程式"前,看一副喜聞樂見的圖,好像大多數情況下也是這樣用的對吧:

從微信小程式 到 資料庫"小程式" - 鬼知道我經曆了什麼

随着雲計算的普及,雲為我們提供了越來越多的便利,降低了開發和運維的成本。

但是也必須思考一個問題,我們的雲元件之間的網絡延遲有多大(是否可控?),和以前在區域網路是一樣的嗎(相比較區域網路的伺服器和伺服器之間)?

我可能無法給出一個标準的答案,但是你可以用各種方法測試驗證一下。

以往我們把資料放在資料庫,資料庫隻擔當了簡單的增删改查功能,大部分的業務邏輯放在應用伺服器來完成,一個事務可能需要與資料庫進行多次的互動。

那麼應用伺服器和資料庫間如果多次互動,會不會浪費大量的時間在網絡上面呢?這個問題會不會因為網絡延遲而被放大呢?  

有幾份測試資料僅供參考(這裡指的服務端程式設計均指: 資料庫程式設計(比如plpgsql函數,c函數,pljava, plperl, plpython, pltcl, plr等資料庫函數))

從微信小程式 到 資料庫"小程式" - 鬼知道我經曆了什麼
從微信小程式 到 資料庫"小程式" - 鬼知道我經曆了什麼
從微信小程式 到 資料庫"小程式" - 鬼知道我經曆了什麼

看完以上幾組測試資料,知道為什麼要寫"資料庫小程式"了吧。盡量的讓資料和運算靠近,避免多次互動造成的網絡rt放大問題。(當然了,并不是推薦大夥一切都丢給資料庫,還是要有個度的,從圖1我們可以了解到,随着硬體的發展和sharding技術的普及,尺度越來越大可能是個趨勢呢,嘿嘿。)

資料庫小程式也許是這樣的,水乳交融、天人合一,是不是功力大增呢?

從微信小程式 到 資料庫"小程式" - 鬼知道我經曆了什麼

那麼如何編寫"資料庫小程式"呢?

大家可能覺得,隻要資料庫支援函數語言,或者過程語言,就可以編寫"資料庫小程式"了。

這個想法固然沒錯,但是要知道通常資料庫提供的過程語言是比較簡陋的,包括oracle的pl/sql,postgresql的plpgsql在内,雖然它們強大,它也無法與常用的程式設計語言例如go, java, python, r等相提并論,特别是在一些非常專的領域,可能就有非常專業的語言來支撐,比如資料分析領域r語言就首當其沖。

那麼要讓"資料庫小程式"能夠擔當起真正的程式左右,看樣子僅支援資料庫的"簡陋"語言是不夠的。能不能在資料庫中直接支援java, python, perl, tcl, r等流行的程式設計語言呢?

如果有這樣的資料庫,肯定可以歡快的編寫"資料庫小程式"是不是呢。

postgresql是這樣一個資料庫,理論上你可以把任何程式設計語言(隻要是地球語言),作為它的資料庫端程式設計語言,目前已支援的語言就已經好多好多了,以語言插件的方式提供。

c, plpgsql, plpython, plperl, pltcl, plr, pljava, plv8, ..... 恕我叫得出名字的程式設計語言較少,實際上支援的語言數不勝數啊

除了考慮程式設計語言的支援,我們還需要考慮點其他的嗎?

postgresql的開放性不僅僅表現在程式設計能力的擴充方面,在postgresql的生态中有很多貼近業務的用法,比如在postgresql中存儲和處理化學分子、存儲和處理圖像、存儲和處理基因資料、存儲和處理文本(包括高效正則、模糊、全文檢索等技術,文本相似度查詢等)、通路外部任意資料源等。

一些比較有意思的特性如下

1. 支援使用常見的c, plpgsql, plpython, plperl, pltcl, plr, pljava, plv8等語言編寫資料庫端函數,

同時你還可以根據postgresql提供的擴充接口,擴充更多的程式設計語言

<a href="https://www.postgresql.org/docs/devel/static/xplang.html">https://www.postgresql.org/docs/devel/static/xplang.html</a>

2. 資料類型支援豐富,例如支援傳統資料類型外的包括 數組、序列, uuid , jsonb, gis, text, 異構類型,key-value類型(hstore), 全文檢索 , 化學 , 圖像 , 基因 , 外部資料源 ... 等,同時支援自定義擴充類型

3. 支援btree, hash, gin , gist, spgist, brin , rum , bloom等索引類型,

這些索引可以用于支援常見的排序,大于,小于,等于,任意列等于查詢,同時也可以支援異構類型如數組、全文檢索的比對,圖檔文本的相似度排序,交疊查詢,地理位置的運算,knn等,支援塊級索引(在iot場景很好用)等。

同時允許使用者自定義索引接口,支援更多的資料類型。

4. sql文法層面支援大部分2013 sql标準,以及擴充的sql用法: returning, 遊标, 異步消息, ecpg, 視窗查詢,遞歸查詢,grouping set, upsert, skip lock, ad lock 等進階文法。

5. join方面,支援hash join , merge join , nestloop join ,

6. 優化器方面,支援自定義成本因子, cbo , 遺傳算法等。

7. 另外可以利用gpu加速運算,包括隐式加速,也可以顯示加速。

隐式指資料庫自身提供的custom scan provider程式設計接口,已經有實作了的插件。

顯式,指的是過程語言和cuda的結合,例如pycuda。

8. 還可以用支援并行程式設計的語言來友善的實作多核處理,(目前postgresql 9.6已經支援内置的并行計算(包括全表掃描、哈希join,哈希聚合等操作))。

9. 通過fdw接口,通路幾乎任意外部資料

<a href="https://wiki.postgresql.org/wiki/fdw">https://wiki.postgresql.org/wiki/fdw</a>

<a href="https://wiki.postgresql.org/wiki/foreign_data_wrapper">https://wiki.postgresql.org/wiki/foreign_data_wrapper</a>

還有很多特性就不一一介紹了,用到的時候就知道它的好了(來自很多使用者的切身感受)。

postgresql完全可以滿足大多數業務的需求。

更詳細的介紹,請參考

<a href="https://github.com/digoal/blog/blob/master/201609/20160929_02.md">《postgresql 前世今生》</a>

前面說了,理論上你可以把任何程式設計語言(隻要是地球語言),作為postgresql的資料庫端程式設計語言。

那麼如何安裝呢?

安裝擴充語言很簡單,通常隻需要 create extension language_name 即可,目前postgresql系統自帶的語言包括c, python, perl, tcl, plpgsql.

編譯postgresql時帶上對應的參數即可,如果你是通過yum或者rpm安裝的postgresql,那麼下載下傳并安裝對應的擴充語言包就可以了

軟體安裝好後,就會帶對應的擴充語言,例如

在需要使用該語言的資料庫中建立擴充語言,也可以在模闆庫中建立,以後通過模闆庫建立的資料庫就預設帶有這個擴充語言了

以pltcl為例

是不是很簡單呢

通常在pgxn.org, git.postgresql.org, github會比較多。

但是還有一個好的搜尋方法,搜尋pl+語言即可,例如在谷歌搜尋 "pljava postgresql",馬上就搜尋到了

postgresql pl/java – pl/java: stored procedures, triggers, and ...

<a href="https://tada.github.io/pljava/">https://tada.github.io/pljava/</a>

pl/java is a free open-source extension for postgresql? that allows stored ... files can use java annotations from the org.postgresql.pljava.annotation package ...

home · tada/pljava wiki · github

<a href="https://github.com/tada/pljava/wiki">https://github.com/tada/pljava/wiki</a>

pljava - pl/java is a free add-on module that brings java? stored procedures, triggers, and functions to the postgresql? backend.

你除了搜尋現有的資料庫程式設計語言使用,其實還可以貢獻,比如你發現julia語言目前postgresql還不支援作為資料庫内置的程式設計語言怎麼辦?

那也很好辦哦,根據postgresql提供的語言擴充接口,就可以把julia加進來了。

擴充語言包括如下幾個部分,其中language_handler為必須的

1. language_handler,必須為擴充語言建立一個對應的language_handler

2. 當這個擴充語言需要使用do的文法(即不建立函數,直接跑代碼)時,則需要實作一個對應的inline_function

3. 如果需要讓資料庫支援這個語言的函數,在建立函數時檢查内部的代碼,則需要實作對應的validator

postgresql 參數 check_function_bodies = on 時,如果這個擴充語言實作了validator,那麼使用這個擴充語言create function時會自動檢查函數體的内容,比如文法是否正确。

4. 建立擴充語言

編寫擴充語言主要就是實作這幾個内容,包括call handler, inline handler, validator。

範例可以參考postgresql内置的幾個語言的代碼,比如python

postgresql-9.6.1/src/pl/plpython

編寫"資料庫小程式",和你用對應的程式設計語言寫程式是一樣的,隻是資料庫有固定的格式

例如

這裡指的參數類型,傳回類型,都是資料庫的資料類型。

create function的文法詳細參考

<a href="https://www.postgresql.org/docs/devel/static/sql-createfunction.html">https://www.postgresql.org/docs/devel/static/sql-createfunction.html</a>

例子

是不是覺得我舉例太少了,因為編寫"資料庫小程式"确實就是這麼簡單,嘿嘿,代碼的内容完全取決于你的需求。

因為資料庫有自己的類型定義和表達方法,而擴充語言有自己的類型支援。

比如postgresql支援hstore資料類型,而python沒有這個類型,那麼預設情況下python就隻能使用text來表達資料庫的hstore.

postgresql允許使用者自定義資料類型轉換方法,将資料庫支援的類型與擴充語言支援的類型橋梁建立起來。

詳見

<a href="https://github.com/digoal/blog/blob/master/201701/20170110_01.md">《postgresql 資料庫擴充語言程式設計 之 plpgsql - 1》</a>

不用我說,你一定在擔心一個問題,如果"資料庫小程式"寫得爛或者寫的"小程式"有bug,會不會把資料庫搞死?

如果不加控制,是很危險的。不過還好postgresql是程序模式的,要死也隻死調用"小程式"的程序。

同時由于程序模式,我們可以使用cgroup,對每個會話隔離資源,不會因為一個小程式寫得有問題,把資源全部耗光。

cgroup參考

<a href="https://github.com/digoal/blog/blob/master/201606/20160613_1.md">《linux cgroup - cpu與cpuset子系統講解》</a>

<a href="https://github.com/digoal/blog/blob/master/201701/20170111_02.md">《linux cgroup - memory子系統講解》</a>

同時資料庫還對語言進行了比較明确的區分,可信和不可信語言。

所謂可信指不會帶來破壞性的語言,比如不會越權通路包括資料,資料檔案,作業系統檔案等,也沒有import外部庫的功能。

不可信語言,需要超級使用者才能建立,因為它不受任何限制,可以通路檔案,import外部庫,執行系統調用等。

the optional key word trusted specifies that the language does not grant access to data that the user would not otherwise have.

trusted languages are designed for ordinary database users (those without superuser privilege) and allows them to safely create functions and trigger procedures.

since pl functions are executed inside the database server, the trusted flag should only be given for languages that do not allow access to database server internals or the file system.

the languages pl/pgsql, pl/tcl, and pl/perl are considered trusted;

the languages pl/tclu, pl/perlu, and pl/pythonu are designed to provide unlimited functionality and should not be marked trusted.

trusted 指 這個語言不能通路越權的資料(如資料庫伺服器的檔案、資料庫内部(包括直接通路共享記憶體))

untrusted 指 這個語言沒有任何限制,允許通路任何資料(包括檔案,網絡,共享lib庫等,危害性較大),但是功能更加強大。

這個例子使用postgresql的異步消息通知機制(notify/listen),以及資料庫的觸發器,postgis地理庫插件,結合nodejs, socket.io實作了一個實時的用戶端gps坐标更新的小業務。

1. 在資料庫中新增gps坐标,資料庫端編寫的"小程式"會自動發送異步消息給用戶端,用戶端馬上就展示了目前新增的坐标

從微信小程式 到 資料庫"小程式" - 鬼知道我經曆了什麼

2. 修改gps坐标,資料庫端編寫的"小程式"會自動發送異步消息給用戶端,用戶端重新整理了目前坐标

從微信小程式 到 資料庫"小程式" - 鬼知道我經曆了什麼

3. 删除gps坐标,資料庫端編寫的"小程式"會自動發送異步消息給用戶端,用戶端重新整理了目前坐标

從微信小程式 到 資料庫"小程式" - 鬼知道我經曆了什麼

<a href="https://github.com/digoal/blog/blob/master/201701/20170113_02.md">《[轉載] postgres + socket.io + nodejs 實時地圖應用實踐》</a>

1. postgresql通過開放的語言接口,支援了目前地球上大部分的程式設計語言,你可以使用這些語言在資料庫内部直接編寫業務代碼,是不是很神奇,是不是不再需要擔心資料來回搬運了呢,是不是一下把互動扁平化了呢?

2. postgresql以其開放的 資料類型、操作符、索引接口 支援了目前為止我見到的最為豐富的資料類型(數組、序列, uuid , jsonb, gis, text, 異構類型,key-value類型(hstore), 全文檢索 , 化學 , 圖像 , 基因 ,)。

也就是說,你在postgresql裡面操作這些資料,有如神助。

比如

<a href="https://github.com/digoal/blog/blob/master/201612/20161228_01.md">《從天津濱海新區大爆炸、危化品監管聊聊 資料庫如何支援化學分子類型》</a>

<a href="https://github.com/digoal/blog/blob/master/201612/20161225_01.md">《恭迎萬億級營銷(圈人)潇灑的邁入毫秒時代 - 萬億user_tags級實時推薦系統資料庫設計》</a>

<a href="https://github.com/digoal/blog/blob/master/201612/20161220_01.md">《流計算風雲再起 - postgresql攜pipelinedb力挺iot》</a>

<a href="https://github.com/digoal/blog/blob/master/201612/20161213_01.md">《金融風控、公安刑偵、社會關系、人脈分析等需求分析與資料庫實作 - postgresql圖資料庫場景應用》</a>

<a href="https://github.com/digoal/blog/blob/master/201610/20161021_01.md">《基于 阿裡雲 rds postgresql 打造實時使用者畫像推薦系統》</a>

還有很多可以從這裡閱讀

<a href="https://github.com/digoal/blog/blob/master/201701/20170106_01.md">《想挑戰alphago嗎?先和postgresql玩一玩?? postgresql與人工智能(ai)》</a>

3. postgresql還支援外部通路泵,可以擴充,可以通路目前幾乎所有的外部資料源,你甚至可以用它來做冷熱資料分層,資料的異構融合等。

是不是對postgresql心動了呢?快點來建立屬于你的"資料庫小程式吧"。

<a href="https://github.com/digoal/blog/blob/master/201604/20160426_01.md">《iperf 測試網絡性能名額》</a>

<a href="https://github.com/digoal/blog/blob/master/201604/20160428_01.md">《postgresql 網絡延遲 瓶頸定量分析》</a>

<a href="https://github.com/digoal/blog/blob/master/201605/20160505_01.md">《論雲資料庫程式設計能力的重要性》</a>

<a href="https://github.com/digoal/blog/blob/master/201701/20170113_02.md">《[轉載]postgres+socket.io+nodejs實時地圖應用實踐》</a>

<a href="https://github.com/digoal/blog/blob/master/201701/20170113_02.md">《[轉載]postgres + socket.io + nodejs實時地圖應用實踐》</a>