PostgreSQL 的 Bloom index

前幾天才跟人提到 PostgreSQL 的功能與完整性比 MySQL 多不少,剛剛又看到 Percona 的「Bloom Indexes in PostgreSQL」這篇,裡面提到了 PostgreSQL 可以使用 Bloom filter 當作 index。

查了一下資料是從 PostgreSQL 9.6 支援的 (參考「PostgreSQL: Documentation: 9.6: bloom」這邊的說明),不過說明裡面沒看到 DELETE (以及 UPDATE) 會怎麼處理,因為原版的 Bloom filter 資料結構應該沒有能力處理刪除的情況...

另外這幾年比較有名的應該是 Cuckoo filter,不只支援刪除,而且空間與效能都比 Bloom filter 好,不知道為什麼是實做 Bloom filter...

在 SQL 裡面避免大量刪除資料的方式

看到 Percona 的「An Overview of Sharding in PostgreSQL and How it Relates to MongoDB’s」這篇,雖然是在講 PostgreSQL 上的 sharding (以及 partition),突然想到好像沒寫過要怎麼避免大量刪除資料的操作...

一個常見的情境是,想要讓某個表格只保留這一個月的資料,所以每個月開頭都會跑一隻 cron job 負責刪掉上個月的資料,像是 DELETE FROM xxx WHERE timestamp < yyy; 這樣的指令。

這個方式無論是在 PostgreSQL 或是 MySQL 都需要很多時間與 I/O 資源,而透過 partition 將不同時間區段切開到不同的表格,再用 TRUNCATE 直接清空表格剛好可以解這樣的問題。

Percona 的文章裡說了一些 PostgreSQL 的歷史與目前的進展。

在 PostgreSQL 9 或更早以前的版本,一個常見的作法是透過 table inheritance 實做 partition,然後用再用 function 實做 INSERT

CREATE TABLE temperature (
  id BIGSERIAL PRIMARY KEY NOT NULL,
  city_id INT NOT NULL,
  timestamp TIMESTAMP NOT NULL,
  temp DECIMAL(5,2) NOT NULL
);

CREATE TABLE temperature_201901 (CHECK (timestamp >= DATE '2019-01-01' AND timestamp <= DATE '2019-01-31')) INHERITS (temperature);
CREATE TABLE temperature_201902 (CHECK (timestamp >= DATE '2019-02-01' AND timestamp <= DATE '2019-02-28')) INHERITS (temperature);
CREATE TABLE temperature_201903 (CHECK (timestamp >= DATE '2019-03-01' AND timestamp <= DATE '2019-03-31')) INHERITS (temperature);

CREATE OR REPLACE FUNCTION temperature_insert_trigger()
RETURNS TRIGGER AS $$
BEGIN
    IF ( NEW.timestamp >= DATE '2019-01-01' AND NEW.timestamp <= DATE '2019-01-31' ) THEN INSERT INTO temperature_201901 VALUES (NEW.*);
    ELSIF ( NEW.timestamp >= DATE '2019-02-01' AND NEW.timestamp <= DATE '2019-02-28' ) THEN INSERT INTO temperature_201902 VALUES (NEW.*);
    ELSIF ( NEW.timestamp >= DATE '2019-03-01' AND NEW.timestamp <= DATE '2019-03-31' ) THEN INSERT INTO temperature_201903 VALUES (NEW.*);
    ELSE RAISE EXCEPTION 'Date out of range!';
    END IF;
    RETURN NULL;
END;
$$
LANGUAGE plpgsql;

在 PostgreSQL 10 之後,就直接支援一些與 partition 相關的設計,像是這樣:

CREATE TABLE temperature (
  id BIGSERIAL NOT NULL,
  city_id INT NOT NULL,
  timestamp TIMESTAMP NOT NULL,
  temp DECIMAL(5,2) NOT NULL
) PARTITION BY RANGE (timestamp);

CREATE TABLE temperature_201901 PARTITION OF temperature FOR VALUES FROM ('2019-01-01') TO ('2019-02-01');
CREATE TABLE temperature_201902 PARTITION OF temperature FOR VALUES FROM ('2019-02-01') TO ('2019-03-01');
CREATE TABLE temperature_201903 PARTITION OF temperature FOR VALUES FROM ('2019-03-01') TO ('2019-04-01');

雖然還是有些限制,但可以看出比起以前簡單不少。

而有了 partition 後,文章的後續就在討論這跟 MongoDB 的 sharding 有什麼關係,但這就不是我關注的事情了...

CockroachDB 也拋棄 Open Source License 了

CockroachDB 的主力在於 PostgreSQL 的相容層 (包括底層資料結構,SQL 語法,以及 Protocol,所以原有的 client 不需要太多修改就可以用),並且提供橫向擴充的能力 (實作類似於 F1 與 Spanner 這些論文的功能)。

現在他們也宣佈拋棄 Open Source License 了,從本來的 Apache License 2.0 轉為他們自己定義的 Business Source License:「Why We’re Relicensing CockroachDB」。

最大的差異就是擋提供服務:

The one and only thing that you cannot do is offer a commercial version of CockroachDB as a service without buying a license.

商業版本最終會以 open source license 釋出,但會有三年延遲 (以現在的社群速度,基本上就等於不提供了),不算太意外,但這樣的話也需要先從可用的列表上移除了...

PostgreSQL 的 Don't Do This

Hacker News Daily 上看到的資料,整理了 PostgreSQL 上不要使用的功能:「Don't Do This」,而且是放在官方網域 wiki.postgresql.org 上。

裡面這些想法不知道出處是哪邊... 有不少功能算是 PostgreSQL 特有的功能 (以 open source RDBMS 這個領域來看),而且大概也還想的到用的場景,你卻在上面叫大家不要用,再寫的時候大概是吸了一批很純的,已經不知道要從哪邊開始吐槽...

要看的話連同 Hacker News 上的留言一起看會比較有前因後果:「https://news.ycombinator.com/item?id=19817531」。

DynamoDB 也有固定的 IP address 區段了

AWS 宣佈 DynamoDB 也有固定的 IP address 區段了:「AWS specifies the IP address ranges for Amazon DynamoDB endpoints」,對於使用 IP firewall 的人可以多一些控制權。

資料可以在 https://ip-ranges.amazonaws.com/ip-ranges.json 這邊抓到,裡面 serviceDYNAMODB 的就是了。

因為沒看到 IPv6 的位置,才發現 DynamoDB 目前沒有提供 IPv6 Endpoint...

PostgreSQL 裡的 B-tree 結構

在「Indexes in PostgreSQL — 4 (Btree)」這邊看到講 PostgreSQLB-tree 結構以及常見的查詢會怎麼使用 B-tree。

裡面講了三種查詢,第一種是等號的查詢 (Search by equality),第二種是不等號的查詢 (Search by inequality),第三種是範圍的查詢 (Search by range)。再後面講到排序與 index 的用法。

雖然是分析 PostgreSQL,但裡面是一般性的概念,其他使用 B-tree 結構的資料庫也是類似作法...

Amazon Aurora with PostgreSQL 支援 Logical Replication

AWS 先前宣佈 Amazon Aurora (MySQL) 支援 GTID Replication (參考「Amazon Aurora with MySQL 5.7 支援 GTID」),現在則是宣佈 Amazon Aurora with PostgreSQL 支援 Logical Replication:「Amazon Aurora with PostgreSQL Compatibility Supports Logical Replication」。

如同預期的,要新版的才支援:

Logical replication is supported with Aurora PostgreSQL versions 2.2.0 and 2.2.1, compatible with PostgreSQL 10.6.

有 Logical Replication 可以多做很多事情,像是雲端與外部 PostgreSQL 服務的串接 (e.g. 即時拉一份到 IDC 機房)。另外有些 ETL 工具也可以透過這個方式取得資料庫上改變了什麼東西。

Amazon Aurora with MySQL 5.7 支援 GTID

雖然在 AWS 上服務的 HA 大多都不需要自己管理,但備份機制 (甚至異地備援) 還是要自己規劃,Amazon Aurora with MySQL 的 GTID 功能算是讓這塊多了一個選擇:「Amazon Aurora with MySQL 5.7 Compatibility Supports GTID-Based Replication」。

公告裡面有提到 Aurora 自己的 replication 還是用自己的機制,而非透過 GTID 做的:

This provides complete consistency when using binlog replication between an Aurora database and an external MySQL database. Your replication won’t miss transactions or generate conflicts, even after failover or downtime. (Note that replication within an Aurora cluster doesn't use binlog files, so the GTID feature doesn't apply.)

不過就 Aurora 的架構來說,整個 cluster 比較像是看作一個整體,用 binlog + position 應該是夠用的?也不會有 failover 時的 conflict 問題?不確定用 GTID 的好處會在哪邊,還得再想看看...

在 Galera Cluster 上的 DDL 操作 (e.g. ALTER TABLE)

Percona 整理了一份關於 Galara Cluster 上 DDL 操作的一些技巧,這包括了 Percona XtraDB ClusterMariaDB 的版本:「How to Perform Compatible Schema Changes in Percona XtraDB Cluster (Advanced Alternative)?」。

在不知道這些技巧前,一般都是拿 Percona Toolkit 裡的 pt-online-schema-change 來降低影響 (可以降的非常低),所以這些技巧算是額外知識,另外在某些極端無法使用 pt-online-schema-change 的情境下也可以拿來用...

裡面的重點就是 wsrep_OSU_method 這個參數,預設的值 TOI 就是一般性的常識,所有的指令都會被傳到每一台資料庫上執行,而 RSU 則是會故意不讓 DDL 操作 (像是 ALTER TABLE) 被 replicate 到其他機器,需要由管理者自己到每台機器上執行。

利用這個設定,加上透過工具將流量導到不同後端的資料庫上,就有機會分批進行修改,而不需要透過 pt-online-schema-change 這種工具。

把 MySQL 的 binlog 功能再拆出來的 mysql-ripple

看到 Percona 的「MySQL Ripple: The First Impression of a MySQL Binlog Server」這篇提到了 Google 放出來的專案 mysql-ripple

這個軟體的情境是針對有很多 replica (slave) 時的情境,要解決每一個 replica 都會對 master server 產生壓力,算是 binlog 的 cache layer。

MySQL Ripple 抓了 binlog 下來後就可以模擬成 mysql server (但是只能提供 binlog 服務) 讓 replica 接,在 replica 很多的情境下就可以橫向擴充,而且因為軟體只支援 GTID 模式,所以比較好做 HA 架構 (相對於 filename + position 模式)。

大概可以歸納出是 write 很多 (所以 binlog 量很大),但又有大量 replica 需求的情境... 目前好像想不出來有什麼情境可以拿出來用 :o