[轉帖]

https://cloud.tencent.com/developer/article/1999970

之前也是 想重建表 但是沒有理論依舊

原作者對 mysql的存儲和二級索引的解釋真好. 

 

個人創作公約:本人聲明創作的所有文章皆爲自己原創,如果有參考任何文章的地方,會標註出來,如果有疏漏,歡迎大家批判。如果大家發現網上有抄襲本文章的,歡迎舉報,並且積極向這個 github 倉庫 提交 issue,謝謝支持~

本文是“爲什麼我建議”系列第三篇,本系列中會針對一些在高併發場景下,我對於組內後臺開發的一些開發建議以及開發規範的要求進行說明和分析解讀,相信能讓各位在面對高併發業務的時候避開一些坑。 往期回顧:

一般現在對於業務要查詢的數據量以及要保持的併發量高於一定配置的單實例 MySQL 的極限的情況,都會採取分庫分表的方案解決。當然,現在也有很多 new SQL 的分佈式數據庫的解決方案,如果你用的是 MySQL,那麼你可以考慮 TiDB(實現了 MySQL 協議,兼容 MySQL 客戶端以及 SQL 語句)。如果你用的是的 PgSQL,那麼你可以考慮使用 YugaByteDB(實現了 PgSQL 協議,兼容 PgSQL 客戶端以及 SQL 語句),他們目前都有自己的雲部署解決方案,你可以試試:

但是對於傳統分庫分表的項目,底層的數據庫還是基於 MySQL 以及 PgSQL 這樣的傳統關係型數據庫。一般在業務剛開始的時候,會考慮按照某個分片鍵多分一些表,例如訂單表,我們估計用戶直接要查的訂單記錄是最近一年內的。如果是一年前的,提供其他入口去查,這時候查的就不是有業務數據庫了,而是歸檔數據庫,例如 HBase 這樣的。例如我們估計一年內用戶訂單,最多不會超過 10 億,更新的併發 TPS (非查詢 QPS)不會超過 10 萬/s。那麼我們可以考慮分成 64 張表(個數最好是 2^n,因爲 2^n 取餘數 = 對 2^n - 1 取與運算,減少分片鍵運算量)。然後我們還會定時的歸檔掉一年前的數據,使用類似於 delete from table 這樣的語句進行“徹底刪除”(注意這裏是引號的刪除)。這樣保證業務表的數據量級一直維持在

然而,日久天長以後,會發現,某些帶分片鍵(這裏就是用戶 id)的普通查詢,也會有些慢,有些走錯本地索引。

查詢越來越慢的原因

例如這個 SQL:

代碼語言:javascript
複製
select * from t_pay_record
WHERE
((
	user_id = 'user_id1' 
	AND is_del = 0 
)) 
ORDER BY
	id DESC 
	LIMIT 20

這個表的分片鍵就是 user_id

一方面,正如我在“爲什麼我建議在複雜但是性能關鍵的表上所有查詢都加上 force index”中說的,數據量可能有些超出我們的預期,導致某些分片表大於一定界限,導致 MySQL 對於索引的隨機採樣越來越不準,由於統計數據不是實時更新,而是更新的行數超過一定比例纔會開始更新。並且統計數據不是全量統計,是抽樣統計。所以在表的數據量很大的時候,這個統計數據很難非常準確。依靠表本身自動刷新數據機制,參數比較難以調整(主要是 STATS_SAMPLE_PAGES 這個參數,STATS_PERSISTENT 我們一般不會改,我們不會能接受在內存中保存,這樣萬一數據庫重啓,表就要重新分析,這樣減慢啓動時間,STATS_AUTO_RECALC 我們也不會關閉,這樣會導致優化器分析的越來越不準確),很難預測出到底調整到什麼數值最合適。並且業務的增長,用戶的行爲導致的數據的傾斜,也是很難預測的。通過 Alter Table 修改某個表的 STATS_SAMPLE_PAGES 的時候,會導致和 Analyze 這個 Table 一樣的效果,會在表上加讀鎖,會阻塞表上的更新以及事務。所以不能在這種在線業務關鍵表上面使用。所以最好一開始就能估計出大表的量級,但是這個很難。

所以,我們考慮對於數據量比較大的表,最好能提前通過分庫分表控制每個表的數據量,但是業務增長與產品需求都是不斷在迭代並且變複雜的。很難保證不會出現大並且索引比較複雜的表。這種情況下需要我們,在適當調高 STATS_SAMPLE_PAGES 的前提下,對於一些用戶觸發的關鍵查詢 SQL,使用 force index 引導它走正確的索引

但是,有時候即使索引走對了,查詢依然有點慢。具體去看這個 SQL 掃描的數據行數的時候,發現並沒有很多。

代碼語言:javascript
複製
+----+-------------+--------------+------------+-------+-----------------------------------------------------------------------------------------+-------------+---------+------+-------+----------+-------------+
| id | select_type | table        | partitions | type  | possible_keys                                                                           | key         | key_len | ref  | rows  | filtered | Extra       |
+----+-------------+--------------+------------+-------+-----------------------------------------------------------------------------------------+-------------+---------+------+-------+----------+------
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章