MySQL 8.0 將會實作「真正的」Descending Indexes

在「MySQL 8.0 Labs – Descending Indexes in MySQL」這邊看到 MySQL 打算在 8.0 時實作出真正的 Descending Indexes。在 5.7 以及之前的版本,可以從「14.1.14 CREATE INDEX Syntax」看到這個參數是~假~的~XDDD

An index_col_name specification can end with ASC or DESC. These keywords are permitted for future extensions for specifying ascending or descending index value storage. Currently, they are parsed but ignored; index values are always stored in ascending order.

所以當 8.0 建立了 a_desc_b_asc (a DESC, b ASC) 這樣的 index,可以看到對於不同 ORDER BY 時效能的差異:(一千萬筆資料)

有些變快可以理解,但有些結果不太清楚造成的原因...

Anyway,對於變慢的兩個 query,他提了一個不算解法的解法,就是加上對應的 index XDDD:

If user wants to avoid filesorts for Query 5 and Query 6, he/she can alter the table to add a key (a ASC, b ASC) . Further to this, if the user wants to avoid backward index scans too, he/she can add both ( a ASC, b DESC) and (a DESC, b DESC).

這樣就會變快,但寫入的 overhead 會增加啊... XD

但不管怎樣,總算是把這個功能生出來了...

Percona XtraDB Cluster 5.7 (Galera Cluster)

Percona 放出 PXC 5.7 了:「Percona XtraDB Cluster 5.7.14-26.17 GA is now available」。

主要的效能提昇還是基於 MySQL 5.7 上面,不過要注意的是有些預設值有改變 (尤其是 5.6 -> 5.7 最有名的 sync_binlog 設定),如果當初沒有特別指定的話,效能會掉不少,這點 Percona 整理了不少資料出來,可以翻一下 Percona 網站得到結果。

不過整體上改善了不少,在 5.6 需要一些手動設定的值以確保在 heavy loading 時不會拖垮系統效能 (也就是常說的「卡 query」),在 5.7 變得自動化了。像是 innodb_thread_concurrency 之前的建議都是設在 CPU logical threads 數量以確保當 threads 數量破千時還是有慢慢消化的能力 (讓 DBA 可以不用介入),在 5.7 不需要設定就跑得不錯了。

Amazon EC2 推出 m4.16xlarge

Amazon EC2m4 系列推出更大台的機器,m4.16xlarge:「Expanding the M4 Instance Type – New M4.16xlarge」。

先前 m4 最大的是是 m4.10xlarge,現在則是往上拉... 比較特別的是這款機器可以吃到 20Gbps (跟之前出的 x1.32xlarge 相同),更早推出的 m4.10xlarge,以及 {c4,c3,g2,r3,i2,d2}.8xlarge 都只能吃到 10Gbps。

選擇會更活一點... 不過到這個等級的應用應該都規劃過 scale 架構才對?雖然也是有可能有那種買來的 application 啦...

用 Rust 寫的 ripgrep

平常一直被大量使用的工具就會有人一直花時間改善,這次是 grep 系列的工具:「ripgrep is faster than {grep, ag, git grep, ucg, pt, sift}」。

ripgrep 是用 Rust 寫的強化版 grep 工具,也就是類似於 ag 或是 ack 的工具,但想辦法讓執行的速度更快,盡可能接近於原始 grep 的速度。

Google 研發出的 BBR: Congestion-Based Congestion Control

Google 針對 TCP 的 congestion control 研究出了新的方法,是個純 sender-side 的演匴法,可以讓現有的 internet 直接換上去使用:「[net-next,14/14] tcp_bbr: add BBR congestion control」。

在 long-lived TCP connection 愈來愈普及後 (像是 HTTP/2),TCP 連線的最佳化可以用統計模型來計算,這也就是 BBR 的想法:

In a nutshell, BBR creates an explicit model of the network pipe by sequentially probing the bottleneck bandwidth and RTT. On the arrival of each ACK, BBR derives the current delivery rate of the last round trip, and feeds it through a windowed max-filter to estimate the bottleneck bandwidth. Conversely it uses a windowed min-filter to estimate the round trip propagation delay. The max-filtered bandwidth and min-filtered RTT estimates form BBR's model of the network pipe.

不過 QUIC 不是也開始有進展了嗎?(參考「Google Chrome 52 預設開啟了更快的 QUIC (被戲稱為 TCP/2)」這篇)

感覺 QUIC 解決的比較徹底,不過 443/udp 的 firewall 問題的確也是個需要時間解決的課題...

MySQL 5.6 到 5.7 改變的預設值

Percona 整理了一份 MySQL 5.6 到 5.7 改變的預設值,對於評估與轉移的人都很有用:「MySQL Default Configuration Changes between 5.6 and 5.7」。

sync_binlog 居然從 0 改成 1 了,這對效能的影響應該不少。

performance_schema_* 有不少改成自動調整了,可以省下不少功夫。

innodb_buffer_pool_dump_at_shutdowninnodb_buffer_pool_load_at_startup 都打開了,這避免了正常重啟時的 warm up 問題,不過在存在有效的手段可以手動 warm up 的時,應該還是會關掉吧。(參考 2013 的文章「熱 MySQL InnoDB 的方式...」)

另外介紹了 InnoDB 預設格式的改變,這點到是因為使用 COMPRESSED,反而不太受到影響。

MySQL 8.0 的 performance_schema 加上 index 了...

MySQL 8.0 是 MySQL 5.7 的後續版本,中間的 6.0 與 7.0 都有一些故事,就被跳過去了,跟 PHP 的情況有點像。

在 8.0 版將會把 performance_schamea 加上 index,讓查詢的速度變快:「MySQL 8.0: Performance Schema, now with indexes!」:

In MySQL 8.0, performance_schema tables are now indexed to speed up data retrieval.

A total of 115 indexes have been added in the performance schema in MySQL 8.0.0, to support better data access patterns in general.

有用過 performance_schema 的人都會有種「這好慢啊」的感覺,總算要改善了... 而且這幾乎是沒什麼成本的改善:

Question: How much overhead was just added by this new feature?
Answer: Absolutely zero

並不是用 index 加快速度,而是加了一些資訊,修正 optimizer 的行為:

It does — not — maintain a physical index internally, be it on file or memory.
It does, however, — pretend — to the optimizer that it has indexes, so that the optimizer is coerced into using the most efficient access pattern.

在有些情況下可以看到會快非常的多:

The performance improvements from indexes can be very easily seen in many of the sys schema queries. With 1000 idle threads, the query SELECT * FROM sys.session drops from 34.70 seconds down to 1.01 seconds (a 30x improvement!):

不知道 Percona 會不會 backport 回來,這看起來對於爆炸中的 server 找問題會很有幫助,可以在短時間翻出是哪個部份爆炸...

CPU 指令的速度

在「Infographics: Operation Costs in CPU Clock Cycles」這邊看到張有趣的圖片:

文章大致說明了底層指令速度差異的由來,另外也提到了 C/C++ Function Calls、Indirect and Virtual Calls、Allocations、Kernel Calls、C++ Exceptions 以及 Thread Context Switches 這些高階面向的 CPU clock cycle 差異...

不過重點還是在這張圖 XD

Python 3.6 對 Dict 的改善

Python 3 的 Dict 將會有重大的改變:「[Python-Dev] Python 3.6 dict becomes compact and gets a private version; and keywords become ordered」。

在 3.5 時:

Python 3.5.1 (default, Jun 20 2016, 14:48:22)
>>> def func(**kw): print(kw.keys())
...
>>> func(a=1, b=2, c=3, d=4, e=5)
dict_keys(['c', 'd', 'e', 'b', 'a'])   # random order

對上目前還在開發的 3.6:

Python 3.6.0a4+ (default:d43f819caea7, Sep  8 2016, 13:05:34)
>>> def func(**kw): print(kw.keys())
...
>>> func(a=1, b=2, c=3, d=4, e=5)
dict_keys(['a', 'b', 'c', 'd', 'e'])   # expected order

在「Compact and ordered dict」這邊可以看到記憶體的使用量降低:

It seems like the memory usage is between 20% and 25% smaller. Great job!

Memory usage, Python 3.5 => Python 3.6 on Linux x86_64:

./python -c 'import sys; print(sys.getsizeof({str(i):i for i in range(10)}))'

* 10 items: 480 B => 384 B (-20%)
* 100 items: 6240 B => 4720 B (-24%)
* 1000 items: 49248 B => 36984 B (-25%)

Note: the size is the the size of the container itself, not of keys nor values.

不過效能上似乎慢了一些:

3% slowdown in microbench is not surprising.
Compact dict introduces one additional indirection.

Instead, I've added freelist for most compact PyDictKeys.
So I think overall performance is almost same to before compact dict.

不過也有人提到應該拿 3.5 + patch 測,而不是直接拿 3.6 測:

There are a lot of other changes in interpreter core between 3.5 and 3.5 (such as new bytecode and optimized function calls). Could you compare the performance between the version just before adding new dict implementation and the version just after this?

看起來後續還在進行中...