自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

TiDB Best Practice

企業(yè)動態(tài)
本文檔用于總結(jié)在使用 TiDB 時候的一些最佳實踐,主要涉及 SQL 使用、OLAP/OLTP 優(yōu)化技巧,特別是一些 TiDB 專有的優(yōu)化開關。

[[198151]]

本文檔用于總結(jié)在使用 TiDB 時候的一些***實踐,主要涉及 SQL 使用、OLAP/OLTP 優(yōu)化技巧,特別是一些 TiDB 專有的優(yōu)化開關。 建議先閱讀講解 TiDB 原理的三篇文章(講存儲說計算,談調(diào)度),再來看這篇文章。

一、前言

數(shù)據(jù)庫是一個通用的基礎組件,在開發(fā)過程中會考慮到多種目標場景,在具體的業(yè)務場景中,需要根據(jù)業(yè)務的實際情況對數(shù)據(jù)的參數(shù)或者使用方式進行調(diào)整。

TiDB 是一個兼容 MySQL 協(xié)議和語法的分布式數(shù)據(jù)庫,但是由于其內(nèi)部實現(xiàn),特別是支持分布式存儲以及分布式事務,使得一些使用方法和 MySQL 有所區(qū)別。

二、基本概念

TiDB 的***實踐與其實現(xiàn)原理密切相關,建議讀者先了解一些基本的實現(xiàn)機制,包括 Raft、分布式事務、數(shù)據(jù)分片、負載均衡、SQL 到 KV 的映射方案、二級索引的實現(xiàn)方法、分布式執(zhí)行引擎。下面會做一點簡單的介紹。

1. Raft

Raft 是一種一致性協(xié)議,能提供強一致的數(shù)據(jù)復制保證,TiDB ***層用 Raft 來同步數(shù)據(jù)。每次寫入都要寫入多數(shù)副本,才能對外返回成功,這樣即使丟掉少數(shù)副本,也能保證系統(tǒng)中還有***的數(shù)據(jù)。比如*** 3 副本的話,每次寫入 2 副本才算成功,任何時候,只丟失一個副本的情況下,存活的兩個副本中至少有一個具有***的數(shù)據(jù)。

相比 Master-Slave 方式的同步,同樣是保存三副本,Raft 的方式更為高效,寫入的延遲取決于最快的兩個副本,而不是最慢的那個副本。所以使用 Raft 同步的情況下,異地多活成為可能。在典型的兩地三中心場景下,每次寫入只需要本數(shù)據(jù)中心以及離得近的一個數(shù)據(jù)中心寫入成功就能保證數(shù)據(jù)的一致性,而并不需要三個數(shù)據(jù)中心都寫成功。但是這并不意味著在任何場景都能構(gòu)建跨機房部署的業(yè)務,當寫入量比較大時候,機房之間的帶寬和延遲成為關鍵因素,如果寫入速度超過機房之間的帶寬,或者是機房之間延遲過大,整個 Raft 同步機制依然無法很好的運轉(zhuǎn)。

2. 分布式事務

TiDB 提供完整的分布式事務,事務模型是在 Google Percolator 的基礎上做了一些優(yōu)化。這里只說兩點:

(1) 樂觀鎖

TiDB 的事務模型采用樂觀鎖,只有在真正提交的時候,才會做沖突檢測,如果有沖突,則需要重試。這種模型在沖突嚴重的場景下,會比較低效,因為重試之前的操作都是無效的,需要重復做。舉一個比較極端的例子,就是把數(shù)據(jù)庫當做計數(shù)器用,如果訪問的并發(fā)度比較高,那么一定會有嚴重的沖突,導致大量的重試甚至是超時。但是如果訪問沖突并不十分嚴重,那么樂觀鎖模型具備較高的效率。所以在沖突嚴重的場景下,推薦在系統(tǒng)架構(gòu)層面解決問題,比如將計數(shù)器放在 Redis 中。

(2) 事務大小限制

由于分布式事務要做兩階段提交,并且底層還需要做 Raft 復制,如果一個事務非常大,會使得提交過程非常慢,并且會卡住下面的 Raft 復制流程。為了避免系統(tǒng)出現(xiàn)被卡住的情況,我們對事務的大小做了限制:

  • 單條 KV entry 不超過 6MB
  • KV entry 的總條數(shù)不超過 30w
  • KV entry 的總大小不超過 100MB

在 Google 的 Cloud Spanner 上面,也有類似的限制。

3. 數(shù)據(jù)分片

TiKV 自動將底層數(shù)據(jù)按照 Key 的 Range 進行分片。每個 Region 是一個 Key 的范圍,從 StartKey 到 EndKey 的左閉右開區(qū)間。Region 中的 Key-Value 總量超過一定值,就會自動分裂。這部分用戶不需要擔心。

4. 負載均衡

PD 會根據(jù)整個 TiKV 集群的狀態(tài),對集群的負載進行調(diào)度。調(diào)度是以 Region 為單位,以 PD 配置的策略為調(diào)度邏輯,自動完成。

5. SQL on KV

TiDB 自動將 SQL 結(jié)構(gòu)映射為 KV 結(jié)構(gòu)。具體的可以參考這篇文檔。簡單來說,TiDB 做了兩件事:

  • 一行數(shù)據(jù)映射為一個 KV,Key 以 TableID 構(gòu)造前綴,以行 ID 為后綴
  • 一條索引映射為一個 KV,Key 以 TableID+IndexID 構(gòu)造前綴,以索引值構(gòu)造后綴

可以看到,對于一個表中的數(shù)據(jù)或者索引,會具有相同的前綴,這樣在 TiKV 的 Key 空間內(nèi),這些 Key-Value 會在相鄰的位置。那么當寫入量很大,并且集中在一個表上面時,就會造成寫入的熱點,特別是連續(xù)寫入的數(shù)據(jù)中某些索引值也是連續(xù)的(比如 update time 這種按時間遞增的字段),會再很少的幾個 Region 上形成寫入熱點,成為整個系統(tǒng)的瓶頸。同樣,如果所有的數(shù)據(jù)讀取操作也都集中在很小的一個范圍內(nèi) (比如在連續(xù)的幾萬或者十幾萬行數(shù)據(jù)上),那么可能造成數(shù)據(jù)的訪問熱點。

6. Secondary Index

TiDB 支持完整的二級索引,并且是全局索引,很多查詢可以通過索引來優(yōu)化。如果利用好二級索引,對業(yè)務非常重要,很多 MySQL 上的經(jīng)驗在 TiDB 這里依然適用,不過 TiDB 還有一些自己的特點,需要注意,這一節(jié)主要討論在 TiDB 上使用二級索引的一些注意事項。

(1) 二級索引是否有多越好

二級索引能加速查詢,但是要注意新增一個索引是有副作用的,在上一節(jié)中我們介紹了索引的存儲模型,那么每增加一個索引,在插入一條數(shù)據(jù)的時候,就要新增一個 Key-Value,所以索引越多,寫入越慢,并且空間占用越大。另外過多的索引也會影響優(yōu)化器運行時間,并且不合適的索引會誤導優(yōu)化器。所以索引并不是越多越好。

(2) 對哪些列建索引比較合適

上面提到,索引很重要但不是越多越好,我們需要根據(jù)具體的業(yè)務特點創(chuàng)建合適的索引。原則上我們需要對查詢中需要用到的列創(chuàng)建索引,目的是提高性能。下面幾種情況適合創(chuàng)建索引:

  • 區(qū)分度比較大的列,通過索引能顯著地減少過濾后的行數(shù)
  • 有多個查詢條件時,可以選擇組合索引,注意需要把等值條件的列放在組合索引的前面

這里舉一個例子,假設常用的查詢是 select * from t where c1 = 10 and c2 = 100 and c3 > 10, 那么可以考慮建立組合索引 Index cidx (c1, c2, c3),這樣可以用查詢條件構(gòu)造出一個索引前綴進行 Scan。

(3) 通過索引查詢和直接掃描 Table 的區(qū)別

TiDB 實現(xiàn)了全局索引,所以索引和 Table 中的數(shù)據(jù)并不一定在一個數(shù)據(jù)分片上,通過索引查詢的時候,需要先掃描索引,得到對應的行 ID,然后通過行 ID 去取數(shù)據(jù),所以可能會涉及到兩次網(wǎng)絡請求,會有一定的性能開銷。

如果查詢涉及到大量的行,那么掃描索引是并發(fā)進行,只要***批結(jié)果已經(jīng)返回,就可以開始去取 Table 的數(shù)據(jù),所以這里是一個并行 + Pipeline 的模式,雖然有兩次訪問的開銷,但是延遲并不會很大。

有兩種情況不會涉及到兩次訪問的問題:

  • 索引中的列已經(jīng)滿足了查詢需求。比如 Table t 上面的列 c 有索引,查詢是 select c from t where c > 10; 這個時候,只需要訪問索引,就可以拿到所需要的全部數(shù)據(jù)。這種情況我們稱之為覆蓋索引(Covering Index)。所以如果很關注查詢性能,可以將部分不需要過濾但是需要再查詢結(jié)果中返回的列放入索引中,構(gòu)造成組合索引,比如這個例子: select c1, c2 from t where c1 > 10; 要優(yōu)化這個查詢可以創(chuàng)建組合索引 Index c12 (c1, c2)。
  • 表的 Primary Key 是整數(shù)類型。在這種情況下,TiDB 會將 Primary Key 的值當做行 ID,所以如果查詢條件是在 PK 上面,那么可以直接構(gòu)造出行 ID 的范圍,直接掃描 Table 數(shù)據(jù),獲取結(jié)果。

(4) 查詢并發(fā)度

數(shù)據(jù)分散在很多 Region 上,所以 TiDB 在做查詢的時候會并發(fā)進行,默認的并發(fā)度比較保守,因為過高的并發(fā)度會消耗大量的系統(tǒng)資源,且對于 OLTP 類型的查詢,往往不會涉及到大量的數(shù)據(jù),較低的并發(fā)度已經(jīng)可以滿足需求。對于 OLAP 類型的 Query,往往需要較高的并發(fā)度。所以 TiDB 支持通過 System Variable 來調(diào)整查詢并發(fā)度。

  1. ref="https://github.com/pingcap/docs-cn/blob/master/sql/tidb-specific.md#tidb_distsql_scan_concurrency">tidbdistsqlscan_concurrency 

在進行掃描數(shù)據(jù)的時候的并發(fā)度,這里包括掃描 Table 以及索引數(shù)據(jù)。

 

  1. ref="https://github.com/pingcap/docs-cn/blob/master/sql/tidb-specific.md#tidb_index_lookup_size">tidbindexlookup_size 

如果是需要訪問索引獲取行 ID 之后再訪問 Table 數(shù)據(jù),那么每次會把一批行 ID 作為一次請求去訪問 Table 數(shù)據(jù),這個參數(shù)可以設置 Batch 的大小,較大的 Batch 會使得延遲增加,較小的 Batch 可能會造成更多的查詢次數(shù)。這個參數(shù)的合適大小與查詢涉及的數(shù)據(jù)量有關。一般不需要調(diào)整。

 

  1. ref="https://github.com/pingcap/docs-cn/blob/master/sql/tidb-specific.md#tidb_index_lookup_concurrency">tidbindexlookup_concurrency 

如果是需要訪問索引獲取行 ID 之后再訪問 Table 數(shù)據(jù),每次通過行 ID 獲取數(shù)據(jù)時候的并發(fā)度通過這個參數(shù)調(diào)節(jié)。

(5) 通過索引保證結(jié)果順序

索引除了可以用來過濾數(shù)據(jù)之外,還能用來對數(shù)據(jù)排序,首先按照索引的順序獲取行 ID,然后再按照行 ID 的返回順序返回行的內(nèi)容,這樣可以保證返回結(jié)果按照索引列有序。前面提到了掃索引和獲取 Row 之間是并行 + Pipeline 模式,如果要求按照索引的順序返回 Row,那么這兩次查詢之間的并發(fā)度設置的太高并不會降低延遲,所以默認的并發(fā)度比較保守??梢酝ㄟ^ ref="https://gihttp://thub.com/pingcap/docs-cn/blob/master/sql/tidb-specific.md#tidb_index_serial_scan_concurrency">tidbindexserialscanconcurrency 變量進行并發(fā)度調(diào)整。

(6) 逆序索引

目前 TiDB 支持對索引進行逆序 Scan,但是速度要比順序 Scan 慢 5 倍左右,所以盡量避免對索引的逆序 Scan。

三、場景與實踐

上一節(jié)我們討論了一些 TiDB 基本的實現(xiàn)機制及其對使用帶來的影響,本節(jié)我們從具體的使用場景出發(fā),談一些更為具體的操作實踐。我們以從部署到支撐業(yè)務這條鏈路為序,進行討論。

1. 部署

在部署之前請務必閱讀 TiDB 部署建議以及對硬件的需求。

推薦通過 TiDB-Ansible 部署 TiDB 集群,這個工具可以部署、停止、銷毀、升級整個集群,非常方便易用。

具體的使用文檔在這里。非常不推薦手動部署,后期的維護和升級會很麻煩。

2. 導入數(shù)據(jù)

如果有 Unique Key 并且業(yè)務端可以保證數(shù)據(jù)中沒有沖突,可以在 Session 內(nèi)打開這個開關: SET @@session.tidb_skip_constraint_check=1;

另外為了提高寫入性能,可以對 TiKV 的參數(shù)進行調(diào)優(yōu),具體的文檔在這里。

請?zhí)貏e注意這個參數(shù):

[raftstore] # 默認為 true,表示強制將數(shù)據(jù)刷到磁盤上。如果是非金融安全級別的業(yè)務場景,建議設置成 false, # 以便獲得更高的性能。 sync-log = true

3. 寫入

上面提到了 TiDB 對單個事務的大小有限制,這層限制是在 KV 層面,反映在 SQL 層面的話,簡單來說一行數(shù)據(jù)會映射為一個 KV entry,每多一個索引,也會增加一個 KV entry,所以這個限制反映在 SQL 層面是:

  • 單行數(shù)據(jù)不大于 6MB
  • 總的行數(shù)*(1 + 索引個數(shù)) < 30w
  • 一次提交的全部數(shù)據(jù)小于 100MB

另外注意,無論是大小限制還是行數(shù)限制,還要考慮 TiDB 做編碼以及事務額外 Key 的開銷,在使用的時候,建議每個事務的行數(shù)不要超過 1w 行,否則有可能會超過限制,或者是性能不佳。

建議無論是 Insert,Update 還是 Delete 語句,都通過分 Batch 或者是加 Limit 的方式限制。

在刪除大量數(shù)據(jù)的時候,建議使用 Delete * from t where xx limit 5000; 這樣的方案,通過循環(huán)來刪除,用 Affected Rows == 0 作為循環(huán)結(jié)束條件,這樣避免遇到事務大小的限制。

如果一次刪除的數(shù)據(jù)量非常大,這種循環(huán)的方式會越來越慢,因為每次刪除都是從前向后遍歷,前面的刪除之后,短時間內(nèi)會殘留不少刪除標記(后續(xù)會被 gc 掉),影響后面的 Delete 語句。如果有可能,建議把 Where 條件細化。舉個例子,假設要刪除 2017-05-26 當天的所有數(shù)據(jù),那么可以這樣做:

  1. for i from 0 to 23: while affected_rows > 0: delete * from t where insert_time >= i:00:00 and insert_time < (i+1):00:00 limit 5000; affected_rows = select affected_rows() 

上面是一段偽代碼,意思就是要把大塊的數(shù)據(jù)拆成小塊刪除,以避免刪除過程中前面的 Delete 語句影響后面的 Delete 語句。

4. 查詢

看業(yè)務的查詢需求以及具體的語句,可以參考這篇文檔,可以通過 SET 語句控制 SQL 執(zhí)行的并發(fā)度,另外通過 Hint 控制 Join 物理算子選擇。

另外 MySQL 標準的索引選擇 Hint 語法,也可以用,通過 Use Index/Ignore Index hint 控制優(yōu)化器選擇索引。

如果是個 OLTP 和 OLAP 混合類型的業(yè)務,可以把 TP 請求和 AP 請求發(fā)送到不同的 tidb-server 上,這樣能夠減小 AP 業(yè)務對于 TP 業(yè)務的影響。 承載 AP 業(yè)務的 tidb-server 推薦使用高配的機器,比如 CPU 核數(shù)比較多,內(nèi)存比較大。

5. 監(jiān)控 & 日志

Metrics 系統(tǒng)是了解系統(tǒng)狀態(tài)的***方法,建議所有的用戶都部署監(jiān)控系統(tǒng)。TiDB 使用 Grafana+Prometheus 監(jiān)控系統(tǒng)狀態(tài),如果使用 TiDB-Ansible 部署集群,那么會自動部署和配置監(jiān)控系統(tǒng)。

監(jiān)控系統(tǒng)中的監(jiān)控項很多,大部分是給 TiDB 開發(fā)者查看的內(nèi)容,如果沒有對源代碼比較深入的了解,并沒有必要了解這些監(jiān)控項。我們會精簡出一些和業(yè)務相關或者是系統(tǒng)關鍵組件狀態(tài)相關的監(jiān)控項,放在一個獨立的面板中,供用戶使用。

除了監(jiān)控之外,查看日志也是了解系統(tǒng)狀態(tài)的常用方法。TiDB 的三個組件 tidb-server/tikv-server/pd-server 都有一個 --log-file 的參數(shù),如果啟動的時候設置了這個參數(shù),那么日志會保存著參數(shù)所設置的文件的位置,另外會自動的按天對 Log 文件做歸檔。如果沒有設置 --log-file 參數(shù),日志會輸出在 stderr 中。

6. 文檔

了解一個系統(tǒng)或者解決使用中的問題***的方法是閱讀文檔,明白實現(xiàn)原理,TiDB 有大量的官方文檔,希望大家在遇到問題的時候能先嘗試通過文檔或者搜索 Issue list 尋找解決方案。官方文檔在這里。如果希望閱讀英文文檔,可以看這里

其中的 FAQ故障診斷章節(jié)建議大家仔細閱讀。另外 TiDB 還有一些不錯的工具,也有配套的文檔,具體的見各項工具的 GitHub 頁面。

四、TiDB 的***適用場景

簡單來說,TiDB 適合具備下面這些特點的場景:

  • 數(shù)據(jù)量大,單機保存不下
  • 不希望做 Sharding 或者懶得做 Sharding
  • 訪問模式上沒有明顯的熱點
  • 需要事務、需要強一致、需要災備

【本文是51CTO專欄機構(gòu)“PingCAP”的原創(chuàng)文章,轉(zhuǎn)載請聯(lián)系作者本人獲取授權(quán)】

戳這里,看該作者更多好文

責任編輯:趙寧寧 來源: 51CTO專欄
相關推薦

2022-09-09 10:24:54

SREZUOYEBANGDevOps

2022-04-25 10:04:58

MySQL性能數(shù)據(jù)

2019-05-07 09:31:41

TiDBMySQL數(shù)據(jù)

2017-06-09 14:22:31

AnsibleTiDB分布式數(shù)據(jù)庫

2010-07-13 16:27:32

CCIE

2022-11-11 19:09:13

架構(gòu)

2017-07-04 09:21:58

TiDBbuilt-in計算框架

2022-03-25 11:11:50

機器學習TiDBSQL

2019-01-25 19:19:28

數(shù)據(jù)工具互聯(lián)網(wǎng)

2023-02-15 08:31:19

2014-11-12 15:49:45

2021-07-14 05:55:12

鴻蒙HarmonyOS應用

2021-02-01 09:35:53

關系型數(shù)據(jù)庫模型

2023-09-28 08:31:11

MySQLTiDB大數(shù)據(jù)

2025-02-17 10:30:01

2024-08-07 10:34:46

2023-03-28 08:58:47

分庫分表TiDB

2020-03-12 08:00:34

MySQL遷移TiDB
點贊
收藏

51CTO技術(shù)棧公眾號