0
  • 聊天消息
  • 系統(tǒng)消息
  • 評(píng)論與回復(fù)
登錄后你可以
  • 下載海量資料
  • 學(xué)習(xí)在線課程
  • 觀看技術(shù)視頻
  • 寫文章/發(fā)帖/加入社區(qū)
會(huì)員中心
創(chuàng)作中心

完善資料讓更多小伙伴認(rèn)識(shí)你,還能領(lǐng)取20積分哦,立即完善>

3天內(nèi)不再提示

當(dāng)MySQL單表記錄數(shù)過大時(shí),增刪改查性能都會(huì)急劇下降

jf_TEuU2tls ? 來源:浩道linux ? 作者:低至一折起 ? 2022-12-15 11:44 ? 次閱讀

當(dāng)MySQL單表記錄數(shù)過大時(shí),增刪改查性能都會(huì)急劇下降

單表優(yōu)化

除非單表數(shù)據(jù)未來會(huì)一直不斷上漲,否則不要一開始就考慮拆分,拆分會(huì)帶來邏輯、部署、運(yùn)維的各種復(fù)雜度,一般以整型值為主的表在千萬級(jí)以下,字符串為主的表在五百萬以下是沒有太大問題的。

而事實(shí)上很多時(shí)候 MySQL 單表的性能依然有不少優(yōu)化空間,甚至能正常支撐千萬級(jí)以上的數(shù)據(jù)量。

字段

  • 盡量使用 TINYINT、 SMALLINT、 MEDIUM_INT 作為整數(shù)類型而非 INT,如果非負(fù)則加上 UNSIGNED

  • VARCHAR 的長度只分配真正需要的空間

  • 使用枚舉或整數(shù)代替字符串類型

  • 盡量使用 TIMESTAMP 而非 DATETIME

  • 單表不要有太多字段,建議在 20 以內(nèi)

  • 避免使用 NULL 字段,很難查詢優(yōu)化且占用額外索引空間

  • 用整型來存 IP

索引

  • 索引并不是越多越好,要根據(jù)查詢有針對(duì)性的創(chuàng)建,考慮在 WHERE 和 ORDER BY

  • 命令上涉及的列建立索引,可根據(jù) EXPLAIN 來查看是否用了索引還是全表掃描

  • 應(yīng)盡量避免在 WHERE 子句中對(duì)字段進(jìn)行 NULL 值判斷,否則將導(dǎo)致引擎放棄使用索引而進(jìn)行全表掃描

  • 值分布很稀少的字段不適合建索引,例如"性別"這種只有兩三個(gè)值的字段

  • 字符字段只建前綴索引

  • 字符字段最好不要做主鍵

  • 不用外鍵,由程序保證約束

  • 盡量不用 UNIQUE,由程序保證約束

  • 使用多列索引時(shí)主意順序和查詢條件保持一致,同時(shí)刪除不必要的單列索引

查詢SQL

  • 可通過開啟慢查詢?nèi)罩緛碚页鲚^慢的 SQL

  • 不做列運(yùn)算:SELECT id WHERE age+1=10,任何對(duì)列的操作都將導(dǎo)致表掃描,它包括數(shù)據(jù)庫教程函數(shù)、計(jì)算表達(dá)式等等,查詢時(shí)要盡可能將操作移至等號(hào)右邊

  • sql 語句盡可能簡單:一條 sql 只能在一個(gè) cpu 運(yùn)算;大語句拆小語句,減少鎖時(shí)間;一條大sql 可以堵死整個(gè)庫

  • 不用 SELECT *

  • OR 改寫成 IN:OR 的效率是 n 級(jí)別, IN 的效率是 log(n) 級(jí)別,IN 的個(gè)數(shù)建議控制在 200 以內(nèi)

  • 不用函數(shù)和觸發(fā)器,在應(yīng)用程序?qū)崿F(xiàn)

  • 避免 %xxx 式查詢

  • 少用 JOIN

  • 使用同類型進(jìn)行比較,比如用 '123' 和 '123' 比, 123 和 123 比

  • 盡量避免在 WHERE 子句中使用 != 或 <> 操作符,否則將引擎放棄使用索引而進(jìn)行全表掃描

  • 對(duì)于連續(xù)數(shù)值,使用 BETWEEN 不用 IN:SELECT id FROM t WHERE num BETWEEN 1 AND 5

  • 列表數(shù)據(jù)不要拿全表,要使用 LIMIT 來分頁,每頁數(shù)量也不要太大

引擎

目前廣泛使用的是 MyISAM 和 InnoDB 兩種引擎:

MyISAM

MyISAM 引擎是 MySQL 5.1 及之前版本的默認(rèn)引擎,它的特點(diǎn)是:

  • 不支持行鎖,讀取時(shí)對(duì)需要讀到的所有表加鎖,寫入時(shí)則對(duì)表加排它鎖

  • 不支持事務(wù)

  • 不支持外鍵

  • 不支持崩潰后的安全恢復(fù)

  • 在表有讀取查詢的同時(shí),支持往表中插入新紀(jì)錄

  • 支持 BLOB 和 TEXT 的前 500 個(gè)字符索引,支持全文索引

  • 支持延遲更新索引,極大提升寫入性能

  • 對(duì)于不會(huì)進(jìn)行修改的表,支持壓縮表,極大減少磁盤空間占用

InnoDB

InnoDB 在 MySQL 5.5 后成為默認(rèn)索引,它的特點(diǎn)是:

  • 支持行鎖,采用 MVCC 來支持高并發(fā)

  • 支持事務(wù)

  • 支持外鍵

  • 支持崩潰后的安全恢復(fù)

  • 不支持全文索引(5.6.4之后版本逐漸開始支持)

總體來講,MyISAM 適合 SELECT 密集型的表,而 InnoDB 適合 INSERT 和 UPDATE 密集型的表

系統(tǒng)調(diào)優(yōu)參數(shù)

可以使用下面幾個(gè)工具來做基準(zhǔn)測(cè)試:

  • sysbench:一個(gè)模塊化,跨平臺(tái)以及多線程的性能測(cè)試工具

  • iibench-mysql:基于 Java 的 MySQL/Percona/MariaDB 索引進(jìn)行插入性能測(cè)試工具

  • tpcc-mysql:Percona 開發(fā)的 TPC-C 測(cè)試工具

具體的調(diào)優(yōu)參數(shù)內(nèi)容較多,具體可參考官方文檔,這里介紹一些比較重要的參數(shù):

  • backlog:backlog 值指出在 MySQL 暫時(shí)停止回答新請(qǐng)求之前的短時(shí)間內(nèi)多少個(gè)請(qǐng)求可以被存在堆棧中。也就是說,如果 MySql 的連接數(shù)據(jù)達(dá)到 maxconnections 時(shí),新來的請(qǐng)求將會(huì)被存在堆棧中,以等待某一連接釋放資源,該堆棧的數(shù)量即 backlog,如果等待連接的數(shù)量超過back_log,將不被授予連接資源??梢詮哪J(rèn)的 50 升至 500

  • wait_timeout:數(shù)據(jù)庫連接閑置時(shí)間,閑置連接會(huì)占用內(nèi)存資源??梢詮哪J(rèn)的 8 小時(shí)減到半小時(shí)

  • maxuserconnection:最大連接數(shù),默認(rèn)為 0 無上限,最好設(shè)一個(gè)合理上限

  • thread_concurrency:并發(fā)線程數(shù),設(shè)為 CPU 核數(shù)的兩倍

  • skipnameresolve:禁止對(duì)外部連接進(jìn)行 DNS 解析,消除 DNS 解析時(shí)間,但需要所有遠(yuǎn)程主機(jī)用 IP 訪問

  • keybuffersize:索引塊的緩存大小,增加會(huì)提升索引處理速度,對(duì) MyISAM 表性能影響最大。對(duì)于內(nèi)存 4G 左右,可設(shè)為 256M 或 384M,通過查詢show status like'key_read%',保證 key_reads / key_read_requests 在 0.1% 以下最好

  • innodbbufferpool_size:緩存數(shù)據(jù)塊和索引塊,對(duì) InnoDB 表性能影響最大。通過查詢show status like'Innodb_buffer_pool_read%',保證(Innodb_buffer_pool_read_requests –
    Innodb_buffer_pool_reads) / Innodb_buffer_pool_read_requests
    越高越好

  • innodbadditionalmempoolsize:InnoDB 存儲(chǔ)引擎用來存放數(shù)據(jù)字典信息以及一些內(nèi)部數(shù)據(jù)結(jié)構(gòu)的內(nèi)存空間大小,當(dāng)數(shù)據(jù)庫對(duì)象非常多的時(shí)候,適當(dāng)調(diào)整該參數(shù)的大小以確保所有數(shù)據(jù)都能存放在內(nèi)存中提高訪問效率,當(dāng)過小的時(shí)候,MySQL 會(huì)記錄 Warning 信息到數(shù)據(jù)庫的錯(cuò)誤日志中,這時(shí)就需要該調(diào)整這個(gè)參數(shù)大小

  • innodblogbuffer_size:InnoDB 存儲(chǔ)引擎的事務(wù)日志所使用的緩沖區(qū),一般來說不建議超過
    32MB

  • querycachesize:緩存 MySQL 中的 ResultSet,也就是一條 SQL 語句執(zhí)行的結(jié)果集,所以僅僅只能針對(duì) select 語句。當(dāng)某個(gè)表的數(shù)據(jù)有任何任何變化,都會(huì)導(dǎo)致所有引用了該表的select 語句在 Query Cache 中的緩存數(shù)據(jù)失效。所以,當(dāng)我們的數(shù)據(jù)變化非常頻繁的情況下,使用 Query Cache 可能會(huì)得不償失。根據(jù)命中率(Qcache_hits / (Qcache_hits + Qcache_inserts) * 100))進(jìn)行調(diào)整,一般不建議太大,256MB 可能已經(jīng)差不多了,大型的配置型靜態(tài)數(shù)據(jù)可適當(dāng)調(diào)大. 可以通過命令show status like'Qcache_%'查看目前系統(tǒng) Query Catch 使用大小

  • readbuffersize:MySql 讀入緩沖區(qū)大小。對(duì)表進(jìn)行順序掃描的請(qǐng)求將分配一個(gè)讀入緩沖區(qū),MySql 會(huì)為它分配一段內(nèi)存緩沖區(qū)。如果對(duì)表的順序掃描請(qǐng)求非常頻繁,可以通過增加該變量值以及內(nèi)存緩沖區(qū)大小提高其性能

  • sortbuffersize:MySql 執(zhí)行排序使用的緩沖大小。如果想要增加 ORDER BY 的速度,首先看是否可以讓 MySQL 使用索引而不是額外的排序階段。如果不能,可以嘗試增加 sortbuffersize 變量的大小

  • readrndbuffer_size:MySql 的隨機(jī)讀緩沖區(qū)大小。當(dāng)按任意順序讀取行時(shí)(例如,按照排序順序),將分配一個(gè)隨機(jī)讀緩存區(qū)。進(jìn)行排序查詢時(shí),MySql 會(huì)首先掃描一遍該緩沖,以避免磁盤搜索,提高查詢速度,如果需要排序大量數(shù)據(jù),可適當(dāng)調(diào)高該值。但 MySql 會(huì)為每個(gè)客戶連接發(fā)放該緩沖空間,所以應(yīng)盡量適當(dāng)設(shè)置該值,以避免內(nèi)存開銷過大

  • record_buffer:每個(gè)進(jìn)行一個(gè)順序掃描的線程為其掃描的每張表分配這個(gè)大小的一個(gè)緩沖區(qū)。如果你做很多順序掃描,可能想要增加該值

  • threadcachesize:保存當(dāng)前沒有與連接關(guān)聯(lián)但是準(zhǔn)備為后面新的連接服務(wù)的線程,可以快速響應(yīng)連接的線程請(qǐng)求而無需創(chuàng)建新的

  • tablecache:類似于 threadcache_size,但用來緩存表文件,對(duì) InnoDB 效果不大,主要用于 MyISAM

升級(jí)硬件

Scale up,這個(gè)不多說了,根據(jù) MySQL 是 CPU 密集型還是 I/O 密集型,通過提升 CPU 和內(nèi)存、使用 SSD,都能顯著提升 MySQL 性能。

讀寫分離

也是目前常用的優(yōu)化,從庫讀主庫寫,一般不要采用雙主或多主引入很多復(fù)雜性,盡量采用文中的其他方案來提高性能。

同時(shí)目前很多拆分的解決方案同時(shí)也兼顧考慮了讀寫分離。

緩存

緩存可以發(fā)生在這些層次:

  • MySQL 內(nèi)部:在系統(tǒng)調(diào)優(yōu)參數(shù)介紹了相關(guān)設(shè)置

  • 數(shù)據(jù)訪問層:比如 MyBatis 針對(duì) SQL 語句做緩存,而 Hibernate 可以精確到單個(gè)記錄,這里緩存的對(duì)象主要是持久化對(duì)象 PersistenceObject

  • 應(yīng)用服務(wù)層:這里可以通過編程手段對(duì)緩存做到更精準(zhǔn)的控制和更多的實(shí)現(xiàn)策略,這里緩存的對(duì)象是數(shù)據(jù)傳輸對(duì)象 DataTransferObject(DTO)

  • Web 層:針對(duì) web 頁面做緩存

  • 瀏覽器客戶端:用戶端的緩存

可以根據(jù)實(shí)際情況在一個(gè)層次或多個(gè)層次結(jié)合加入緩存。

這里重點(diǎn)介紹下服務(wù)層的緩存實(shí)現(xiàn),目前主要有兩種方式:

  • 直寫式(Write Through):在數(shù)據(jù)寫入數(shù)據(jù)庫后,同時(shí)更新緩存,維持?jǐn)?shù)據(jù)庫與緩存的一致性。這也是當(dāng)前大多數(shù)應(yīng)用緩存框架如 Spring Cache 的工作方式。這種實(shí)現(xiàn)非常簡單,同步好,但效率一般。

  • 回寫式(Write Back):當(dāng)有數(shù)據(jù)要寫入數(shù)據(jù)庫時(shí),只會(huì)更新緩存,然后異步批量的將緩存數(shù)據(jù)同步到數(shù)據(jù)庫上。這種實(shí)現(xiàn)比較復(fù)雜,需要較多的應(yīng)用邏輯,同時(shí)可能會(huì)產(chǎn)生數(shù)據(jù)庫與緩存的不同步,但效率非常高。

表分區(qū)

MySQL 在 5.1 版引入的分區(qū)是一種簡單的水平拆分,用戶需要在建表的時(shí)候加上分區(qū)參數(shù),對(duì)應(yīng)用是透明的無需修改代碼

對(duì)用戶來說,分區(qū)表是一個(gè)獨(dú)立的邏輯表,但是底層由多個(gè)物理子表組成,實(shí)現(xiàn)分區(qū)的代碼實(shí)際上是通過對(duì)一組底層表的對(duì)象封裝,但對(duì) SQL 層來說是一個(gè)完全封裝底層的黑盒子。MySQL 實(shí)現(xiàn)分區(qū)的方式也意味著索引也是按照分區(qū)的子表定義,沒有全局索引。

327c7444-7c19-11ed-8abf-dac502259ad0.jpg

用戶的 SQL 語句是需要針對(duì)分區(qū)表做優(yōu)化,SQL 條件中要帶上分區(qū)條件的列,從而使查詢定位到少量的分區(qū)上,否則就會(huì)掃描全部分區(qū),可以通過 EXPLAIN PARTITIONS 來查看某條SQL 語句會(huì)落在那些分區(qū)上,從而進(jìn)行 SQL 優(yōu)化,如下圖 5 條記錄落在兩個(gè)分區(qū)上:

328bbb0c-7c19-11ed-8abf-dac502259ad0.jpg

分區(qū)的好處是:

  • 可以讓單表存儲(chǔ)更多的數(shù)據(jù)

  • 分區(qū)表的數(shù)據(jù)更容易維護(hù),可以通過清楚整個(gè)分區(qū)批量刪除大量數(shù)據(jù),也可以增加新的分區(qū)來支持新插入的數(shù)據(jù)。另外,還可以對(duì)一個(gè)獨(dú)立分區(qū)進(jìn)行優(yōu)化、檢查、修復(fù)等操作

  • 部分查詢能夠從查詢條件確定只落在少數(shù)分區(qū)上,速度會(huì)很快

  • 分區(qū)表的數(shù)據(jù)還可以分布在不同的物理設(shè)備上,從而高效利用多個(gè)硬件設(shè)備

  • 可以使用分區(qū)表賴避免某些特殊瓶頸,例如 InnoDB 單個(gè)索引的互斥訪問、ext3 文件系統(tǒng)的
    inode 鎖競(jìng)爭(zhēng)

  • 可以備份和恢復(fù)單個(gè)分區(qū)

分區(qū)的限制和缺點(diǎn):

  • 一個(gè)表最多只能有 1024 個(gè)分區(qū)

  • 如果分區(qū)字段中有主鍵或者唯一索引的列,那么所有主鍵列和唯一索引列都必須包含進(jìn)來

  • 分區(qū)表無法使用外鍵約束

  • NULL 值會(huì)使分區(qū)過濾無效

  • 所有分區(qū)必須使用相同的存儲(chǔ)引擎

分區(qū)的類型:

  • RANGE 分區(qū):基于屬于一個(gè)給定連續(xù)區(qū)間的列值,把多行分配給分區(qū)

  • LIST 分區(qū):類似于按 RANGE 分區(qū),區(qū)別在于 LIST 分區(qū)是基于列值匹配一個(gè)離散值集合中的某個(gè)值來進(jìn)行選擇

  • HASH 分區(qū):基于用戶定義的表達(dá)式的返回值來進(jìn)行選擇的分區(qū),該表達(dá)式使用將要插入到表中的這些行的列值進(jìn)行計(jì)算。這個(gè)函數(shù)可以包含 MySQL 中有效的、產(chǎn)生非負(fù)整數(shù)值的任何表達(dá)式

  • KEY 分區(qū):類似于按 HASH 分區(qū),區(qū)別在于 KEY 分區(qū)只支持計(jì)算一列或多列,且 MySQL 服務(wù)器提供其自身的哈希函數(shù)。必須有一列或多列包含整數(shù)值

分區(qū)適合的場(chǎng)景有:

最適合的場(chǎng)景數(shù)據(jù)的時(shí)間序列性比較強(qiáng),則可以按時(shí)間來分區(qū),如下所示:

329d551a-7c19-11ed-8abf-dac502259ad0.jpg

查詢時(shí)加上時(shí)間范圍條件效率會(huì)非常高,同時(shí)對(duì)于不需要的歷史數(shù)據(jù)能很容的批量刪除。

如果數(shù)據(jù)有明顯的熱點(diǎn),而且除了這部分?jǐn)?shù)據(jù),其他數(shù)據(jù)很少被訪問到,那么可以將熱點(diǎn)數(shù)據(jù)單獨(dú)放在一個(gè)分區(qū),讓這個(gè)分區(qū)的數(shù)據(jù)能夠有機(jī)會(huì)都緩存在內(nèi)存中,查詢時(shí)只訪問一個(gè)很小的分區(qū)表,能夠有效使用索引和緩存。

另外 MySQL 有一種早期的簡單的分區(qū)實(shí)現(xiàn) - 合并表(merge table),限制較多且缺乏優(yōu)化,不建議使用,應(yīng)該用新的分區(qū)機(jī)制來替代

垂直拆分

垂直分庫是根據(jù)數(shù)據(jù)庫里面的數(shù)據(jù)表的相關(guān)性進(jìn)行拆分。

比如:一個(gè)數(shù)據(jù)庫里面既存在用戶數(shù)據(jù),又存在訂單數(shù)據(jù),那么垂直拆分可以把用戶數(shù)據(jù)放到用戶庫、把訂單數(shù)據(jù)放到訂單庫。

垂直分表是對(duì)數(shù)據(jù)表進(jìn)行垂直拆分的一種方式,常見的是把一個(gè)多字段的大表按常用字段和非常用字段進(jìn)行拆分,每個(gè)表里面的數(shù)據(jù)記錄數(shù)一般情況下是相同的,只是字段不一樣,使用主鍵關(guān)聯(lián)

比如原始的用戶表是:

32cfd6e8-7c19-11ed-8abf-dac502259ad0.jpg

垂直拆分后是:

32e31424-7c19-11ed-8abf-dac502259ad0.jpg

垂直拆分的優(yōu)點(diǎn)是:

  • 可以使得行數(shù)據(jù)變小,一個(gè)數(shù)據(jù)塊( Block )就能存放更多的數(shù)據(jù),在查詢時(shí)就會(huì)減少 I/O 次數(shù)(每次查詢時(shí)讀取的 Block 就少)

  • 可以達(dá)到最大化利用 Cache 的目的,具體在垂直拆分的時(shí)候可以將不常變的字段放一起,將經(jīng)常改變的放一起

  • 數(shù)據(jù)維護(hù)簡單

缺點(diǎn)是:

  • 主鍵出現(xiàn)冗余,需要管理冗余列

  • 會(huì)引起表連接 JOIN 操作(增加 CPU 開銷)可以通過在業(yè)務(wù)服務(wù)器上進(jìn)行 join 來減少數(shù)據(jù)庫壓力

  • 依然存在單表數(shù)據(jù)量過大的問題(需要水平拆分)

  • 事務(wù)處理復(fù)雜

水平拆分

概述

水平拆分是通過某種策略將數(shù)據(jù)分片來存儲(chǔ),分庫內(nèi)分表和分庫兩部分,每片數(shù)據(jù)會(huì)分散到不同的 MySQL 表或庫,達(dá)到分布式的效果,能夠支持非常大的數(shù)據(jù)量。前面的表分區(qū)本質(zhì)上也是一種特殊的庫內(nèi)分表。

庫內(nèi)分表,僅僅是單純的解決了單一表數(shù)據(jù)過大的問題,由于沒有把表的數(shù)據(jù)分布到不同的機(jī)器上,因此對(duì)于減輕 MySQL 服務(wù)器的壓力來說,并沒有太大的作用,大家還是競(jìng)爭(zhēng)同一個(gè)物理機(jī)上的 IO、CPU、網(wǎng)絡(luò),這個(gè)就要通過分庫來解決

前面垂直拆分的用戶表如果進(jìn)行水平拆分,結(jié)果是:

32f5777c-7c19-11ed-8abf-dac502259ad0.jpg

實(shí)際情況中往往會(huì)是垂直拆分和水平拆分的結(jié)合,即將 Users_A_M 和 Users_N_Z 再拆成 Users 和 UserExtras,這樣一共四張表

水平拆分的優(yōu)點(diǎn)是:

  • 不存在單庫大數(shù)據(jù)和高并發(fā)的性能瓶頸

  • 應(yīng)用端改造較少

  • 提高了系統(tǒng)的穩(wěn)定性和負(fù)載能力

缺點(diǎn)是:

  • 分片事務(wù)一致性難以解決

  • 跨節(jié)點(diǎn) Join 性能差,邏輯復(fù)雜

  • 數(shù)據(jù)多次擴(kuò)展難度跟維護(hù)量極大

分片原則

  • 能不分就不分,參考單表優(yōu)化

  • 分片數(shù)量盡量少,分片盡量均勻分布在多個(gè)數(shù)據(jù)結(jié)點(diǎn)上,因?yàn)橐粋€(gè)查詢 SQL 跨分片越多,則總體性能越差,雖然要好于所有數(shù)據(jù)在一個(gè)分片的結(jié)果,只在必要的時(shí)候進(jìn)行擴(kuò)容,增加分片數(shù)量

  • 分片規(guī)則需要慎重選擇做好提前規(guī)劃,分片規(guī)則的選擇,需要考慮數(shù)據(jù)的增長模式,數(shù)據(jù)的訪問模式,分片關(guān)聯(lián)性問題,以及分片擴(kuò)容問題,最近的分片策略為范圍分片,枚舉分片,一致性 Hash 分片,這幾種分片都有利于擴(kuò)容

  • 盡量不要在一個(gè)事務(wù)中的 SQL 跨越多個(gè)分片,分布式事務(wù)一直是個(gè)不好處理的問題

  • 查詢條件盡量優(yōu)化,盡量避免 Select * 的方式,大量數(shù)據(jù)結(jié)果集下,會(huì)消耗大量帶寬和
    CPU 資源,查詢盡量避免返回大量結(jié)果集,并且盡量為頻繁使用的查詢語句建立索引。

  • 通過數(shù)據(jù)冗余和表分區(qū)依賴降低跨庫 Join 的可能

這里特別強(qiáng)調(diào)一下分片規(guī)則的選擇問題,如果某個(gè)表的數(shù)據(jù)有明顯的時(shí)間特征,比如訂單、交易記錄等,則他們通常比較合適用時(shí)間范圍分片,因?yàn)榫哂袝r(shí)效性的數(shù)據(jù),我們往往關(guān)注其近期的數(shù)據(jù),查詢條件中往往帶有時(shí)間字段進(jìn)行過濾,比較好的方案是,當(dāng)前活躍的數(shù)據(jù),采用跨度比較短的時(shí)間段進(jìn)行分片,而歷史性的數(shù)據(jù),則采用比較長的跨度存儲(chǔ)。

總體上來說,分片的選擇是取決于最頻繁的查詢 SQL 的條件,因?yàn)椴粠魏?Where 語句的查詢 SQL,會(huì)遍歷所有的分片,性能相對(duì)最差,因此這種 SQL 越多,對(duì)系統(tǒng)的影響越大,所以我們要盡量避免這種 SQL 的產(chǎn)生。

解決方案

由于水平拆分牽涉的邏輯比較復(fù)雜,當(dāng)前也有了不少比較成熟的解決方案。這些方案分為兩大類:

  • 客戶端架構(gòu)

  • 代理架構(gòu)

客戶端架構(gòu)

通過修改數(shù)據(jù)訪問層,如 JDBC、Data Source、MyBatis,通過配置來管理多個(gè)數(shù)據(jù)源,直連數(shù)據(jù)庫,并在模塊內(nèi)完成數(shù)據(jù)的分片整合,一般以 Jar 包的方式呈現(xiàn)

這是一個(gè)客戶端架構(gòu)的例子:

330d20d4-7c19-11ed-8abf-dac502259ad0.jpg

可以看到分片的實(shí)現(xiàn)是和應(yīng)用服務(wù)器在一起的,通過修改 Spring JDBC 層來實(shí)現(xiàn)

客戶端架構(gòu)的優(yōu)點(diǎn)是:

  • 應(yīng)用直連數(shù)據(jù)庫,降低外圍系統(tǒng)依賴所帶來的宕機(jī)風(fēng)險(xiǎn)

  • 集成成本低,無需額外運(yùn)維的組件

缺點(diǎn)是:

  • 限于只能在數(shù)據(jù)庫訪問層上做文章,擴(kuò)展性一般,對(duì)于比較復(fù)雜的系統(tǒng)可能會(huì)力不從心

  • 將分片邏輯的壓力放在應(yīng)用服務(wù)器上,造成額外風(fēng)險(xiǎn)

代理架構(gòu)

通過獨(dú)立的中間件來統(tǒng)一管理所有數(shù)據(jù)源和數(shù)據(jù)分片整合,后端數(shù)據(jù)庫集群對(duì)前端應(yīng)用程序透明,需要獨(dú)立部署和運(yùn)維代理組件

這是一個(gè)代理架構(gòu)的例子:

331e3374-7c19-11ed-8abf-dac502259ad0.jpg

代理組件為了分流和防止單點(diǎn),一般以集群形式存在,同時(shí)可能需要 Zookeeper 之類的服務(wù)組件來管理

代理架構(gòu)的優(yōu)點(diǎn)是:

  • 能夠處理非常復(fù)雜的需求,不受數(shù)據(jù)庫訪問層原來實(shí)現(xiàn)的限制,擴(kuò)展性強(qiáng)

  • 對(duì)于應(yīng)用服務(wù)器透明且沒有增加任何額外負(fù)載

缺點(diǎn)是:

  • 需部署和運(yùn)維獨(dú)立的代理中間件,成本高

  • 應(yīng)用需經(jīng)過代理來連接數(shù)據(jù)庫,網(wǎng)絡(luò)上多了一跳,性能有損失且有額外風(fēng)險(xiǎn)

各方案比較

框架 出品方 架構(gòu)模型 支持?jǐn)?shù)據(jù)庫 分庫 分表 讀寫分離 外部依賴 是否開源 實(shí)現(xiàn)語言 支持語言 GitHub星數(shù)
MySQL Fabric MySQL官方 代理架構(gòu) MySQL python 無限制 35
Cobar 阿里巴巴 代理架構(gòu) MySQL Java 無限制 1287
Cobar Client 阿里巴巴 客戶端架構(gòu) MySQL Java Java 344
TDDL 淘寶 客戶端架構(gòu) 無限制 Diamond 只開源部分 Java Java 519
Atlas 奇虎360 代理架構(gòu) MySQL C 無限制 1941
Heisenberg 百度熊照 代理架構(gòu) MySQL Java 無限制 197
TribeDB 個(gè)人 代理架構(gòu) MySQL NodeJS 無限制 126
Sharding JDBC 當(dāng)當(dāng) 客戶端架構(gòu) MySQL Java Java 1144
Shark 個(gè)人 客戶端架構(gòu) MySQL Java Java 84
KingShard 個(gè)人 代理架構(gòu) MySQL Golang 無限制 1836
OneProxy 平民軟件 代理架構(gòu) MySQL 未知 無限制 未知
MyCat 社區(qū) 代理架構(gòu) MySQL Java 無限制 1270
Vitess Youtube 代理架構(gòu) MySQL Golang 無限制 3636
Mixer 個(gè)人 代理架構(gòu) MySQL Golang 無限制 472
JetPants Tumblr 客戶端架構(gòu) MySQL Ruby Ruby 957
HibernateShard Hibernate 客戶端架構(gòu) 無限制 Java Java 57
MybatisShard MakerSoft 客戶端架構(gòu) 無限制 Java Java 119
Gizzard Twitter 代理架構(gòu) 無限制 Java 無限制 2087


如此多的方案,如何進(jìn)行選擇?可以按以下思路來考慮:

  • 確定是使用代理架構(gòu)還是客戶端架構(gòu)。中小型規(guī)?;蚴潜容^簡單的場(chǎng)景傾向于選擇客戶端架構(gòu),復(fù)雜場(chǎng)景或大規(guī)模系統(tǒng)傾向選擇代理架構(gòu)

  • 具體功能是否滿足,比如需要跨節(jié)點(diǎn) ORDER BY,那么支持該功能的優(yōu)先考慮

  • 不考慮一年內(nèi)沒有更新的產(chǎn)品,說明開發(fā)停滯,甚至無人維護(hù)和技術(shù)支持

  • 最好按大公司 -> 社區(qū) -> 小公司 -> 個(gè)人這樣的出品方順序來選擇

  • 選擇口碑較好的,比如 GitHub 星數(shù)、使用者數(shù)量質(zhì)量和使用者反饋

  • 開源的優(yōu)先,往往項(xiàng)目有特殊需求可能需要改動(dòng)源代碼

按照上述思路,推薦以下選擇:

  • 客戶端架構(gòu):ShardingJDBC

  • 代理架構(gòu):MyCat 或 Atlas

兼容 MySQL 且可水平擴(kuò)展的數(shù)據(jù)庫

目前也有一些開源數(shù)據(jù)庫兼容 MySQL 協(xié)議,如:

  1. https://github.com/pingcap/tidb

  2. http://www.cubrid.org/

但其工業(yè)品質(zhì)和 MySQL 尚有差距,且需要較大的運(yùn)維投入,如果想將原始的 MySQL 遷移到可水平擴(kuò)展的新數(shù)據(jù)庫中,可以考慮一些云數(shù)據(jù)庫:

  1. https://cn.aliyun.com/product/petadata/?spm=5176.7960203.237031.38.cAzx5r

  2. https://cn.aliyun.com/product/oceanbase?spm=5176.7960203.237031.40.cAzx5r

  3. https://www.qcloud.com/product/dcdbfortdsql.html

NoSQL

在 MySQL 上做 Sharding 是一種戴著鐐銬的跳舞,事實(shí)上很多大表本身對(duì) MySQL 這種
RDBMS 的需求并不大,并不要求 ACID,可以考慮將這些表遷移到 NoSQL,徹底解決水平擴(kuò)展問題,例如:

  • 日志類、監(jiān)控類、統(tǒng)計(jì)類數(shù)據(jù)

  • 非結(jié)構(gòu)化或弱結(jié)構(gòu)化數(shù)據(jù)

  • 對(duì)事務(wù)要求不強(qiáng),且無太多關(guān)聯(lián)操作的數(shù)據(jù)

審核編輯 :李倩


聲明:本文內(nèi)容及配圖由入駐作者撰寫或者入駐合作網(wǎng)站授權(quán)轉(zhuǎn)載。文章觀點(diǎn)僅代表作者本人,不代表電子發(fā)燒友網(wǎng)立場(chǎng)。文章及其配圖僅供工程師學(xué)習(xí)之用,如有內(nèi)容侵權(quán)或者其他違規(guī)問題,請(qǐng)聯(lián)系本站處理。 舉報(bào)投訴
  • 數(shù)據(jù)庫
    +關(guān)注

    關(guān)注

    7

    文章

    3838

    瀏覽量

    64541
  • MySQL
    +關(guān)注

    關(guān)注

    1

    文章

    819

    瀏覽量

    26647

原文標(biāo)題:誰還說不懂MySQL常用優(yōu)化,我就把這個(gè)丟過去!

文章出處:【微信號(hào):浩道linux,微信公眾號(hào):浩道linux】歡迎添加關(guān)注!文章轉(zhuǎn)載請(qǐng)注明出處。

收藏 人收藏

    評(píng)論

    相關(guān)推薦

    華為云 Flexus X 實(shí)例 MySQL 性能加速評(píng)測(cè)及對(duì)比

    基于 sysbench 構(gòu)造測(cè)試表和測(cè)試數(shù)據(jù) 12 3.5 數(shù)據(jù)庫讀寫性能測(cè)試 13 四、業(yè)界 U?系列無加速 MySQL 測(cè)
    的頭像 發(fā)表于 12-25 17:10 ?208次閱讀
    華為云 Flexus X 實(shí)例 <b class='flag-5'>MySQL</b> <b class='flag-5'>性能</b>加速評(píng)測(cè)及對(duì)比

    數(shù)據(jù)庫數(shù)據(jù)恢復(fù)—Mysql數(shù)據(jù)庫表記錄丟失的數(shù)據(jù)恢復(fù)流程

    Mysql數(shù)據(jù)庫故障: Mysql數(shù)據(jù)庫表記錄丟失。 Mysql數(shù)據(jù)庫故障表現(xiàn): 1、Mysql數(shù)據(jù)庫表中無任何數(shù)據(jù)或只有部分?jǐn)?shù)據(jù)
    的頭像 發(fā)表于 12-16 11:05 ?188次閱讀
    數(shù)據(jù)庫數(shù)據(jù)恢復(fù)—<b class='flag-5'>Mysql</b>數(shù)據(jù)庫<b class='flag-5'>表記錄</b>丟失的數(shù)據(jù)恢復(fù)流程

    tlv320aic3101怎樣才能在使用AGC效果的同時(shí),保證SINAD參數(shù)的良好?

    mVRMS 時(shí),輸出信號(hào)出現(xiàn)削峰,此時(shí)SINAD急劇下降。 (2)芯片的總增益為一定值K,通過對(duì)寄存器進(jìn)行設(shè)置,將最終輸出恒定設(shè)置為630 mVRMS 當(dāng)輸出隨輸入的增加,第一次到達(dá)630 mVRMS
    發(fā)表于 11-06 06:51

    電源軌的封裝電感過大怎么辦

    當(dāng)電源軌的封裝電感過大時(shí),可能會(huì)對(duì)電路的性能和穩(wěn)定性產(chǎn)生不利影響,如增加能量損耗、降低效率、增加噪聲等。針對(duì)這一問題,可以采取以下幾種方法來解決:
    的頭像 發(fā)表于 10-01 15:32 ?298次閱讀

    記錄到管理:北斗工作記錄儀如何優(yōu)化工作流程

    在這個(gè)快節(jié)奏的時(shí)代,每一分效率的提升都是企業(yè)競(jìng)爭(zhēng)力的關(guān)鍵。從繁瑣的手工記錄到智能化的數(shù)據(jù)管理,技術(shù)的飛躍正悄然改變著我們的工作方式。頂堅(jiān)北斗工作記錄儀如何成為優(yōu)化工作流程的得力助手,實(shí)現(xiàn)從
    的頭像 發(fā)表于 08-30 11:09 ?291次閱讀
    從<b class='flag-5'>記錄</b>到管理:<b class='flag-5'>單</b>北斗工作<b class='flag-5'>記錄</b>儀如何優(yōu)化工作流程

    磁路飽和對(duì)磁路的等效電感有何影響

    。磁路飽和通常發(fā)生在磁路中磁通密度較高的區(qū)域,如磁芯、磁環(huán)等。 磁路飽和的原因主要有以下幾點(diǎn): 1.1 材料特性:不同的磁性材料具有不同的飽和磁通密度,當(dāng)磁通密度超過材料的飽和磁通密度時(shí),磁導(dǎo)率會(huì)急劇下降,導(dǎo)致磁路飽
    的頭像 發(fā)表于 08-29 15:20 ?1248次閱讀

    精準(zhǔn)記錄,高效分析:北斗現(xiàn)場(chǎng)記錄儀在各行各業(yè)的應(yīng)用

    在這個(gè)信息爆炸、效率至上的時(shí)代,每一個(gè)細(xì)節(jié)的記錄與分析都成為了推動(dòng)行業(yè)進(jìn)步的關(guān)鍵力量。北斗現(xiàn)場(chǎng)記錄儀,作為集高精度定位、高清視頻錄制、智能數(shù)據(jù)分析于一體的創(chuàng)新設(shè)備,正悄然改變著各行各業(yè)的作業(yè)模式
    的頭像 發(fā)表于 08-28 11:46 ?377次閱讀
    精準(zhǔn)<b class='flag-5'>記錄</b>,高效分析:<b class='flag-5'>單</b>北斗現(xiàn)場(chǎng)<b class='flag-5'>記錄</b>儀在各行各業(yè)的應(yīng)用

    索尼日本裁員應(yīng)對(duì)光盤需求下滑

    近日,索尼公司宣布將在其位于日本東北部的可記錄媒體制造廠進(jìn)行大規(guī)模裁員,共計(jì)250名員工將受到影響。此次裁員的主要原因是隨著流媒體服務(wù)的日益普及,消費(fèi)者對(duì)傳統(tǒng)光盤媒體的需求急劇下降,導(dǎo)致市場(chǎng)銷量萎縮。
    的頭像 發(fā)表于 07-02 16:07 ?1252次閱讀

    電感飽和會(huì)有怎么樣的后果

    電感飽和是指電感器的磁芯達(dá)到其磁化曲線的飽和區(qū),此時(shí)磁芯的磁導(dǎo)率急劇下降,導(dǎo)致電感值顯著降低。
    的頭像 發(fā)表于 05-06 15:22 ?5215次閱讀

    MySQL的整體邏輯架構(gòu)

    支持多種存儲(chǔ)引擎是眾所周知的MySQL特性,也是MySQL架構(gòu)的關(guān)鍵優(yōu)勢(shì)之一。如果能夠理解MySQL Server與存儲(chǔ)引擎之間是怎樣通過API交互的,將大大有利于理解MySQL的核心
    的頭像 發(fā)表于 04-30 11:14 ?474次閱讀
    <b class='flag-5'>MySQL</b>的整體邏輯架構(gòu)

    如何通過PCB接地設(shè)計(jì)實(shí)現(xiàn)環(huán)路面積最小化

    對(duì)于低頻磁場(chǎng)屏蔽采用高磁導(dǎo)率材料的選擇非常重要,磁導(dǎo)率會(huì)隨外界磁場(chǎng)強(qiáng)度的變化而變。當(dāng)外加磁場(chǎng)強(qiáng)度較低時(shí),磁導(dǎo)率會(huì)隨磁場(chǎng)強(qiáng)度的增加而升高,而當(dāng)外加的磁場(chǎng)強(qiáng)度超過某限值時(shí),磁導(dǎo)率就會(huì)急劇下降,此時(shí)磁導(dǎo)材料發(fā)生了磁飽和,也意味著該材料
    發(fā)表于 02-28 11:43 ?3327次閱讀
    如何通過PCB接地設(shè)計(jì)實(shí)現(xiàn)環(huán)路面積最小化

    運(yùn)算放大器電路的放大倍數(shù)為什么不能太大或太小呢?

    或過小都會(huì)對(duì)電路的性能產(chǎn)生不良影響。本文將詳細(xì)討論為什么放大倍數(shù)不能過大或過小,并對(duì)其原因進(jìn)行詳實(shí)而細(xì)致的解釋。 首先,讓我們討論為什么放大倍數(shù)過大會(huì)引起問題。
    的頭像 發(fā)表于 02-04 09:32 ?3676次閱讀

    HID燈的啟動(dòng)順序

    放電開始后,需要提供足夠的電流(使功率高于額定值的四分之一,但不超過額定電流的兩倍)。輝光放電時(shí)的燈管阻抗為1kΩ以上,因此需要比額定電壓高很多的燈管電壓。當(dāng)電極上形成熱點(diǎn)并開始電弧放電時(shí),燈阻抗急劇下降。
    發(fā)表于 02-02 17:02 ?625次閱讀
    HID燈的啟動(dòng)順序

    鴻蒙ArkUI開發(fā)-實(shí)現(xiàn)增刪Tab頁簽

    本文以瀏覽器中增加或刪除頁簽為例,實(shí)現(xiàn)Tabs中頁簽的增刪功能。
    的頭像 發(fā)表于 01-29 18:43 ?1613次閱讀
    鴻蒙ArkUI開發(fā)-實(shí)現(xiàn)<b class='flag-5'>增刪</b>Tab頁簽

    阿里二面:了解MySQL事務(wù)底層原理嗎

    MySQL 是如何來解決臟寫這種問題的?沒錯(cuò),就是鎖。MySQL 在開啟一個(gè)事務(wù)的時(shí)候,他會(huì)將某條記錄和事務(wù)做一個(gè)綁定。這個(gè)其實(shí)和 JVM 鎖是類似的。
    的頭像 發(fā)表于 01-18 16:34 ?355次閱讀
    阿里二面:了解<b class='flag-5'>MySQL</b>事務(wù)底層原理嗎