基于SSD固態(tài)硬盤的數(shù)據(jù)庫性能優(yōu)化
NOR和NAND
NOR和NAND都是閃存技術(shù)的一種,NOR是Intel公司開發(fā)的,它有點(diǎn)類似于內(nèi)存,允許通過地址直接訪問任何一個(gè)內(nèi)存單元,缺點(diǎn)是:密度低(容量?。瑢懭牒筒脸乃俣群苈?。NAND是東芝公司開發(fā)的,它密度高(容量大),寫入和擦除的速度都很快,但是必須通過特定的IO接口經(jīng)過地址轉(zhuǎn)換之后才可以訪問,有些類似于磁盤。
我們現(xiàn)在廣泛使用的U盤,SD卡,SSD都屬于NAND類型,廠商將flash memory封裝成為不同的接口,比如Intel的SSD就是采用了SATA的接口,訪問與普通SATA磁盤一樣,還有一些企業(yè)級(jí)的閃存卡,比如FusionIO,則封裝為PCIe接口。
SLC和MLC
SLC是單極單元,MLC是多級(jí)單元,兩者的差異在于每單元存儲(chǔ)的數(shù)據(jù)量(密度),SLC每單元只存儲(chǔ)一位,只包含0和1兩個(gè)電壓符,MLC每單元可以存儲(chǔ)兩位,包含四個(gè)電壓符(00,01,10,11)。顯然,MLC的存儲(chǔ)容量比SLC大,但是SLC更簡單可靠,SLC讀取和寫入的速度都比MLC更快,而且SLC比MLC更耐用,MLC每單元可擦除1w次,而SLC可擦除10w次,所以,企業(yè)級(jí)的閃存產(chǎn)品一般都選用SLC,這也是為什么企業(yè)級(jí)產(chǎn)品比家用產(chǎn)品貴很多的原因。
SSD的技術(shù)特點(diǎn)
SSD與傳統(tǒng)磁盤相比,***是沒有機(jī)械裝置,第二是由磁介質(zhì)改為了電介質(zhì)。在SSD內(nèi)部有一個(gè)FTL(Flash Transalation Layer),它相當(dāng)于磁盤中的控制器,主要功能就是作地址映射,將flash memory的物理地址映射為磁盤的LBA邏輯地址,并提供給OS作透明訪問。
SSD沒有傳統(tǒng)磁盤的尋道時(shí)間和延遲時(shí)間,所以SSD可以提供非常高的隨機(jī)讀取能力,這是它的***優(yōu)勢(shì),SLC類型的SSD通??梢蕴峁┏^35000的IOPS,傳統(tǒng)15k的SAS磁盤,最多也只能達(dá)到160個(gè)IOPS,這對(duì)于傳統(tǒng)磁盤來說幾乎就是個(gè)天文數(shù)字。SSD連續(xù)讀的能力相比普通磁盤優(yōu)勢(shì)并不明顯,因?yàn)檫B續(xù)讀對(duì)于傳統(tǒng)磁盤來說,并不需要尋道時(shí)間,15k的SAS磁盤,連續(xù)讀的吞吐能力可以達(dá)到130MB,而SLC類型的SSD可以達(dá)到170-200MB,我們看到在吞吐量方面,SSD雖然比傳統(tǒng)磁盤高一些,但優(yōu)勢(shì)雖然并不明顯。
SSD的寫操作比較特殊,SSD的最小寫入單元為4KB,稱為頁(page),當(dāng)寫入空白位置時(shí)可以按照4KB的單位寫入,但是如果需要改寫某個(gè)單元時(shí),則需要一個(gè)額外的擦除(erase)動(dòng)作,擦除的單位一般是128個(gè)page(512KB),每個(gè)擦除單元稱為塊(block)。如果向一個(gè)空白的page寫入信息時(shí),可以直接寫入而無需擦除,但是如果需要改寫某個(gè)存儲(chǔ)單元(page)的數(shù)據(jù),必須首先將整個(gè)block讀入緩存,然后修改數(shù)據(jù),并擦除整個(gè)block的數(shù)據(jù),***將整個(gè)block寫入,很顯然,SSD改寫數(shù)據(jù)的代價(jià)很高,SSD的這個(gè)特性,我們稱之為erase-before-write。
經(jīng)過測(cè)試,SLC SSD的隨即寫性能可以達(dá)到3000個(gè)左右的IOPS,連續(xù)寫的吞吐量可以達(dá)到170MB,這個(gè)數(shù)據(jù)還是比傳統(tǒng)磁盤高出不少。但是,隨著SSD的不斷寫入,當(dāng)越來越多的數(shù)據(jù)需要被改寫時(shí),寫的性能就會(huì)逐步下降。經(jīng)過我們的測(cè)試,SLC在這個(gè)方面要明顯好于MLC,在長時(shí)間寫入后,MLC隨機(jī)寫IO下降得非常厲害,而SLC表現(xiàn)則比較穩(wěn)定。為了解決這個(gè)問題,各個(gè)廠商都有很多策略來防止寫性能下降的問題。
wear leveling
因?yàn)镾SD存在“寫磨損”的問題,當(dāng)某個(gè)單元長時(shí)間被反復(fù)擦寫時(shí)(比如Oracle redo),不僅會(huì)造成寫入的性能問題,而且會(huì)大大縮短SSD的使用壽命,所以必須設(shè)計(jì)一個(gè)均衡負(fù)載的算法來保證SSD的每個(gè)單元能夠被均衡的使用,這就是wear leveling,稱為損耗均衡算法。
Wear leveling也是SSD內(nèi)部的FTL實(shí)現(xiàn)的,它通過數(shù)據(jù)遷移來達(dá)到均衡損耗的目的。Wear leveling依賴于SSD中的一部分保留空間,基本原理是在SSD中設(shè)置了兩個(gè)block pool,一個(gè)是free block pool(空閑池),一個(gè)是數(shù)據(jù)池(data block pool),當(dāng)需要改寫某個(gè)page時(shí)(如果寫入原有位置,必須先擦除整個(gè)block,然后才能寫入數(shù)據(jù)),并不寫入原有位置(不需要擦除的動(dòng)作),而是從空閑池中取出新的block,將現(xiàn)有的數(shù)據(jù)和需要改寫的數(shù)據(jù)合并為新的block,一起寫入新的空白block,原有的block被標(biāo)識(shí)為invalid狀態(tài)(等待被擦除回收),新的block則進(jìn)入數(shù)據(jù)池。后臺(tái)任務(wù)會(huì)定時(shí)從data block中取出無效數(shù)據(jù)的block,擦除后回收到空閑池中。這樣做的好處在于,一是不會(huì)反復(fù)擦寫同一個(gè)block,二是寫入的速度會(huì)比較快(省略了擦除的動(dòng)作)。
Wear leveling分為兩種:動(dòng)態(tài)損耗均衡和靜態(tài)損耗均衡,兩者的原理一致,區(qū)別在于動(dòng)態(tài)算法只會(huì)處理動(dòng)態(tài)數(shù)據(jù),比如數(shù)據(jù)改寫時(shí)才會(huì)觸發(fā)數(shù)據(jù)遷移的動(dòng)作,對(duì)靜態(tài)數(shù)據(jù)不起作用,而靜態(tài)算法可以均衡靜態(tài)數(shù)據(jù),當(dāng)后臺(tái)任務(wù)發(fā)現(xiàn)損耗很低的靜態(tài)數(shù)據(jù)塊時(shí),將其遷移到其他數(shù)據(jù)庫塊上,將這些塊放入空閑池中使用。從均衡的效果來看,靜態(tài)算法要好于動(dòng)態(tài)算法,因?yàn)閹缀跛械腷lock都可以被均衡的使用,SSD的壽命會(huì)大大延長,但是靜態(tài)算法的缺點(diǎn)是當(dāng)數(shù)據(jù)遷移時(shí),可能會(huì)導(dǎo)致寫性能下降。
寫入放大
因?yàn)镾SD的erase-before-write的特性,所以就出現(xiàn)了一個(gè)寫入放大的概念,比如你想改寫4K的數(shù)據(jù),必須首先將整個(gè)擦除塊(512KB)中的數(shù)據(jù)讀出到緩存中,改寫后,將整個(gè)塊一起寫入,這時(shí)你實(shí)際寫入了512KB的數(shù)據(jù),寫入放大系數(shù)是128。寫入放大***的情況是1,就是不存在放大的情況。
Wear leveling算法可以有效緩解寫入放大的問題,但是不合理的算法依然會(huì)導(dǎo)致寫入放大,比如用戶需要寫入4k數(shù)據(jù)時(shí),發(fā)現(xiàn)free block pool中沒有空白的block,這時(shí)就必須在data block pool中選擇一個(gè)包含無效數(shù)據(jù)的block,先讀入緩存中,改寫后,將整個(gè)塊一起寫入,采用wear leveling算法依然會(huì)存在寫入放大的問題。
通過為SSD預(yù)留更多空間,可以顯著緩解寫入放大導(dǎo)致的性能問題。根據(jù)我們的測(cè)試結(jié)果,MLC SSD在長時(shí)間的隨機(jī)寫入后,性能下降很明顯(隨機(jī)寫IOPS甚至降低到300)。如果為wear leveling預(yù)留更多空間,就可以顯著改善MLC SSD在長時(shí)間寫操作之后的性能下降問題,而且保留的空間越多,性能提升就越明顯。相比較而言,SLC SSD的性能要穩(wěn)定很多(IOPS在長時(shí)間隨機(jī)寫后,隨機(jī)寫可以穩(wěn)定在3000 IOPS),我想應(yīng)該是SLC SSD的容量通常比較?。?2G和64G),而用于wear leveling的空間又比較大的原因。
數(shù)據(jù)庫IO特點(diǎn)分析
IO有四種類型:連續(xù)讀,隨機(jī)讀,隨機(jī)寫和連續(xù)寫,連續(xù)讀寫的IO size通常比較大(128KB-1MB),主要衡量吞吐量,而隨機(jī)讀寫的IO size比較小(小于8KB),主要衡量IOPS和響應(yīng)時(shí)間。數(shù)據(jù)庫中的全表掃描是連續(xù)讀IO,索引訪問則是典型的隨機(jī)讀IO,日志文件是連續(xù)寫IO,而數(shù)據(jù)文件則是隨機(jī)寫IO。
數(shù)據(jù)庫系統(tǒng)基于傳統(tǒng)磁盤訪問特性來設(shè)計(jì),***特點(diǎn)是日志文件采用sequential logging,數(shù)據(jù)庫中的日志文件,要求必須在事務(wù)提交時(shí)寫入到磁盤,對(duì)響應(yīng)時(shí)間的要求很高,所以設(shè)計(jì)為順序?qū)懭氲姆绞?,可以有效降低磁盤尋道花費(fèi)的時(shí)間,減少延遲時(shí)間。日志文件的順序?qū)懭?,雖然是物理位置是連續(xù)的,但是并不同于傳統(tǒng)的連續(xù)寫類型,日志文件的IO size很?。ㄍǔP∮?K),每個(gè)IO之間是獨(dú)立的(磁頭必須抬起來重新尋道,并等待磁盤轉(zhuǎn)動(dòng)到相應(yīng)的位置),而且間隔很短,數(shù)據(jù)庫通過log buffer(緩存)和group commit的方式(批量提交)來達(dá)到提高IO size的大小,并減少IO的次數(shù),從而得到更小的響應(yīng)延遲,所以日志文件的順序?qū)懭肟梢员徽J(rèn)為是“連續(xù)位置的隨機(jī)寫入”,更關(guān)注IOPS,而不是吞吐量。
數(shù)據(jù)文件采用in place uddate的方式,意思是數(shù)據(jù)文件的修改都是寫入到原來的位置,數(shù)據(jù)文件不同于日志文件,并不會(huì)在事務(wù)commit時(shí)寫入數(shù)據(jù)文件,只有當(dāng)數(shù)據(jù)庫發(fā)現(xiàn)dirty buffer過多或者需要做checkpoint動(dòng)作時(shí),才會(huì)刷新這些dirty buffer到相應(yīng)的位置,這是一個(gè)異步的過程,通常情況下,數(shù)據(jù)文件的隨機(jī)寫入對(duì)IO的要求并不是特別高,只要滿足checkpoint和dirty buffer的要求就可以了。
SSD的IO特點(diǎn)分析
1.隨機(jī)讀能力非常好,連續(xù)讀性能一般,但比普通SAS磁盤好。
2.不存在磁盤尋道的延遲時(shí)間,隨機(jī)寫和連續(xù)寫的響應(yīng)延遲差異不大。
3.erase-before-write特性,造成寫入放大,影響寫入的性能。
4.寫磨損特性,采用wear leveling算法延長壽命,但同時(shí)會(huì)影響讀的性能。
5.讀和寫的IO響應(yīng)延遲不對(duì)等(讀要大大好于寫),而普通磁盤讀和寫的IO響應(yīng)延遲差異很小。
6.連續(xù)寫比隨機(jī)寫性能好,比如1M順序?qū)懕?28個(gè)8K的隨即寫要好很多,因?yàn)殡S即寫會(huì)帶來大量的擦除。
基于SSD的上述特性,如果將數(shù)據(jù)庫全部放在SSD上,可能會(huì)有以下的問題:
1.日志文件sequential logging會(huì)反復(fù)擦寫同一位置,雖然有損耗均衡算法,但是長時(shí)間寫入依然會(huì)導(dǎo)致性能下降。
2.數(shù)據(jù)文件in place update會(huì)產(chǎn)生大量的隨機(jī)寫入,erase-before-write會(huì)產(chǎn)生寫入放大。
3.數(shù)據(jù)庫讀寫混合型應(yīng)用,存在大量的隨機(jī)寫入,同時(shí)會(huì)影響讀的性能,產(chǎn)生大量的IO延遲。
基于SSD的數(shù)據(jù)庫優(yōu)化法則:
基于SSD的優(yōu)化就是解決erase-before-write產(chǎn)生的寫入放大的問題,不同類型的IO分離,減少寫操作帶來的性能影響。
1.將sequential logging修改為In-page logging,避免對(duì)相同位置的反復(fù)擦寫。
2.通過緩存寫入的方式將大量的in-place update隨機(jī)寫入合并為少量順序?qū)懭搿?/p>
3.利用SSD隨機(jī)讀寫能力高的特點(diǎn),減少寫增加讀,從而達(dá)到整體性能的提升。
In-page logging
In-page logging是基于SSD對(duì)數(shù)據(jù)庫sequential logging的一種優(yōu)化方法,數(shù)據(jù)庫中的sequential logging對(duì)傳統(tǒng)磁盤是非常有利的,可以大大提高響應(yīng)時(shí)間,但是對(duì)于SSD就是噩夢(mèng),因?yàn)樾枰獙?duì)同一位置反復(fù)擦寫,而wear leveling算法雖然可以平衡負(fù)載,但是依然會(huì)影響性能,并產(chǎn)生大量的IO延遲。所以In-page logging將日志和數(shù)據(jù)合并,將日志順序?qū)懭敫臑殡S機(jī)寫入,基于SSD對(duì)隨機(jī)寫和連續(xù)寫IO響應(yīng)延遲差異不大的特性,避免對(duì)同一位置反復(fù)擦寫,提高整體性能。
In-page logging基本原理:在data buffer中,有一個(gè)in-memory log sector的結(jié)構(gòu),類似于log buffer,每個(gè)log sector是與data block對(duì)應(yīng)的。在data buffer中,data和log并不合并,只是在data block和log sector之間建立了對(duì)應(yīng)關(guān)系,可以將某個(gè)data block的log分離出來。但是,在SSD底層的flash memory中,數(shù)據(jù)和日志是存放在同一個(gè)block(擦除單元),每個(gè)block都包含data page和log page。
當(dāng)日志信息需要寫入的時(shí)候(log buffer空間不足或者事務(wù)提交),日志信息會(huì)寫入到flash memory對(duì)應(yīng)的block中,也就是說日志信息是分布在很多不同的block中的,而每個(gè)block內(nèi)的日志信息是append write,所以不需要擦除的動(dòng)作。當(dāng)某個(gè)block中的log sector寫滿的時(shí)候,這時(shí)會(huì)發(fā)生一個(gè)動(dòng)作,將整個(gè)block中的信息讀出,然后應(yīng)用block中的log sector,就可以得到***的數(shù)據(jù),然后整個(gè)block寫入,這時(shí),block中的log sector是空白的。
在in-page logging方法中,data buffer中的dirty block是不需要寫入到flash memory中的,就算dirty buffer需要被交換出去,也不需要將它們寫入flash memory中。當(dāng)需要讀取***的數(shù)據(jù),只要將block中的數(shù)據(jù)和日志信息合并,就可以得到***的數(shù)據(jù)。
In-page logging方法,將日志和數(shù)據(jù)放在同一個(gè)擦除單元內(nèi),減少了對(duì)flash相同位置的反復(fù)擦寫,而且不需要將dirty block寫入到flash中,大量減少了in-place update的隨機(jī)寫入和擦除的動(dòng)作。雖然在讀取時(shí),需要做一個(gè)merge的操作,但是因?yàn)閿?shù)據(jù)和日志存放在一起,而且SSD的隨機(jī)讀取能力很高,in-page logging可以提高整體的性能。
SSD作為寫cache-append write
SSD可以作為磁盤的寫cache,因?yàn)镾SD連續(xù)寫比隨機(jī)寫性能好,比如:1M順序?qū)懕?28個(gè)8K的隨機(jī)寫要好很多,我們可以將大量隨機(jī)寫合并成為少量順序?qū)?,增加IO的大小,減少IO(擦除)的次數(shù),提高寫入性能。這個(gè)方法與很多NoSQL產(chǎn)品的append write類似,即不改寫數(shù)據(jù),只追加數(shù)據(jù),需要時(shí)做合并處理。
基本原理:當(dāng)dirty block需要寫入到數(shù)據(jù)文件時(shí),并不直接更新原來的數(shù)據(jù)文件,而是首先進(jìn)行IO合并,將很多個(gè)8K的dirty block合并為一個(gè)512KB的寫入單元,并采用append write的方式寫入到一個(gè)cache file中(保存在SSD上),避免了擦除的動(dòng)作,提高了寫入性能。cache file中的數(shù)據(jù)采用循環(huán)的方式順序?qū)懭?,?dāng)cache file空間不足夠時(shí),后臺(tái)進(jìn)程會(huì)將cache file中的數(shù)據(jù)寫入到真正的數(shù)據(jù)文件中(保存在磁盤上),這時(shí)進(jìn)行第二次IO合并,將cache file內(nèi)的數(shù)據(jù)進(jìn)行合并,整合成為少量的順序?qū)懭?,?duì)于磁盤來說,最終的IO是1M的順序?qū)懭?,順序?qū)懭胫粫?huì)影響吞吐量,而磁盤的吞吐量不會(huì)成為瓶頸,將IOPS的瓶頸轉(zhuǎn)化為吞吐量的瓶頸,從而提升了整體系統(tǒng)能力。
讀取數(shù)據(jù)時(shí),必須首先讀取cache file,而cache file中的數(shù)據(jù)是無序存放的,為了快速檢索cache file中的數(shù)據(jù),一般會(huì)在內(nèi)存中為cache file建立一個(gè)索引,讀取數(shù)據(jù)時(shí)會(huì)先查詢這個(gè)索引,如果命中查詢cache file,如果沒有命中,再讀取data file(普通磁盤),所以,這種方法實(shí)際不僅僅是寫cache,同時(shí)也起到了讀cache的作用。
但是這種方法并不適合日志文件的寫cache,雖然日志文件也是append write,但是因?yàn)槿罩疚募腎O size比較小,而且必須同步寫入,無法做合并處理,所以性能提升有限。
SSD作為讀cache-flashcache
因?yàn)榇蟛糠謹(jǐn)?shù)據(jù)庫都是讀多寫少的類型,所以SSD作為數(shù)據(jù)庫flashcache是優(yōu)化方案中最簡單的一種,它可以充分利用SSD讀性能的優(yōu)勢(shì),又避免了SSD寫入的性能問題。實(shí)現(xiàn)的方法有很多種,可以在讀取數(shù)據(jù)時(shí),將數(shù)據(jù)同時(shí)寫入SSD,也可以在數(shù)據(jù)被刷出buffer時(shí),寫入到SSD。讀取數(shù)據(jù)時(shí),首先在buffer中查詢,然后在flashcache中查詢,***讀取datafile。
SSD作為flashcache與memcache作為數(shù)據(jù)庫外部cache的***區(qū)別在于,SSD掉電后數(shù)據(jù)是不丟失的,這也引起了另外一個(gè)思考,當(dāng)數(shù)據(jù)庫發(fā)生故障重啟后,flashcache中的數(shù)據(jù)是有效還是無效?如果是有效的,那么就必須時(shí)刻保證flashcache中數(shù)據(jù)的一致性,如果是無效的,那么flashcache同樣面臨一個(gè)預(yù)熱的問題(這與memcache掉電后的問題一樣)。目前,據(jù)我所知,基本上都認(rèn)為是無效的,因?yàn)橐3謋lashcache中數(shù)據(jù)的一致性,非常困難。
flashcache作為內(nèi)存和磁盤之間的二級(jí)cache,除了性能的提升以外,從成本的角度看,SSD的價(jià)格介于memory和disk之間,作為兩者之間的一層cache,可以在性能和價(jià)格之間找到平衡。
總結(jié)
隨著SSD價(jià)格不斷降低,容量和性能不斷提升,SSD取代磁盤只是個(gè)時(shí)間問題。
原文鏈接:http://www.hellodba.net/2010/10/ssd-database-2.html
【編輯推薦】