关于MySQL InnoDB存储引擎 text blob 大字段的存储和优化MYSQL教
《关于MySQL InnoDB存储引擎 text blob 大字段的存储和优化MYSQL教程》要点: 一、简介为了清楚大字段对性能的影响,我们必须要知道innodb存储引擎的处理方式:MYSQL学习 1、一些知识点?1.1 在InnoDB 1.0.x版本之前,InnoDB 存储引擎提供了? 对于blob,text,varchar(5120)这样的大字段,innodb只会存放前768字节在数据页中,而剩余的数据则会存储在溢出段中(发生溢出情况的时候适用),最大768字节的作用是便于创建前缀索引/prefix index,其余更多的内容存储在额外的page里,哪怕只是多了一个字节.因此,所有列长度越短越好MYSQL学习
?MYSQL学习 1.2 MySQL 5.1 中的 innodb_plugin 引入了新的文件格式: 1.3?innodb的page大小默认为16kb,innodb存储引擎表为索引组织表,树底层的叶子节点为一双向链表,因此每个页中至少应该有两行记录,这就决定了innodb在存储一行数据的时候不能够超过8k,但事实上应该更小,因为还有一些InnoDB内部数据结构要存储,5.6版本以后,新增选项 innodb_page_size 可以修改,在5.6以前的版本,只能修改源码重新编译,但并不推荐修改这个配置MYSQL学习 1.4?InnoDB的data page在有新数据写入时,会预留1/16的空间,预留出来的空间可用于后续的新纪录写入,减少频繁的新增data page的开销,受限于InnoDB存储方式,数据如果是顺序写入的话,最理想的情况下,data page的填充率是15/16,但一般没办法保证完全的顺序写入,因此data page的填充率一般是1/2到15/16.因此每个InnoDB表都最好要有一个自增列作为主键,使得新纪录写入尽可能是顺序的;当data page填充率不足1/2时,InnoDB会进行收缩,释放空闲空间MYSQL学习 1.5?COMPACT行格式相比REDUNDANT,大概能节省20%的存储空间,COMPRESSED相比COMPACT大概能节省50%的存储空间,但会导致TPS下降了90%.因此强烈不推荐使用COMPRESSED行格式MYSQL学习 1.6 使用了blob数据类型,是不是一定就会存放在溢出段中?通常我们认为blob这类的大对象的存储会把数据存放在数据页之外,其实不然,关键点还是要看一个page中到底能否存放两行数据,blob可以完全存放在数据页中(单行长度没有超过8096字节),而varchar类型的也有可能存放在溢出页中(单行长度超过8096字节,前768字节存放在数据页中)MYSQL学习 1.7 mysql在操作数据的时候,以page为单位,不管是更新,插入,删除一行数据,都需要将那行数据所在的page读到内存中,然后在进行操作,这样就存在一个命中率的问题,如果一个page中能够相对的存放足够多的行,那么命中率就会相对高一些,性能就会有提升MYSQL学习 1.8?在off-page中存储的BLOB、TEXT或者长VARCHAR列的page是独享的,不能共享.因此强烈不建议在一个表中使用多个长列MYSQL学习 1.9 MySQL 5.6 中默认还是 Compact 行格式,也是目前使用最多的一种 ROW FORMAT.用户可以通过命令?
在 msyql 5.7.9 及以后版本,默认行格式由 注意,如果要修改现有表的行模式为 二、对TEXT/BLOB这类大字段类型的影响2.1 compact变长大字段类型包括blob,varchar,其中varchar列值长度大于某数N时也会存溢出页,在latin1字符集下N值可以这样计算:innodb的块大小默认为16kb,由于innodb存储引擎表为索引组织表,减去其它列值所占字节数,约等于N.对于InnoDB,内存是极为珍贵的,如果把768字节长度的blob都放在数据页,虽然可以节省部分IO,但是能缓存行数就变少,也就是能缓存的索引值变少了,降低了索引效率MYSQL学习 2.2 dynamicdynamic行格式,列存储是否放到off-page页,主要取决于行大小,它会把行中最长的那一列放到off-page,直到数据页能存放下两行.TEXT/BLOB列 <=40 bytes 时总是存放于数据页.这种方式可以避免compact那样把太多的大列值放到 B-tree Node,因为dynamic格式认为,只要大列值有部分数据放在off-page,那把整个值放入都放入off-page更有效.MYSQL学习 compressed?物理结构上与dynamic类似,但是对表的数据行使用zlib算法进行了压缩存储.在long blob列类型比较多的情况下用,可以降低off-page的使用,减少存储空间(一般40%左右),但要求更高的CPU,buffer pool里面可能会同时存储数据的压缩版和非压缩版,所以也多占用部分内存.这里?MySQL 5.6 Manual innodb-compression-internals?讲的十分清楚.MYSQL学习 另外,由于 三. 对TEXT/BLOB型字段存取优化mysql的 io 以page为单位,因此不必要的数据(大字段)也会随着需要操作的数据一同被读取到内存中来,这样带来的问题由于大字段会占用较大的内存(相比其他小字段),使得内存利用率较差,造成更多的随机读取.从上面的分析来看,我们已经看到性能的瓶颈在于由于大字段存放在数据页中,造成了内存利用较差,带来过多的随机读,那怎么来优化掉这个大字段的影响MYSQL学习 3.1 压缩&合并a、innodb提供了barracuda文件格式,将大字段完全存放在溢出段中,数据段中只存放20个字节,这样就大大的减小了数据页的空间占用,使得一个数据页能够存放更多的数据行,也就提高了内存的命中率(对于本实例,大多数行的长度并没有超过8k,所以优化的幅度有限);如果对溢出段的数据进行压缩,那么在空间使用上也会大大的降低,具体的的压缩比率可以设置key_blok_size来实现.MYSQL学习 b、可以把大字段用COMPRESS()压缩后再存为BLOB,或者在发送到MySQL前在应用程序中进行压缩MYSQL学习 c、一张表有多个类blob字段,把它们组合起来如 d、如果预期长度范围varchar就满足,就避免使用TEXTMYSQL学习 3.2?拆分将主表拆分为一对一的两个关联表,将大字段单独放到另外一张表后,单行长度变的非常的小,page的行密度相比原来的表大很多,这样就能够缓存足够多的行,buffer pool的命中率就会提高,应用程序需要额外维护的是一张大字段的子表,还可以通过覆盖索引来优化,将索引和原表结构分开,从访问密度较小的数据页改为访问密度很大的索引页,随机io转换为顺序ioMYSQL学习 总结:还是让单个page能够存放足够多的行,不断的提示内存的命中率,从数据库底层存储的原理出发,能够更深刻的优化数据库MYSQL学习 综上,如果在实际业务中,确实需要在InnoDB表中存储BLOB、TEXT、长VARCHAR列时,有下面几点建议:MYSQL学习
?MYSQL学习 参考文档:http://www.hudong.com/wiki/%E3%80%8AMySQL%E6%8A%80%E6%9C%AF%E5%86%85%E5%B9%95%EF%BC%9AInnoDB%E5%AD%98%E5%82%A8%E5%BC%95%E6%93%8E%E3%80%8BMYSQL学习 http://www.mysqlperformanceblog.com/2008/01/11/mysql-blob-compression-performance-benefits/MYSQL学习 http://www.mysqlperformanceblog.com/2012/05/30/data-compression-in-innodb-for-text-and-blob-fields/MYSQL学习 http://yoshinorimatsunobu.blogspot.com/2010/11/handling-long-textsblobs-in-innodb-1-to.htmlMYSQL学习 http://blog.opskumu.com/mysql-blob.htmlMYSQL学习 http://hidba.org/?p=551MYSQL学习 http://blog.chinaunix.net/uid-24485075-id-3523032.htmlMYSQL学习 http://dev.mysql.com/doc/refman/5.6/en/innodb-row-format-dynamic.htmlMYSQL学习 (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |