Amazon RDS 支援 ARM 架構的 t4g 與 x2g

這兩篇剛好一起看,Amazon RDS 支援了 ARM 架構的 t4gx2g:「Amazon RDS now supports X2g instances for MySQL, MariaDB, and PostgreSQL databases.」與「Amazon RDS now supports T4g instances for MySQL, MariaDB, and PostgreSQL databases.」。

目前主要是關注 t4g,因為目前量的關係反而是大量使用 t4g 類的機器,如果上面的 PostgreSQL 可以跑 t4g 的話,看起來只要沒有買 RI 的可以換過去,主要是比 t3 再省一些錢:以新加坡區的 PostgreSQL 來說,db.t4g.micro 目前是 $0.025/hr,而 db.t3.micro 則是 $0.028/hr,差不多是九折。

沒意外的話效能應該也會提昇一些,不過用 t 系列的機器本來就沒有太大的量在上面跑,這點應該是還好...

Percona 連載到 PostgreSQL 存 JSON object 以及增加 Index 的方式了...

先前 Percona 的人在講 MySQL 存 JSON object 的方式,現在開始講在 PostgreSQL 裡存 JSON object,並且增加 index 的方式了:「Storing and Using JSON Within PostgreSQL Part One」。

這基本上就是不想用 MongoDB,但還是有需要極為彈性而選擇用 JSON object 的需求。

首先先先建立一個表格,這邊直接用 JSONB:

alice=# CREATE TABLE table1 (id SERIAL PRIMARY KEY, jb JSONB);

接著拿「A dataset of English plaintext jokes」這邊的 reddit_jokes.json 來玩,我先把 JSON 裡面的內容變成 JSON Lines 格式:

cat reddit_jokes.json | jq -c '.[]' > reddit_jokes.jsonl

然後 COPY 了十次,多一點資料,後面可以看效能:

alice=# COPY table1 (jb) FROM '/tmp/reddit_jokes.jsonl' CSV QUOTE e'\x01' DELIMITER e'\x02';
-- (repeat this command 10 times)

接著跑個 SELECT 看看速度,我跑了幾次大約都在 260ms 上下:

alice=# SELECT COUNT(*) FROM table1 WHERE (jb->>'score')::int = 10;
 count 
-------
 25510
(1 row)

Time: 264.023 ms

然後針對 score 生個數字的 index:

alice=# CREATE INDEX ON table1 (((jb->>'score')::int));
CREATE INDEX
Time: 1218.503 ms (00:01.219)

接著再跑 SELECT 下去,可以看到速度快超多:

alice=# SELECT COUNT(*) FROM table1 WHERE (jb->>'score')::int = 10;
 count 
-------
 25510
(1 row)

Time: 12.735 ms

另外也可以加 column:

alice=# ALTER TABLE table1 ADD COLUMN score INT GENERATED ALWAYS AS ((jb->>'score')::int) STORED;

然後可以看到速度也不快:

alice=# SELECT COUNT(*) FROM table1 WHERE score = 10;
 count 
-------
 25510
(1 row)

Time: 222.163 ms

幫他補 index:

alice=# CREATE INDEX ON table1 (score);

速度有變快,但不知道為什麼沒有 JSONB 的版本快:

alice=# SELECT COUNT(*) FROM table1 WHERE score = 10;
 count 
-------
 25510
(1 row)

Time: 81.346 ms

算是還蠻好用的,不過得學 JSON query 語法... (應該是還好)

在本機用 pip 直接安裝 PostgreSQL server

看到 PostgreSQL 官方站台上的介紹,可以直接用 Pythonpip 指令安裝 PostgreSQL server:「Install a local, non-root PostgreSQL Server with Python "pip"」,專案在「postgresql-wheel」這邊。

GitHub 上面的說明跑了一下,還真的可以惡搞... 這樣如果真的要在 CI 裡面跑的話也簡單很多了?只要能 pip 裝軟體就能跟你拼 XDDD

也省掉需要設定一些權限跑 Docker-in-Docker...

Amazon Aurora PostgreSQL 多支援了一些 extension

Amazon Aurora PostgreSQL 多支援了一些 extension,剛好看到一些對我還蠻有用的東西。

第一個是 pg_cron,就如同名字所說的,可以拿來安排 cron job:「Amazon Aurora PostgreSQL supports pg_cron extension for scheduling database jobs」。

第二個是 pg_proctab,可以拿來看系統狀態,這在 Aurora 裡面算是沒有 shell 的替代方案:「Amazon Aurora PostgreSQL Supports the pg_proctab Extension to access PostgreSQL system stats」。

第三個是 pg_partman,可以對 serial id 切到不同的 partition:「Amazon Aurora PostgreSQL supports the pg_partman extension for managing time or serial id based table partitioning」。

這幾個在一定的量下應該都用的到...

PostgreSQL 的 Job Queue、Application Lock 以及 Pub/Sub

Hacker News Daily 上看到一篇講 PostgreSQL 做 Job Queue、Application Lock 以及 Pub/Sub 的方法:「Do You Really Need Redis? How to Get Away with Just PostgreSQL」,對應的討論在「Do you really need Redis? How to get away with just PostgreSQL (atomicobject.com)」這邊可以翻到。

拿 PostgreSQL 跑這些東西的確有點浪費,不過如果是自己的專案,不想要把 infrastructure 搞的太複雜的話,倒是還不錯。

首先是 Job Queue 的部份,從他的範例看起來他是在做 async job queue (不用等回傳值的),這讓我想到很久前寫的 queue service (應該是 2007 年與 2012 年都寫過一次),不過我是用 MySQL 當作後端,要想辦法降低 InnoDB 的 lock 特性。

async job queue 設計起來其實很多奇怪的眉角,主要就是在怎麼處理失敗的狀態。大多數的需求可以放到兩個種類,最常見用的是 at-least-once,保證最少跑一次,大多數從設計上有設計成 idempotence 的都可以往這類丟,像是報表類的 (重複再跑一次昨天的報表是 OK 的),另外每天更新會員狀態也可以放在這邊。

另外少見一點的是 at-most-once 與 exactly-once,最多只跑一次與只跑一次,通常用在不是 idempotence 的操作上,像是扣款之類的,這邊的機制通常都會跟商業邏輯有關,反正不太好處理...

第二個是 Application Lock,跨機器時的 lock 機制,量沒有很大時拿 PostgreSQL 跑還行,再大就要另外想辦法了,馬上想到的是 ZooKeeper,但近年設計的系統應該更偏向用 etcdConsul 了...

最後提到的 Pub/Sub,一樣是在量大的時候拿 PostgreSQL 跑還行,更大的時候就要拿 Kafka 這種專門為了效能而設計出來的軟體出來用...

Amazon RDS 上 PostgreSQL 的不停機升級

Hacker News Daily 上看到「Zero downtime Postgres migration, done right」這篇,講 PostgreSQL 9.5 不停機的前提下升級到 12.5 的方式,而且是在 Amazon RDS 上:

We have successfully used this process to migrate our Postgres databases from version 9.5 to 12.5 on RDS, but the process isn’t restricted to RDS only, and does not depend on anything AWS specific.

然後整個重點就在一張圖:

其實幾個 open source database 在這塊的基本概念都類似,用 replication 的技巧升級。

這邊作者選的是用 Bucardo 同步資料,然後舊的與新的 replication 都是雙向的,這樣在切換應用程式的時候就比較不會有時間差的問題。

這邊值得說的是,PostgreSQL 10 (2017 年十月出) 之後因為有了 logical replication,這種不停機持續性的 replication 選擇就變多了,不一定要用 trigger-based replication。作者這邊應該是因為 PostgreSQL 9.5 的關係,所以需要挑了 Bucardo。

另外一個重點是,如果你可以允許短時間的停機 (十分鐘之類的),那就可以改用單向的 replication 升級。因為你可以先停掉舊的資料庫,確保所有的資料都已經更新到新的資料庫,再把應用程式切換到新的資料庫上。

而這套方法如同作者說的,不限於 AWS 家的產品,其他家也可以使用類似的方法,在傳統實體機房也可以這樣做。

另外在 Hacker News 上的討論「Zero downtime Postgres migration, done right (theblueground.com)」很正常的又在戰 MySQL 在這塊的成熟度好太多,看看就好 XDDD

PostgreSQL 上可以列出建議增加 index 的 extension

Twitter 上看到 Percona 家老大貼他們自家 2019 年的舊文章:「Automatic Index Recommendations in PostgreSQL using pg_qualstats and hypopg」。

先說一下,因為要另外裝 extension,目前 Amazon RDS 上面是沒辦法用的,但自己管理的 PostgreSQL 就可以考慮看看。

看了一下文章裡面介紹的兩個 extension,一個是 HypoPG,另外一個是 pg_qualstats,看起來組合技可以提供不少有用的建議。

目前只有針對 B-tree index 提供建議,但這應該已經相當足夠了,大多數的場景下應該都是用 B-tree:

With this experiment, we see that we can use hypopg and pg_qualstats to automate index recommendations. The automation logic is currently limited to B-Tree Indexes only.

另外看 Percona 的 PostgreSQL 文章都會習慣翻了一下作者的背景 (之前被雷過),看起來作者 Avinash Vallarapu 在今年年初已經離開 Percona,成立自己的公司 MigOps 提供 PostgreSQL 相關的服務了...

PostgreSQL 的 Fuzzy Matching

在「Fuzzy Name Matching in Postgres」這邊看到 PostgreSQL 下怎麼設計 Fuzzy Matching 的方式,文章裡用的方法主要是出自 PostgreSQL 的文件:「F.15. fuzzystrmatch」。

文章最後的解法是 Soundex + Levenshtein

翻了一下資料,這個領域另外有 NYSIIS (New York State Identification and Intelligence System):

The New York State Identification and Intelligence System Phonetic Code, commonly known as NYSIIS, is a phonetic algorithm devised in 1970 as part of the New York State Identification and Intelligence System (now a part of the New York State Division of Criminal Justice Services). It features an accuracy increase of 2.7% over the traditional Soundex algorithm.

以及 Metaphone

Metaphone is a phonetic algorithm, published by Lawrence Philips in 1990, for indexing words by their English pronunciation. It fundamentally improves on the Soundex algorithm by using information about variations and inconsistencies in English spelling and pronunciation to produce a more accurate encoding, which does a better job of matching words and names which sound similar. As with Soundex, similar-sounding words should share the same keys. Metaphone is available as a built-in operator in a number of systems.

不過這些都是以英文為主,中文的沒特別翻到...

PostgreSQL 的 scale 建議

Hacker News Daily 上看到「Postgres scaling advice for 2021」這篇,講 PostgreSQL 要怎麼 scale,在 Hacker News 上也有對應的討論可以看:「Postgres scaling advice (cybertec-postgresql.com)」。

文章前面先提到分散式系統的複雜度會導致 RDBMS 上的一些假設失效,所以如果可以用單台機器暴力解,就儘量用單台機器來解 (scale up 的情境),裡面就提到了一些「暴力可以解決很多問題」的說明,差不多就是前幾天提到的「Let's Encrypt 升級資料庫伺服器 (AMD YES?)」。

後面提到如果真的要放進分散式的 RDBMS (scale out 的情境),怎麼設計資料結構會比較好。

這邊剛好也可以提一下,量夠大的時候要把 OLTPOLAP 的應用分開,現在有很多 OLAP 資料庫可以選擇,同步的工具也很成熟了,通常效能會比在 OLTP 上面硬跑來的好。

最後提一下,文章裡面對於 transaction per second 可以拉很高,有些假設沒有明寫出來。這需要盡可能把 transaction 拆小,避免常常有 giant transaction 卡住整個資料庫,這點對於一般的系統會需要做不少改寫...

不過最後比較疑惑的是,這種文章怎麼會上 Hacker News 的啊...

用 GPT-3 直接產生對應的 SQL query

Hacker News Daily 上看到的東西,直接給 GPT-3 條件,叫 GPT-3 給出對應的 SQL query,這就有點誇張了...:「Automating My Job with GPT-3」。

這樣丟進去:

Instruction: Given an input question, respond with syntactically correct PostgreSQL. Be creative but the SQL must be correct.

Input: how many users signed up in the past month?

然後這樣出來:

GPT-3 Response: SELECT COUNT(*) FROM users
WHERE signup_time > now() - interval '1 month'

把欄位名稱替換掉就可以用了... 而且接下來就更誇張了,直接要求 GPT-3 也要照著設定的 table schema 給答案:

Instruction: Given an input question, respond with syntactically correct PostgreSQL. Be creative but the SQL must be correct. Only use tables called "users" and "charges". The "users" table has columns: id (integer), signup_dt (timestamp), email (character varying), and plan_type (character varying). The "charges" table has columns: amount (bigint), user_id (integer), and charge_dt (timestamp).

Input: how much revenue did we have in the past 7 days?

然後輸出了:

GPT-3 Response: SELECT SUM(amount) FROM charges WHERE charge_dt > now() - interval '7 days'

接下來是在同樣 instruction 下,跨表格的問題:

Input: how much revenue have we had from users that signed up in the last 6 months?

這時候 INNER JOIN 就跑出來了:

.8 Temperature GPT-3 Response: SELECT SUM(charges.amount) FROM users INNER JOIN charges ON users.id = charges.user_id WHERE signup_dt >= DATE_SUB(now(), INTERVAL '6 months')

後面的問題也很精彩,看起來之後可以接上 BI dashboard,直接丟句子進去,然後拉各種資料出來視覺化?