MySQL 與 PostgreSQL
查詢效能比較
假設 table 有 id (PK)、name, age 三個欄位,且在 name, age 有分別創建索引。
Example
SELECT p.*
FROM person p
WHERE p.id > 10;
- Select 全部的欄位
- Innodb 直接從 clustered index 搜尋
- PostgreSQL 需要用指標去 heap table找
因此 MySQL 會比較快。
Example
SELECT p.*
FROM person p
WHERE p.age > 50;
- Select 全部的欄位
- 查詢條件是 non-clustered index, Innodb 必須再去 clustered index 搜尋
因此 PostgreSQL 會比較快。
Example
SELECT p.name
FROM person p
WHERE p.name = "Jojo";
由於是覆蓋索引查詢,跟是用 cluster index 還是 heap table 就沒有關係了,因此不會有太大差異。
MySQL (InnoDB) | PostgreSQL | |
---|---|---|
儲存資料的地方 | IOT (Index-Organized Table) | heap table |
有查詢效能優勢的情境 | 以 cluster index 查詢時 | 以 non-cluster index 查詢時 |
Isolation
MySQL
- 用 Read View 和 Undo Log 實現 MVCC
- Read Committed 下每一次的 select 都會產生新的 Read View
- Repeatable Read 下只有第一次的 select 產生 Read View
Warning
MySQL 的 Repeatable Read 會有 lost update /write non repeatable read /phantom read 問題,因為只有 select 讀的是 READ VIEW
Example
sessnio1 | session2 |
---|---|
start transaction repeatable read; | |
select amount from user*balance where id = 'Kenny'; /* return 100 */ | |
start transaction repeatable read; | |
select amount from user*balance where id = 'Kenny'; /* return 100 */ | |
update user_balance set amount = amount - 90 where id = 'Kenny'; | |
commit; | |
update user_balance set amount = amount - 90 where id = 'Kenny'; /* return -80 */ | |
commit; |
解法:
- 樂觀鎖
- select … for update
- table constraint
PostgreSQL
- 用 WAL 實現 MVCC
- 沒有 Gap Lock 跟 Next-Key Lock
- For Update 只對指定的 record 加上 X lock
- 在 Repeatable Read 下只會考慮 tx 開始前的 committed 版本,改動資料會檢查該 record 是否存在 tx 開始後的 committed 版本,有的話就會強制 rollback