一兩個節點、一兩條命令,輕鬆讓 TiDB 分析場景無痛提速十倍

> 作者:馬曉宇

## 講個故事,假如……

某天,老闆讓你分省統計口罩最近的訂貨數據,以快速決策需要向哪裡調貨。你發起查詢,全部訂單數據多達數億甚至更多,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]。**