> 作者:馬曉宇
## 講個故事,假如……
某天,老闆讓你分省統計口罩最近的訂貨資料,以快速決策需要向哪裡調貨。你發起查詢,全部訂單資料多達數億甚至更多,TiDB 不得不花費一小段時間。由于存儲節點在全力計算,你的叢集波動的監控哔哔作響,主站的訂單送出也一下子變得慢起來。倒了杯咖啡回來,你得到了結果。
老闆站在你身後,聲音低沉而有磁性,“能否更快一點?”
請架構師吃了頓飯,她向你推薦将資料從線上導出到 Hadoop 或者分析型資料庫,用列存格式存儲,這樣就可以大大提速。碼農們加班加點,将 ETL 作業架設起來。你驚喜地發現,查詢快了很多!
你興奮地跟老闆說:“我們的分析已經變快了,也不會影響線上業務,您可以放心提要求。”
“幹得好!馬上告訴我過去 48 小時上海闆藍根的銷量。”
“啊?我們隻能查一天前的資料……”
**是以,你需要更快:接入業務更快,資料到達更快,查詢也需要更快。**
## 一兩個節點,一兩條指令,數倍提速
**即将随着 TiDB 3.1 推出的 TiFlash 産品,可以讓你的 AP 查詢提升數倍,不需要複雜的操作,無需多少節點,輕輕松松。隻要将叢集更新到 TiDB 3.1+,然後執行如下兩條指令:**
```
./run_tiflash.sh
mysql> ALTER TABLE orders SET TIFLASH REPLICA 1;
```
然後再發起查詢查詢,對比一下,體驗數倍甚至十幾倍的提速。沒有互相幹擾,資料永遠保持最新(而不僅僅是新鮮),TiDB 會自動或者按照使用者意願選取行存或列存。
TiDB 加入了對 TiFlash 的讀取支援同時,也将列存納入優化器代價估算中。**這意味着,作為使用者,你可以無需選擇使用 TiKV 還是 TiFlash 進行查詢,可以簡單丢給優化器完成;另一方面,如果你有業務隔離的需求,也可以簡單執行如下指令強制隔離:**
```
set @@session.tidb_isolation_read_engines = "tiflash";
```
## 有多快?
放兩個使用者的實際案例,SQL 是經過脫敏的,但是不會影響實際執行時間。事實上,我們也建議你用自己的真實場景進行測試,而非某種 Benchmark。
測試使用如下三節點的 TiFlash 和 TiKV 進行對比:
>**CPU:**
>40 Cores, Intel(R) Xeon(R) CPU E5-2630 v4 @ 2.20GHz @ 1268.383 MHz
>**Mem:**
>188G @ 2133 MHz
>**OS:**
>centos-release-7-6.1810.2.el7.centos.x86_64
>**Disk:**
>NVME SSD
### 查詢 1
```
SELECT code, COUNT(DISTINCT order_id) FROM shipping_order
WHERE ( prod_id in ( 'T1', 'C4', 'Z1', 'F15', 'C21', 'D01' ) ) AND cannel_shipping = 'N' AND drop_order = 'N' AND order_type = '01' AND vip_flag = 'N' AND TIMESTAMPDIFF(HOUR, create_time, NOW()) > 2 AND DW_is_enabled = 1
GROUP BY prod_id;
```
其中 `ipping_order` 表為 100 列,6 千萬行的送貨單表。查詢使用 TiDB。這是一個典型的銷售訂單多元分析統計(聚合類)查詢。
| Engine | Time |
| :------: | :----: |
| TiKV | 30.91 sec|
| TiFlash | 1.94 sec |
使用 TiFlash 查詢提速接近 16 倍。單表的統計聚合是最能展現 TiFlash 引擎加速效果的場景。借助高效的向量化引擎以及列存,計算可以完全下推到 TiFlash 進行,加速效果爆炸。
### 查詢 2
```sql
SELECT prod_code, prod_name, SUM(sales_qty)
FROM shipping_order a JOIN shipping_order_detail b
ON a.order_no = b.shipping_order_no AND a.prod_id = b.prod_id
WHERE a.cannel_shipping = 'N' AND
a.drop_order = 'N' AND a.shipping_order_type = '01' AND
a.discount_is_enabled = 1 AND b.discount_is_enabled = 1 AND a.prod_id in ('C003') AND
a.order_time >= '2019-11-18 00:00:00.0' AND
b.ts >= '2019-11-18 00:00:00.0'
GROUP BY prod_code, prod_name
ORDER BY SUM(qty_ordered) DESC LIMIT 10;
```
其中 `shipping_order_detail` 表為 50 列,1 億行的送貨明細表。查詢使用 TiDB。這是一個典型的銷售訂單關聯後再多元分析統計查詢(表連接配接+聚合)。
| Engine | Time |
| :------: | :----: |
| TiDB + TiKV | 23.74 sec|
| TiDB + TiFlash | 3.90 sec |
這個場景下,使用 TiFlash 查詢提速 6 倍多。哪怕表連接配接仍需在 TiDB 中進行,但是批量掃表仍然可以體驗到明顯的加速。
以上均為使用者測試場景。該使用者實際測試場景在次元無法建立索引的情況下,幾乎都可以觀測到 2 至 10 倍以上的加速。須知,你在多元分析場景下,往往無法為很多元度建立索引。
### 對比 Greenplum
那麼對比 Greenplum,TiFlash 配合分布式計算引擎 TiSpark 又能達到什麼樣的速度呢?

測試使用了 TPC-H 标準測試,橫軸為運作時間(越短越好),灰色是 TiFlash + TiSpark,藍色為 Greenplum 行存,橙色為 Greenplum 列存。
可以看到,TiFlash + TiSpark 在做到無縫鏡像的同時,能取得和 Greenplum 近似甚至更快的速度。
## 除了速度之外,還有何特點?
### 簡化技術棧
TiFlash 并不是另一個系統,也無需維護複雜的資料搬運,無需考慮資料的新老和一緻性。TiFlash 可以近似看做是一種特殊的 TiKV 節點,它可以一樣地通過 Mult-Raft 和 PD 排程無縫擴充,提供對等的協處理器讀取服務,隻是它在分析查詢場景下更快。
### 新鮮且一緻的資料
你仍然享有最新的資料,而不用像做 ETL 搬運那樣,在搬運周期之間隻能讀取老的資料。讀取也總可以捕捉最新的資料(而不僅僅是新鮮資料):你總是可以保證讀到剛寫下去的資料,但也不會捕獲未完成的事務。TiFlash 提供了和 TiKV 一樣的一緻性和事務隔離級别。
### 隔離
關閉 TiDB 自動選擇,或者用 TiSpark 開啟 TiFlash 模式,那麼你是在使用 TiFlash 的 HTAP 模式。簡單說,你不希望某些大型分析查詢幹擾任何正在運作的其他業務,用 TiFlash 你可以很容易做到,僅僅是一個開關配置的問題。這種模式下,你可以放心地對線上資料進行分析,随時觀察業務的最新走向,而不用擔心業務是否受到影響。
### 智能
關閉隔離設定,你可以讓 TiDB 自主選擇。如果你的業務對隔離要求不敏感,你隻是希望很簡單地讓 TiDB 以它判斷下最快的方式通路表,可以走行存 + 索引,也可以走列存,你完全不想操心,那你可以依靠 TiDB 使用統計資訊進行自動選擇。這個設計并不神秘,選擇 TiFlash 副本的過程和在不同索引之間做選擇沒什麼差别。
## 說正經的,TiFlash 是什麼?
**TiFlash 是一種特殊的存儲節點:**
- **它提供了對 TiDB 的加速功能;**
- **它繼承了 TiDB 存儲架構的無縫擴充性;**
- **它可以在不影響正常線上業務的同時,将資料轉存為列存并提供查詢;**
- **并且這個轉存,除了格式和通路速度不同,對使用者來說是完全一樣的鏡像。**
一直以來,TiDB 作為 HTAP 資料庫存在兩個大缺憾:使用行存格式很難快速響應大型分析查詢;進行 AP 查詢會影響 TP 業務穩定。其實這不隻是 TiDB 的缺憾,也是業界面臨的兩個很難調和的設計沖突。
- **存儲格式的沖突**
列存儲存時會拆列和壓縮,對于點查類通路帶來了很大困難,你需要将散落在不同磁盤位置的列資料分别讀取再拼接起來。但是列存對于分析查詢卻是非常高效的:它可以僅僅讀取查詢選中的列,并且列存格式也天然契合向量化加速引擎,是以它也成為了分析場景的推薦格式。如何調和這樣的沖突?
- **分析和交易無法穩定共存的沖突**
分析查詢往往耗時更長,單次查詢通路的資料量比線上交易業務類大得多。分析引擎設計上傾向于同時将大量資源投入同一個查詢,以做到盡快響應。但是一旦這麼做了,線上業務資源将受到擠占,造成巨大抖動。
**為了解決這個問題,業界最常見的做法是,将資料導出到其他平台用列存轉儲,比如 Hadoop + Parquet,或者分析型資料庫如 Greenplum 等,這樣使用者可以同時解決隔離以及查詢性能問題。但是代價卻是,引入了複雜的架構,需要維護資料遷移和 ETL 作業,并且資料無法實時,導出也可能無法保證一緻性。**
**TiFlash 是為了解決這個痛點而設計的産品。它是一款支援更新的列存引擎,在實時鏡像行存資料的同時,提供數倍乃至數十倍以上的對行存的通路加速。它可以使用獨立節點,以完全隔絕兩種業務之間的互相影響。它部分基于 Clickhouse,繼承了 Clickhouse 優秀的向量化計算引擎。**
架構上,TiFlash 是一個提供與 TiKV 類似功能的存儲層子產品,它使用 Raft Learner(<https://etcd.io/docs/v3.3.12/learning/learner/>)進行資料傳輸并轉存為列存。這意味着,TiFlash 節點的狀态和延遲,不會影響 TiKV 的運作,哪怕 TiFlash 節點崩潰,TiKV 也能毫無影響地運作;另一方面也可以提供最新(線性一緻 + 快照隔離),和 TiKV 一緻的資料。
## 何不試試看?
你可以使用一兩台現成的機器進行測試,簡單一兩條指令,上線 TiFlash 節點,添加列存副本,等副本同步完成之後就可以看到效果,綠色無害。何不試試看呢?
**TiFlash 已經在進行第一輪使用者測試,并在 2 到 3 月間會開啟開放公測,請關注後續資訊,也歡迎聯系詢問提前體驗:[email protected]。**