基于SSD的数据库性能优化

标签: flashcache SSD 大话技术 | 发表时间:2010-10-28 22:45 | 作者:jacky Sungelina
出处:http://www.hellodba.net

NOR和NAND

NOR和NAND都是闪存技术的一种,NOR是Intel公司开发的,它有点类似于内存,允许通过地址直接访问任何一个内存单元,缺点是:密度低(容量小),写入和擦除的速度很慢。NAND是东芝公司开发的,它密度高(容量大),写入和擦除的速度都很快,但是必须通过特定的IO接口经过地址转换之后才可以访问,有些类似于磁盘。

我们现在广泛使用的U盘,SD卡,SSD都属于NAND类型,厂商将flash memory封装成为不同的接口,比如Intel的SSD就是采用了SATA的接口,访问与普通SATA磁盘一样,还有一些企业级的闪存卡,比如FusionIO,则封装为PCIe接口。

SLC和MLC

SLC是单极单元,MLC是多级单元,两者的差异在于每单元存储的数据量(密度),SLC每单元只存储一位,只包含0和1两个电压符,MLC每单元可以存储两位,包含四个电压符(00,01,10,11)。显然,MLC的存储容量比SLC大,但是SLC更简单可靠,SLC读取和写入的速度都比MLC更快,而且SLC比MLC更耐用,MLC每单元可擦除1w次,而SLC可擦除10w次,所以,企业级的闪存产品一般都选用SLC,这也是为什么企业级产品比家用产品贵很多的原因。

SSD的技术特点

SSD与传统磁盘相比,第一是没有机械装置,第二是由磁介质改为了电介质。在SSD内部有一个FTL(Flash Transalation Layer),它相当于磁盘中的控制器,主要功能就是作地址映射,将flash memory的物理地址映射为磁盘的LBA逻辑地址,并提供给OS作透明访问。

SSD没有传统磁盘的寻道时间和延迟时间,所以SSD可以提供非常高的随机读取能力,这是它的最大优势,SLC类型的SSD通常可以提供超过35000的IOPS,传统15k的SAS磁盘,最多也只能达到160个IOPS,这对于传统磁盘来说几乎就是个天文数字。SSD连续读的能力相比普通磁盘优势并不明显,因为连续读对于传统磁盘来说,并不需要寻道时间,15k的SAS磁盘,连续读的吞吐能力可以达到130MB,而SLC类型的SSD可以达到170-200MB,我们看到在吞吐量方面,SSD虽然比传统磁盘高一些,但优势虽然并不明显。

SSD的写操作比较特殊,SSD的最小写入单元为4KB,称为页(page),当写入空白位置时可以按照4KB的单位写入,但是如果需要改写某个单元时,则需要一个额外的擦除(erase)动作,擦除的单位一般是128个page(512KB),每个擦除单元称为块(block)。如果向一个空白的page写入信息时,可以直接写入而无需擦除,但是如果需要改写某个存储单元(page)的数据,必须首先将整个block读入缓存,然后修改数据,并擦除整个block的数据,最后将整个block写入,很显然,SSD改写数据的代价很高,SSD的这个特性,我们称之为erase-before-write。

经过测试,SLC SSD的随即写性能可以达到3000个左右的IOPS,连续写的吞吐量可以达到170-200MB,这个数据还是比传统磁盘高出不少。但是,随着SSD的不断写入,当越来越多的数据需要被改写时,写的性能就会逐步下降。经过我们的测试,SLC在这个方面要明显好于MLC,在长时间写入后,MLC随机写IO下降得非常厉害,而SLC表现则比较稳定。为了解决这个问题,各个厂商都有很多策略来防止写性能下降的问题。

wear leveling

因为SSD存在“写磨损”的问题,当某个单元长时间被反复擦写时(比如Oracle redo),不仅会造成写入的性能问题,而且会大大缩短SSD的使用寿命,所以必须设计一个均衡负载的算法来保证SSD的每个单元能够被均衡的使用,这就是wear leveling,称为损耗均衡算法。

Wear leveling也是SSD内部的FTL实现的,它通过数据迁移来达到均衡损耗的目的。Wear leveling依赖于SSD中的一部分保留空间,基本原理是在SSD中设置了两个block pool,一个是free block pool(空闲池),一个是数据池(data block pool),当需要改写某个page时(如果写入原有位置,必须先擦除整个block,然后才能写入数据),并不写入原有位置(不需要擦除的动作),而是从空闲池中取出新的block,将现有的数据和需要改写的数据合并为新的block,一起写入新的空白block,原有的block被标识为invalid状态(等待被擦除回收),新的block则进入数据池。后台任务会定时从data block中取出无效数据的block,擦除后回收到空闲池中。这样做的好处在于,一是不会反复擦写同一个block,二是写入的速度会比较快(省略了擦除的动作)。

Wear leveling分为两种:动态损耗均衡和静态损耗均衡,两者的原理一致,区别在于动态算法只会处理动态数据,比如数据改写时才会触发数据迁移的动作,对静态数据不起作用,而静态算法可以均衡静态数据,当后台任务发现损耗很低的静态数据块时,将其迁移到其他数据库块上,将这些块放入空闲池中使用。从均衡的效果来看,静态算法要好于动态算法,因为几乎所有的block都可以被均衡的使用,SSD的寿命会大大延长,但是静态算法的缺点是当数据迁移时,可能会导致写性能下降。

写入放大

因为SSD的erase-before-write的特性,所以就出现了一个写入放大的概念,比如你想改写4K的数据,必须首先将整个擦除块(512KB)中的数据读出到缓存中,改写后,将整个块一起写入,这时你实际写入了512KB的数据,写入放大系数是128。写入放大最好的情况是1,就是不存在放大的情况。

Wear leveling算法可以有效缓解写入放大的问题,但是不合理的算法依然会导致写入放大,比如用户需要写入4k数据时,发现free block pool中没有空白的block,这时就必须在data block pool中选择一个包含无效数据的block,先读入缓存中,改写后,将整个块一起写入,采用wear leveling算法依然会存在写入放大的问题。

通过为SSD预留更多空间,可以显著缓解写入放大导致的性能问题。根据我们的测试结果,MLC SSD在长时间的随机写入后,性能下降很明显(随机写IOPS甚至降低到300)。如果为wear leveling预留更多空间,就可以显著改善MLC SSD在长时间写操作之后的性能下降问题,而且保留的空间越多,性能提升就越明显。相比较而言,SLC SSD的性能要稳定很多(IOPS在长时间随机写后,随机写可以稳定在3000 IOPS),我想应该是SLC SSD的容量通常比较小(32G和64G),而用于wear leveling的空间又比较大的原因。

数据库IO特点分析

IO有四种类型:连续读,随机读,随机写和连续写,连续读写的IO size通常比较大(128KB-1MB),主要衡量吞吐量,而随机读写的IO size比较小(小于8KB),主要衡量IOPS和响应时间。数据库中的全表扫描是连续读IO,索引访问则是典型的随机读IO,日志文件是连续写IO,而数据文件则是随机写IO。

数据库系统基于传统磁盘访问特性来设计,最大特点是日志文件采用sequential logging,数据库中的日志文件,要求必须在事务提交时写入到磁盘,对响应时间的要求很高,所以设计为顺序写入的方式,可以有效降低磁盘寻道花费的时间,减少延迟时间。日志文件的顺序写入,虽然是物理位置是连续的,但是并不同于传统的连续写类型,日志文件的IO size很小(通常小于4K),每个IO之间是独立的(磁头必须抬起来重新寻道,并等待磁盘转动到相应的位置),而且间隔很短,数据库通过log buffer(缓存)和group commit的方式(批量提交)来达到提高IO size的大小,并减少IO的次数,从而得到更小的响应延迟,所以日志文件的顺序写入可以被认为是“连续位置的随机写入”,瓶颈还是在IOPS,而不是吞吐量。

数据文件采用in place update的方式,意思是数据文件的修改都是写入到原来的位置,数据文件不同于日志文件,并不会在事务commit时写入数据文件,只有当数据库发现dirty buffer过多或者需要做checkpoint动作时,才会刷新这些dirty buffer到相应的位置,这是一个异步的过程,通常情况下,数据文件的随机写入对IO的要求并不是特别高,只要满足checkpoint和dirty buffer的要求就可以了。

SSD的IO特点分析

1.随机读能力非常好,连续读性能一般,但比普通SAS磁盘好。

2.不存在磁盘寻道的延迟时间,随机写和连续写的响应延迟差异不大。

3.erase-before-write特性,造成写入放大,影响写入的性能。

4.写磨损特性,采用wear leveling算法延长寿命,但同时会影响读的性能。

5.读和写的IO响应延迟不对等(读要大大好于写),而普通磁盘读和写的IO响应延迟差异很小。

6.连续写比随机写性能好,比如1M顺序写比128个8K的随即写要好很多,因为随即写会带来大量的擦除。

基于SSD的上述特性,如果将数据库全部放在SSD上,可能会有以下的问题:

1.日志文件sequential logging会反复擦写同一位置,虽然有损耗均衡算法,但是长时间写入依然会导致性能下降。

2.数据文件in place update会产生大量的随机写入,erase-before-write会产生写入放大。

3.数据库读写混合型应用,存在大量的随机写入,同时会影响读的性能,产生大量的IO延迟。

基于SSD的数据库优化法则

基于SSD的优化就是解决erase-before-write产生的写入放大的问题,不同类型的IO分离,减少写操作带来的性能影响。

1.将sequential logging修改为In-page logging,避免对相同位置的反复擦写。

2.通过缓存写入的方式将大量的in-place update随机写入合并为少量顺序写入。

3.利用SSD随机读写能力高的特点,减少写增加读,从而达到整体性能的提升。

In-page logging

In-page logging是基于SSD对数据库sequential logging的一种优化方法,数据库中的sequential logging对传统磁盘是非常有利的,可以大大提高响应时间,但是对于SSD就是噩梦,因为需要对同一位置反复擦写,而wear leveling算法虽然可以平衡负载,但是依然会影响性能,并产生大量的IO延迟。所以In-page logging将日志和数据合并,将日志顺序写入改为随机写入,基于SSD对随机写和连续写IO响应延迟差异不大的特性,避免对同一位置反复擦写,提高整体性能。

In-page logging基本原理:在data buffer中,有一个in-memory log sector的结构,类似于log buffer,每个log sector是与data block对应的。在data buffer中,data和log并不合并,只是在data block和log sector之间建立了对应关系,可以将某个data block的log分离出来。但是,在SSD底层的flash memory中,数据和日志是存放在同一个block(擦除单元),每个block都包含data page和log page。

当日志信息需要写入的时候(log buffer空间不足或者事务提交),日志信息会写入到flash memory对应的block中,也就是说日志信息是分布在很多不同的block中的,而每个block内的日志信息是append write,所以不需要擦除的动作。当某个block中的log sector写满的时候,这时会发生一个动作,将整个block中的信息读出,然后应用block中的log sector,就可以得到最新的数据,然后整个block写入,这时,block中的log sector是空白的。

在in-page logging方法中,data buffer中的dirty block是不需要写入到flash memory中的,就算dirty buffer需要被交换出去,也不需要将它们写入flash memory中。当需要读取最新的数据,只要将block中的数据和日志信息合并,就可以得到最新的数据。

In-page logging方法,将日志和数据放在同一个擦除单元内,减少了对flash相同位置的反复擦写,而且不需要将dirty block写入到flash中,大量减少了in-place update的随机写入和擦除的动作。虽然在读取时,需要做一个merge的操作,但是因为数据和日志存放在一起,而且SSD的随机读取能力很高,in-page logging可以提高整体的性能。

SSD作为写cache—append write

SSD可以作为磁盘的写cache,因为SSD连续写比随机写性能好,比如:1M顺序写比128个8K的随机写要好很多,我们可以将大量随机写合并成为少量顺序写,增加IO的大小,减少IO(擦除)的次数,提高写入性能。这个方法与很多NoSQL产品的append write类似,即不改写数据,只追加数据,需要时做合并处理。

基本原理:当dirty block需要写入到数据文件时,并不直接更新原来的数据文件,而是首先进行IO合并,将很多个8K的dirty block合并为一个512KB的写入单元,并采用append write的方式写入到一个cache file中(保存在SSD上),避免了擦除的动作,提高了写入性能。cache file中的数据采用循环的方式顺序写入,当cache file空间不足够时,后台进程会将cache file中的数据写入到真正的数据文件中(保存在磁盘上),这时进行第二次IO合并,将cache file内的数据进行合并,整合成为少量的顺序写入,对于磁盘来说,最终的IO是1M的顺序写入,顺序写入只会影响吞吐量,而磁盘的吞吐量不会成为瓶颈,将IOPS的瓶颈转化为吞吐量的瓶颈,从而提升了整体系统能力。

读取数据时,必须首先读取cache file,而cache file中的数据是无序存放的,为了快速检索cache file中的数据,一般会在内存中为cache file建立一个索引,读取数据时会先查询这个索引,如果命中查询cache file,如果没有命中,再读取data file(普通磁盘),所以,这种方法实际不仅仅是写cache,同时也起到了读cache的作用。

SSD并不适合放数据库的日志文件,虽然日志文件也是append write,但是因为日志文件的IO size比较小,而且必须同步写入,无法做合并处理,对SSD来说,需要大量的擦除动作。我们也曾经尝试把redo log放在SSD上,考虑到SSD的随机写入也可以达到3000 IOPS,而且响应延时比磁盘低很多,但是这依赖于SSD本身的wear leveling算法是否优秀,而且日志文件必须是独立存放的,如果日志文件的写入是瓶颈,也算是一种解决方案吧。通常情况下,我还是建议日志文件放在普通磁盘上,而不是SSD。

SSD作为读cache—flashcache

因为大部分数据库都是读多写少的类型,所以SSD作为数据库flashcache是优化方案中最简单的一种,它可以充分利用SSD读性能的优势,又避免了SSD写入的性能问题。实现的方法有很多种,可以在读取数据时,将数据同时写入SSD,也可以在数据被刷出buffer时,写入到SSD。读取数据时,首先在buffer中查询,然后在flashcache中查询,最后读取datafile。

SSD作为flashcache与memcache作为数据库外部cache的最大区别在于,SSD掉电后数据是不丢失的,这也引起了另外一个思考,当数据库发生故障重启后,flashcache中的数据是有效还是无效?如果是有效的,那么就必须时刻保证flashcache中数据的一致性,如果是无效的,那么flashcache同样面临一个预热的问题(这与memcache掉电后的问题一样)。目前,据我所知,基本上都认为是无效的,因为要保持flashcache中数据的一致性,非常困难。

flashcache作为内存和磁盘之间的二级cache,除了性能的提升以外,从成本的角度看,SSD的价格介于memory和disk之间,作为两者之间的一层cache,可以在性能和价格之间找到平衡。

总结

随着SSD价格不断降低,容量和性能不断提升,SSD取代磁盘只是个时间问题。

Tape is Dead,Disk is Tape,Flash is Disk,RAM Locality is King.        Jim Gray

–EOF–

后续,我还会整理一个PPT,并提供一个技术分享。

相关 [ssd 数据库 性能优化] 推荐:

基于SSD的数据库性能优化

- Sungelina - Hello DBA
NOR和NAND都是闪存技术的一种,NOR是Intel公司开发的,它有点类似于内存,允许通过地址直接访问任何一个内存单元,缺点是:密度低(容量小),写入和擦除的速度很慢. NAND是东芝公司开发的,它密度高(容量大),写入和擦除的速度都很快,但是必须通过特定的IO接口经过地址转换之后才可以访问,有些类似于磁盘.

DB2数据库性能优化介绍

- - CSDN博客数据库推荐文章
作者:chszs,转载需注明. 博客主页: http://blog.csdn.net/chszs. 前段时间,我从CSDN得到了这本书《DB2数据库性能调整和优化(第2版)》,这是一本介绍DB2数据库性能调优的书籍,此书覆盖了DB2数据库性能调优所需的全部知识和工具,而且还提供了大量的性能调优的实际案例,颇有一种“一书在手,DB2尽在掌握”的豪情.

浅谈MySQL 数据库性能优化

- - BlogJava-qileilove
数据库是 IO 密集型的程序,和其他数据库一样,主要功能就是数据的持久化以及数据的管理. 本文侧重通过优化MySQL 数据库缓存参数如查询缓存,表缓存,. 日志缓存,索引缓存,innodb缓存,插入缓存,以及连接参数等方式来对MySQL数据库进行优化.   这里先引用一句话,从内存中读取一个数据的时间消耗是微秒级别,而从普通硬盘上读取一个数据是在毫秒级别,二者相差3个数量级.

MySQL 数据库性能优化之表结构

- tangfl - Sky.Jian 朝阳的天空
接着上一篇 MySQL 数据库性能优化之缓存参数优化 ,这是 MySQL数据库性能优化专题 系列的第二篇文章:MySQL 数据库性能优化之表结构. 很多人都将 数据库设计范式 作为数据库表结构设计“圣经”,认为只要按照这个范式需求设计,就能让设计出来的表结构足够优化,既能保证性能优异同时还能满足扩展性要求.

MySQL 数据库性能优化之缓存参数优化

- flychen50 - Sky.Jian 朝阳的天空
在平时被问及最多的问题就是关于 MySQL 数据库性能优化方面的问题,所以最近打算写一个MySQL数据库性能优化方面的系列文章,希望对初中级 MySQL DBA 以及其他对 MySQL 性能优化感兴趣的朋友们有所帮助. 这是 MySQL数据库性能优化专题 系列的第一篇文章:MySQL 数据库性能优化之缓存参数优化.

MySQL数据库性能优化之存储引擎选择

- - Sky.Jian 朝阳的天空
MySQL 数据库性能优化之SQL优化,这是  MySQL数据库性能优化专题 系列的第五篇文章:. MySQL数据库性能优化之存储引擎选择. 离上一篇文章已经有很长时间没有更新这个MySQL数据库性能优化专题了,时间太紧加上人之惰性,今天这里将之前就规划好的关于存储引擎选择方面的内容更新出来,希望对大家有所帮助吧.

MySQL数据库性能优化之硬件瓶颈分析

- - Sky.Jian 朝阳的天空
接着上一篇 MySQL数据库性能优化之存储引擎选择,这是 MySQL数据库性能优化专题 系列的第六篇文章: MySQL数据库性能优化之硬件优化. 在过往与很多人的交流过程中发现,在谈到基于硬件来进行数据库性能瓶颈分析的时候,常被大家误解为简单的使用更为强劲的主机或者存储来替换现有的设备. 个人觉得这其中可能存在一个非常大的误区.

数据库查询性能优化之利器—索引(一)

- - 博客园_首页
                   数据库查询性能优化之利器—索引(一).   最近在做基于Android的公交查询系统的过程中,遇到一个很棘手的问题:换乘算法效率低. 在直达查询和一次换乘查询的时候,问题体现的还不是很明显,能够在1s之内查询出乘车方案,而当进行二次查询的时候,基本要等一两分钟才能查询出换乘方案,这对于公交查询系统是绝对无法容忍的.

MySQL 数据库性能优化之SQL优化

- - OurMySQL
注:这篇文章是以 MySQL 为背景,很多内容同时适用于其他关系型数据库,需要有一些索引知识为基础. IO永远是数据库最容易瓶颈的地方,这是由数据库的职责所决定的,大部分数据库操作中超过90%的时间都是 IO 操作所占用的,减少 IO 次数是. SQL 优化中需要第一优先考虑,当然,也是收效最明显的优化手段.

MySQL数据库性能优化之表结构优化

- - haohtml's blog
由于MySQL数据库是基于行(Row)存储的数据库,而数据库操作 IO 的时候是以 page(block)的方式,也就是说,如果我们每条记录所占用的空间量减小,就会使每个page中可存放的数据行数增大,那么每次 IO 可访问的行数也就增多了. 反过来说,处理相同行数的数据,需要访问的 page 就会减少,也就是 IO 操作次数降低,直接提升性能.