`
student_lp
  • 浏览: 437253 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类
最新评论
阅读更多

    一些应用,在表结构的设计上使用了text或者blob的字段;其中一个应用,对blob字段的依赖非常的严重,查询和更新的频率也是非常的高,单表的存储空间已经达到了近100G,这个时候,应用其实已经被数据库绑死了,任何应用或者查询逻辑的变更几乎成为不可能;

    为了清楚大字段对性能的影响,我们必须要知道innodb存储引擎在底层对行的处理方式:

  • 在5.1中,innodb存储引擎的默认的行格式为compact(redundant为兼容以前的版本),对于blob,text,varchar(8099)这样的大字段,innodb只会存放前768字节在数据页中,而剩余的数据则会存储在溢出段中(发生溢出情况的时候适用);
  • innodb的块大小默认为16kb,由于innodb存储引擎表为索引组织表,树底层的叶子节点为一双向链表,因此每个页中至少应该有两行记录,这就决定了innodb在存储一行数据的时候不能够超过8k(8098字节);
  • 使用了blob数据类型,是不是一定就会存放在溢出段中?通常我们认为blob,clob这类的大对象的存储会把数据存放在数据页之外,其实不然,关键点还是要看一个page中到底能否存放两行数据,blob可以完全存放在数据页中(单行长度没有超过8098字节),而varchar类型的也有可能存放在溢出页中(单行长度超过8098字节,前768字节存放在数据页中);
  • 5.1中的innodb_plugin引入了新的文件格式:barracuda(将compact和redundant合称为antelope),该文件格式拥有新的两种行格式:compressed和dynamic,两种格式对blob字段采用完全溢出的方式,数据页中只存放20字节,其余的都存放在溢出段中:

  • mysql在操作数据的时候,以page为单位,不管是更新,插入,删除一行数据,都需要将那行数据所在的page读到内存中,然后在进行操作,这样就存在一个命中率的问题,如果一个page中能够相对的存放足够多的行,那么命中率就会相对高一些,性能就会有提升;

    有了上面的知识点,我们一起看看该应用的特点,表结构:

CREATE TABLE `xx_msg` (
  `col_user` VARCHAR(64)  NOT NULL,
  `col_smallint` SMALLINT(6) NOT NULL,
  `col_lob` longblob,
  `gmt_create` datetime DEFAULT NULL,
  `gmt_modified` datetime DEFAULT NULL,
  PRIMARY KEY (`xxx`)
) ENGINE=InnoDB DEFAULT CHARSET=gbk

   col_lob为blob字段,用于存放该用户的所有的消息,其平均长度在2.4kb左右,该表中其他剩余的字段则是非常的小,大致在60字节左右

SELECT avg(LENGTH(col_clob)) FROM (SELECT * fromxxx_msg LIMIT 30000)a;
|         2473.8472 |

   该表的应用场景包括:

1) select col_user ,col_smallint,DATE_FORMAT(gmt_modified,’%Y-%m-%d’) from xx_msg;

2) update xx_msg set gmt_modified=’2012-03-31 23:16:30′,col_smallint=1,col_lob=’xxx’ where col_user=’xxx’;

3) select col_smallint from xx_msg where user=’xxx’;

可以看到由于单行的平均长度(2.5k)还远小于一个innodb page的size(16k)(当然也有存在超过8k的行),也就是知识点三中提到的,blob并不会存放到溢出段中,而是存放到数据段中去,innodb能够将一行的所有列(包括longlob)存储在数据页中:


    在知识点五中,mysql的io以page为单位,因此不必要的数据(大字段)也会随着需要操作的数据一同被读取到内存中来,这样带来的问题由于大字段会占用较大的内存(相比其他小字段),使得内存利用率较差,造成更多的随机读取。

    从上面的分析来看,我们已经看到性能的瓶颈在于由于大字段存放在数据页中,造成了内存利用较差,带来过多的随机读,那怎么来优化掉这个大字段的影响:

一.压缩:

    在知识点四中,innodb提供了barracuda文件格式,将大字段完全存放在溢出段中,数据段中只存放20个字节,这样就大大的减小了数据页的空间占用,使得一个数据页能够存放更多的数据行,也就提高了内存的命中率(对于本实例,大多数行的长度并没有超过8k,所以优化的幅度有限);如果对溢出段的数据进行压缩,那么在空间使用上也会大大的降低,具体的的压缩比率可以设置key_blok_size来实现。

二.拆分:

    将主表拆分为一对一的两个关联表:

CREATE TABLE `xx_msg` (
  `col_user` VARCHAR(64)  NOT NULL,
  `col_smallint` SMALLINT(6) NOT NULL,
  `gmt_create` datetime DEFAULT NULL,
  `gmt_modified` datetime DEFAULT NULL,
  PRIMARY KEY (`xxx`)
) ENGINE=InnoDB DEFAULT CHARSET=gbk;
 
CREATE TABLE `xx_msg_lob` (
  `col_user` VARCHAR(64)  NOT NULL,
  `col_lob` longblob,
   PRIMARY KEY (`xxx`)
) ENGINE=InnoDB DEFAULT CHARSET=gbk

   xx_msg表由于将大字段单独放到另外一张表后,单行长度变的非常的小,page的行密度相比原来的表大很多,这样就能够缓存足够多的行,表上的多个select由于buffer pool的高命中率而受益;应用程序需要额外维护的是一张大字段的子表;

三.覆盖索引:

   在上面的两个查询当中,都是查询表中的小字段,由于老的方案需要全表或者根据主键来定位表中的数据,但是还是以page为单位进行操作,blob字段存在还是会导致buffer pool命中率的下降,如果通过覆盖索引来优化上面的两个查询,索引和原表结构分开,从访问密度较小的数据页改为访问密度很大的索引页,随机io转换为顺序io,同时内存命中率大大提升;额外的开销为数据库多维护一个索引的代价;

    alter table xx_msg add index ind_msg(col_user ,col_smallint,gmt_modified);

    对于查询一,原来的执行计划为走全表扫描,现在通过全索引扫描来完成查询;

    对于查询二,原来的执行计划为走主键PK来定位数据,现在该走覆盖索引ind_msg完成查询;

    注意上面的两个查询为了稳固执行计划,需要在sql执行中加入hint提示符来强制sql通过索引来完成查询;

    总结:上面三种思路来优化大字段,其核心思想还是让单个page能够存放足够多的行,不断的提示内存的命中率,尽管方法不同,但条条大路通罗马,从数据库底层存储的原理出发,能够更深刻的优化数据库,扬长避短,达到意想不到的效果。

转子:http://hidba.org/?p=551

  • 大小: 11.8 KB
  • 大小: 9.7 KB
  • 大小: 17.9 KB
分享到:
评论

相关推荐

    mysql查询的时候给字段赋默认值操作

    虽然使用`IFNULL()`函数可以提供数据完整性,但要注意这可能会对查询性能产生影响。如果`IFNULL()`涉及的字段是索引的一部分,查询性能可能会下降,因为数据库需要检查更多的行来确定是否需要应用默认值。在这种...

    mysql优化字段存储----优化查询效率.pdf

    索引的长度也会对数据库的性能产生影响。索引长度短的查询起来就快,但并非越短越好。过短会使得数据查询不精确,而过长查询效率又得不到有效提升,还占用存储空间。 优化字段存储 除了建立索引外,还可以通过优化...

    测试MySQL时区设置对查询效率的影响1

    总结来说,MySQL的时区设置对查询效率有直接影响,尤其是在多线程并发和时间字段频繁使用的场景下。优化时区设置可以减少不必要的时区转换,从而提高查询性能。对于高并发和时间敏感的业务,建议根据实际需求设定...

    MySQL中join语句的基本使用教程及其字段对性能的影响

    字段字符集编码对性能的影响不容忽视。不同的字符集可能会导致不同的存储需求和处理速度。例如,如果一个JOIN操作涉及到两个字段,它们在不同的表中但使用了不同的字符集,那么JOIN操作可能会变得非常慢,因为数据库...

    一个完整的数据库图片字段转化为本地图片的例子

    8. **优化与性能**:大量图片的转换可能会对数据库性能产生影响,因此需要考虑批量处理、缓存机制或异步处理等优化策略。 9. **安全性**:确保在读取和写入文件时遵循安全最佳实践,防止数据泄露或恶意攻击。 10. ...

    SQL Server交叉查询存储过程实现(带查询条件)

    * 性能问题:交叉查询可能会对数据库性能产生影响,因此需要对数据库进行优化和维护。 * 数据一致性:交叉查询需要确保数据的一致性,以免出现数据不一致的问题。 * 安全问题:交叉查询需要确保数据库的安全,以免...

    SQL-ORDER BY 多字段排序(升序、降序)

    需要注意的是,`ORDER BY`操作可能会对查询性能产生影响,特别是在处理大型数据集时。因此,如果可能,应考虑创建相应的索引来优化排序过程。索引可以在数据库中预先组织数据,使其能更快地根据指定的列进行查找和...

    plsql删除重复记录

    特别是在大型企业级应用中,由于各种原因(如数据导入错误、系统故障等),数据库表中可能会出现大量的重复记录,这对数据的准确性和系统的性能都会产生负面影响。因此,掌握如何有效地识别并删除这些重复记录显得尤...

    查询语句对SQL Server数据库查询性能优化分析.pdf

    例如,当需要对某个字段进行查询时,如果该字段已经建立了索引,那么可以采用范围查询等方法来提高查询效率。 综合以上分析,我们可以得出以下几点重要的SQL Server数据库查询性能优化策略: 1. 利用过程缓存,...

    查询优化:sql2000中的连接两个表的查询语句的执行路径对性能的影响比较

    - **索引的使用**:索引的存在和选择性极大地影响连接性能。如果一个表的连接字段上有索引,那么这个索引通常会被用来加速连接。 - **数据量**:如果一个表的记录数远大于另一个,通常会选择小表作为驱动表,以减少...

    数据库中identity字段不必是系统产生的唯一值 性能优化方法(新招)

    另一种方法是通过查询现有最大`sessionid`并加1来获取新的`sessionid`,但这会增加数据库的查询负担,影响性能。因此,第一种方法通常更优,因为它减少了对数据库的交互次数。 数据库性能优化是一个广泛的领域,...

    SQL Server 海量数据查询代码优化以及建议

    由于数据库查询效率直接影响到系统的响应速度和用户体验,对查询语句的优化显得至关重要。 1. 避免在where子句中对字段进行null值判断是优化查询的一个重要方面。在SQL Server中,null值的比较会导致查询无法利用...

    Sql Server中一个表2个字段关联同一个表(代码解决)

    值得注意的是,这样的设计可能会导致数据冗余,因为`man`表中的`man_id`字段在`zw`表中重复出现,这可能对数据库的性能和维护性产生影响。在设计数据库时,考虑使用外键和多对多关系表可能会更合适。例如,可以创建...

    oracle 查询重复数据

    - **子查询**: `(select peopleid from people group by peopleid having count(peopleid) > 1)` 这部分首先从`people`表中选择`peopleid`字段,然后使用`GROUP BY`对`peopleid`进行分组,计算每组的`peopleid`数量...

    sql查询优化 查询优化

    根据系统负载和硬件配置,适当调整数据库的配置参数,如缓存大小、并发连接数等,也能对查询性能产生积极影响。 总之,SQL查询优化是一个涉及多个层面的综合过程,需要结合具体的应用场景和数据库系统特性,通过...

    深入Elasticsearch:掌握前缀查询的艺术

    尽管前缀查询非常强大且有用,但在某些情况下可能会对性能产生负面影响,尤其是处理大量数据时。为了优化前缀查询的性能,可以采取以下措施: 1. **使用缓存**:对于频繁执行的查询,可以在应用程序级别缓存结果,...

    修改当前行字段的触发器

    在数据库管理领域,触发器(Trigger)是一种存储过程,它被设计用于响应特定类型的对一个表的数据的操作(如INSERT、UPDATE或DELETE),并自动执行预定义的SQL语句。触发器是实现数据库完整性、安全性和业务规则的...

    PHP中查询SQL Server或Sybase时TEXT字段被截断的解决方法

    设置得过小可能会再次遇到截断问题,而设置得过大又可能对性能产生影响或增加内存消耗。因此,在实际开发过程中,需要在保证数据完整性与系统性能之间做出权衡。 此外,根据文档内容,由于文档可能是通过OCR扫描...

    论MS SQL Server数据库查询优化技巧.pdf

    数据表的设计同样会对查询性能产生重要影响。字符类型的选择需要根据存储数据的实际情况来确定,固定长度的数据类型如char、nchar和binary适合存储长度一致的数据,而可变长度的数据类型varchar、nvarchar和...

    基于SQL语句查询优化分析的研究.pdf

    5. **调整数据库配置**:根据实际情况调整数据库的相关配置参数,比如缓存大小、并发控制策略等,也能对查询性能产生积极影响。 6. **定期维护**:定期对数据库进行维护,如重建索引、清理冗余数据等,也是保持查询...

Global site tag (gtag.js) - Google Analytics