首先采用Mysql存儲(chǔ)千億級(jí)的數(shù)據(jù),確實(shí)是一項(xiàng)非常大的挑戰(zhàn)。Mysql單表確實(shí)可以存儲(chǔ)10億級(jí)的數(shù)據(jù),只是這個(gè)時(shí)候性能非常差,項(xiàng)目中大量的實(shí)驗(yàn)證明,Mysql單表容量在500萬(wàn)左右,性能處于最佳狀態(tài)。
在船營(yíng)等地區(qū),都構(gòu)建了全面的區(qū)域性戰(zhàn)略布局,加強(qiáng)發(fā)展的系統(tǒng)性、市場(chǎng)前瞻性、產(chǎn)品創(chuàng)新能力,以專(zhuān)注、極致的服務(wù)理念,為客戶(hù)提供網(wǎng)站建設(shè)、做網(wǎng)站 網(wǎng)站設(shè)計(jì)制作按需求定制開(kāi)發(fā),公司網(wǎng)站建設(shè),企業(yè)網(wǎng)站建設(shè),品牌網(wǎng)站設(shè)計(jì),成都營(yíng)銷(xiāo)網(wǎng)站建設(shè),成都外貿(mào)網(wǎng)站建設(shè)公司,船營(yíng)網(wǎng)站建設(shè)費(fèi)用合理。針對(duì)大表的優(yōu)化,主要是通過(guò)數(shù)據(jù)庫(kù)分庫(kù)分表來(lái)解決,目前比較普遍的方案有三個(gè):分區(qū)
,分庫(kù)分表
,NoSql/NewSql
。實(shí)際項(xiàng)目中,這三種方案是結(jié)合的,目前絕大部分系統(tǒng)的核心數(shù)據(jù)都是以RDBMS存儲(chǔ)為主,NoSql/NewSql存儲(chǔ)為輔。
分區(qū)
首先來(lái)了解一下分區(qū)方案。
分區(qū)表是由多個(gè)相關(guān)的底層表實(shí)現(xiàn)的。這些底層表也是由句柄對(duì)象表示,所以我們也可以直接訪問(wèn)各個(gè)分區(qū),存儲(chǔ)引擎管理分區(qū)的各個(gè)底層表和管理普通表一樣(所有的底層表都必須使用相同的存儲(chǔ)引擎),分區(qū)表的索引只是在各個(gè)底層表上各自加上一個(gè)相同的索引。這個(gè)方案對(duì)用戶(hù)屏蔽了sharding的細(xì)節(jié),即使查詢(xún)條件沒(méi)有sharding column,它也能正常工作(只是這時(shí)候性能一般)。
不過(guò)它的缺點(diǎn)很明顯:很多的資源都受到單機(jī)的限制,例如連接數(shù),網(wǎng)絡(luò)吞吐等。如何進(jìn)行分區(qū),在實(shí)際應(yīng)用中是一個(gè)非常關(guān)鍵的要素之一。
下面開(kāi)始舉例:以客戶(hù)信息為例,客戶(hù)數(shù)據(jù)量5000萬(wàn)加,項(xiàng)目背景要求保存客戶(hù)的銀行卡綁定關(guān)系,客戶(hù)的證件綁定關(guān)系,以及客戶(hù)綁定的業(yè)務(wù)信息。
此業(yè)務(wù)背景下,該如何設(shè)計(jì)數(shù)據(jù)庫(kù)呢。項(xiàng)目一期的時(shí)候,我們建立了一張客戶(hù)業(yè)務(wù)綁定關(guān)系表,里面冗余了每一位客戶(hù)綁定的業(yè)務(wù)信息。
基本結(jié)構(gòu)大致如下:
查詢(xún)時(shí),對(duì)銀行卡做索引,業(yè)務(wù)編號(hào)做索引,證件號(hào)做索引。隨著需求大增多,這張表的索引會(huì)達(dá)到10個(gè)以上。而且客戶(hù)解約再簽約,里面會(huì)保存兩條數(shù)據(jù),只是綁定的狀態(tài)不同。
假設(shè)我們有5千萬(wàn)的客戶(hù),5個(gè)業(yè)務(wù)類(lèi)型,每位客戶(hù)平均2張卡,那么這張表的數(shù)據(jù)量將會(huì)達(dá)到驚人的5億,事實(shí)上我們系統(tǒng)用戶(hù)量還沒(méi)有過(guò)百萬(wàn)時(shí)就已經(jīng)不行了。這樣的設(shè)計(jì)絕對(duì)是不行的,無(wú)論是插入,還是查詢(xún),都會(huì)讓系統(tǒng)崩潰。
mysql數(shù)據(jù)庫(kù)中的數(shù)據(jù)是以文件的形勢(shì)存在磁盤(pán)上的,默認(rèn)放在/mysql/data下面(可以通過(guò)my.cnf中的datadir來(lái)查看), 一張表主要對(duì)應(yīng)著三個(gè)文件,一個(gè)是frm存放表結(jié)構(gòu)的,一個(gè)是myd存放表數(shù)據(jù)的,一個(gè)是myi存表索引的。這三個(gè)文件都非常的龐大,尤其是.myd文件,快5個(gè)G了。下面進(jìn)行第一次分區(qū)優(yōu)化,Mysql支持的分區(qū)方式有四種:
在我們的項(xiàng)目中,range分區(qū)和list分區(qū)沒(méi)有使用場(chǎng)景,如果基于綁定編號(hào)做range或者list分區(qū),綁定編號(hào)沒(méi)有實(shí)際的業(yè)務(wù)含義,無(wú)法通過(guò)它進(jìn)行查詢(xún),因此,我們就剩下 HASH 分區(qū)和 KEY 分區(qū)了,HASH分區(qū)僅支持int類(lèi)型列的分區(qū),且是其中的一列。
KEY 分區(qū)倒是可以支持多列,但也要求其中的一列必須是int類(lèi)型;看我們的庫(kù)表結(jié)構(gòu),發(fā)現(xiàn)沒(méi)有哪一列是int類(lèi)型的,如何做分區(qū)呢?增加一列,綁定時(shí)間列,將此列設(shè)置為int類(lèi)型,然后按照綁定時(shí)間進(jìn)行分區(qū),將每一天綁定的用戶(hù)分到同一個(gè)區(qū)里面去。
這次優(yōu)化之后,我們的插入快了許多,但是查詢(xún)依然很慢,為什么?
因?yàn)樵谧霾樵?xún)的時(shí)候,我們也只是根據(jù)銀行卡或者證件號(hào)進(jìn)行查詢(xún),并沒(méi)有根據(jù)時(shí)間查詢(xún),相當(dāng)于每次查詢(xún),mysql都會(huì)將所有的分區(qū)表查詢(xún)一遍。
進(jìn)行第二次方案優(yōu)化,既然 HASH 分區(qū)和 KEY分區(qū)要求其中的一列必須是int類(lèi)型的,那么創(chuàng)造出一個(gè)int類(lèi)型的列出來(lái)分區(qū)是否可以?
分析發(fā)現(xiàn),銀行卡的那串?dāng)?shù)字有秘密。銀行卡一般是16位到19位不等的數(shù)字串,我們?nèi)∑渲械哪骋晃荒贸鰜?lái)作為表分區(qū)是否可行呢,通過(guò)分析發(fā)現(xiàn),在這串?dāng)?shù)字中,其中確實(shí)有一位是0到9隨機(jī)生成的,我們基于銀行卡號(hào)+隨機(jī)位進(jìn)行KEY分區(qū),每次查詢(xún)的時(shí)候,通過(guò)計(jì)算截取出這位隨機(jī)位數(shù)字,再加上卡號(hào),聯(lián)合查詢(xún),達(dá)到了分區(qū)查詢(xún)的目的,需要說(shuō)明的是,分區(qū)后,建立的索引,也必須是分區(qū)列,否則Mysql還是會(huì)在所有的分區(qū)表中查詢(xún)數(shù)據(jù)。
通過(guò)銀行卡號(hào)查詢(xún)綁定關(guān)系的問(wèn)題解決了,那么證件號(hào)呢,如何通過(guò)證件號(hào)來(lái)查詢(xún)綁定關(guān)系。
前面已經(jīng)講過(guò),做索引一定是要在分區(qū)健上進(jìn)行,否則會(huì)引起全表掃描。我們?cè)賱?chuàng)建了一張新表,保存客戶(hù)的證件號(hào)綁定關(guān)系,每位客戶(hù)的證件號(hào)都是唯一的,新的證件號(hào)綁定關(guān)系表里,證件號(hào)作為了主鍵,那么如何來(lái)計(jì)算這個(gè)分區(qū)健呢,客戶(hù)的證件信息比較龐雜,有身份證號(hào),港澳臺(tái)通行證,機(jī)動(dòng)車(chē)駕駛證等等,如何在無(wú)序的證件號(hào)里找到分區(qū)健。
為了解決這個(gè)問(wèn)題,我們將證件號(hào)綁定關(guān)系表一分為二,其中的一張表專(zhuān)用于保存身份證類(lèi)型的證件號(hào),另一張表則保存其他證件類(lèi)型的證件號(hào),在身份證類(lèi)型的證件綁定關(guān)系表中,我們將身份證號(hào)中的月數(shù)拆分出來(lái)作為了分區(qū)健,將同一個(gè)月出生的客戶(hù)證件號(hào)保存在同一個(gè)區(qū),這樣分成了12個(gè)區(qū),其他證件類(lèi)型的證件號(hào),數(shù)據(jù)量不超過(guò)10萬(wàn),就沒(méi)有必要進(jìn)行分區(qū)了。
這樣每次查詢(xún)時(shí),首先通過(guò)證件類(lèi)型確定要去查詢(xún)哪張表,再計(jì)算分區(qū)健進(jìn)行查詢(xún)。作了分區(qū)設(shè)計(jì)之后,保存2000萬(wàn)用戶(hù)數(shù)據(jù)時(shí)銀行卡表的數(shù)據(jù)保存文件就分成了10個(gè)小文件,證件表的數(shù)據(jù)保存文件分成了12個(gè)小文件,解決了這兩個(gè)查詢(xún)的問(wèn)題,還剩下一個(gè)問(wèn)題:業(yè)務(wù)編號(hào)怎么辦?
一個(gè)客戶(hù)有多個(gè)簽約業(yè)務(wù),如何進(jìn)行保存?這時(shí)候,采用分區(qū)的方案就不太合適了,它需要用到分表的方案。
分表
我們前面有提到過(guò)對(duì)于mysql,其數(shù)據(jù)文件是以文件形式存儲(chǔ)在磁盤(pán)上的。當(dāng)一個(gè)數(shù)據(jù)文件過(guò)大時(shí),操作系統(tǒng)對(duì)大文件的操作就會(huì)比較麻煩耗時(shí),且有的操作系統(tǒng)就不支持大文件,這個(gè)時(shí)候就必須分表了。
另外對(duì)于mysql常用的存儲(chǔ)引擎是Innodb,它的底層數(shù)據(jù)結(jié)構(gòu)是B+樹(shù)。當(dāng)其數(shù)據(jù)文件過(guò)大的時(shí)候,查詢(xún)一個(gè)節(jié)點(diǎn)可能會(huì)查詢(xún)很多層次,而這必定會(huì)導(dǎo)致多次IO操作進(jìn)行裝載進(jìn)內(nèi)存,肯定會(huì)耗時(shí)的。
除此之外還有Innodb對(duì)于B+樹(shù)的鎖機(jī)制。對(duì)每個(gè)節(jié)點(diǎn)進(jìn)行加鎖,那么當(dāng)更改表結(jié)構(gòu)的時(shí)候,這時(shí)候就會(huì)樹(shù)進(jìn)行加鎖,當(dāng)表文件大的時(shí)候,這可以認(rèn)為是不可實(shí)現(xiàn)的。所以綜上我們就必須進(jìn)行分表與分庫(kù)的操作。
如何進(jìn)行分庫(kù)分表,目前互聯(lián)網(wǎng)上有許多的版本,比較知名的一些方案:阿里的TDDL,DRDS和cobar,京東金融的sharding-jdbc;民間組織的MyCAT;360的Atlas;美團(tuán)的zebra;其他比如網(wǎng)易,58,京東等公司都有自研的中間件。
這么多的分庫(kù)分表中間件方案歸總起來(lái),就兩類(lèi):client模式和proxy模式。
client模式
proxy模式
無(wú)論是client模式,還是proxy模式。幾個(gè)核心的步驟是一樣的:SQL解析,重寫(xiě),路由,執(zhí)行,結(jié)果歸并。個(gè)人比較傾向于采用client模式,它架構(gòu)簡(jiǎn)單,性能損耗也比較小,運(yùn)維成本低。
如何對(duì)業(yè)務(wù)類(lèi)型進(jìn)行分庫(kù)分表。分庫(kù)分表最重要的一步,即sharding column的選取,sharding column選擇的好壞將直接決定整個(gè)分庫(kù)分表方案最終是否成功。而sharding column的選取跟業(yè)務(wù)強(qiáng)相關(guān)。
在我們的項(xiàng)目場(chǎng)景中,sharding column無(wú)疑最好的選擇是業(yè)務(wù)編號(hào)。通過(guò)業(yè)務(wù)編號(hào),將客戶(hù)不同的綁定簽約業(yè)務(wù)保存到不同的表里面去,根據(jù)業(yè)務(wù)編號(hào)路由到相應(yīng)的表中進(jìn)行查詢(xún),達(dá)到進(jìn)一步優(yōu)化sql的目的。
以上就是phper優(yōu)化MySQL千萬(wàn)級(jí)大表的方法詳解的詳細(xì)內(nèi)容,更多請(qǐng)關(guān)注創(chuàng)新互聯(lián)其它相關(guān)文章!
當(dāng)前文章:如何用phper優(yōu)化存儲(chǔ)上千億數(shù)據(jù)的Mysql?-創(chuàng)新互聯(lián)
本文路徑:http://jinyejixie.com/article8/dhdhop.html
成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供微信公眾號(hào)、關(guān)鍵詞優(yōu)化、標(biāo)簽優(yōu)化、虛擬主機(jī)、用戶(hù)體驗(yàn)、電子商務(wù)
聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶(hù)投稿、用戶(hù)轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請(qǐng)盡快告知,我們將會(huì)在第一時(shí)間刪除。文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如需處理請(qǐng)聯(lián)系客服。電話(huà):028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時(shí)需注明來(lái)源: 創(chuàng)新互聯(lián)
猜你還喜歡下面的內(nèi)容