浅析MySQL数据碎片的产生

2011-03-30 09:28 核子可乐译 51CTO 字号:T | T

MySQL列表,包括MyISAM和InnoDB这两种最常见的类型,而根据经验来说,其碎片的产生及消除都是随机的。碎片会在你的表格中留下明显的空白,而这会给列表扫描工作带来相当大的困扰。对你的列表进行优化,这样会使列表的全面及分区扫描工作进行得更有效率。

AD:51CTO 网+首届APP创新评选大赛火热启动——超百万资源等你拿!

【51CTO独家译文】本文浅析MySQL数据碎片的产生:定义,时间及成因。

MySQL列表,包括MyISAMInnoDB这两种最常见的类型,而根据经验来说,其碎片的产生及消除都是随机的。碎片会在你的表格中留下明显的空白,而这会给列表扫描工作带来相当大的困扰。对你的列表进行优化,这样会使列表的全面及分区扫描工作进行得更有效率。

碎片——实例

MySQL具有相当多不同种类的存储引擎来实现列表中的数据存储功能。 每当MySQL从你的列表中删除了一行内容,该段空间就会被留空。而在一段时间内的大量删除操作,会使这种留空的空间变得比存储列表内容所使用的空间更 大。当MySQL对数据进行扫描时,它扫描的对象实际是列表的容量需求上限,也就是数据被写入的区域中处于峰值位置的部分。如果进行新的插入操 作,MySQL将尝试利用这些留空的区域,但仍然无法将其彻底占用。

这种额外的破碎的存储空间在读取效率方面比正常占用的空间要低得多。让我们看一个实例。

我们将创建一个数据库(有时也称其为大纲)及一个测试用的列表:

  1. (root@localhost) [test]> create database frag_test;
  2. Query OK, 1 row affected (0.03 sec)
  3. (root@localhost) [test]> use frag_test;
  4. Database changed
  5. (root@localhost) [frag_test]> create table frag_test (c1 varchar(64));
  6. Query OK, 0 rows affected (0.05 sec)

现在让我们在列表中加入如下几行:

  1. (root@localhost) [frag_test]> insert into frag_test values ('this is row 1');
  2. Query OK, 1 row affected (0.01 sec)
  3. (root@localhost) [frag_test]> insert into frag_test values ('this is row 2');
  4. Query OK, 1 row affected (0.00 sec)
  5. (root@localhost) [frag_test]> insert into frag_test values ('this is row 3');
  6. Query OK, 1 row affected (0.00 sec)

现在我们进行碎片查看:

  1. (root@localhost) [frag_test]> show table status from frag_test\G;
  2. *************************** 1. row ***************************
  3. Name: frag_test
  4. Engine: MyISAM
  5. Version: 10
  6. Row_format: Dynamic
  7. Rows: 3
  8. Avg_row_length: 20
  9. Data_length: 60
  10. Max_data_length: 281474976710655
  11. Index_length: 1024
  12. Data_free: 0
  13. Auto_increment: NULL
  14. Create_time: 2011-02-23 14:55:27
  15. Update_time: 2011-02-23 15:06:55
  16. Check_time: NULL
  17. Collation: latin1_swedish_ci
  18. Checksum: NULL
  19. Create_options:
  20. Comment:
  21. 1 row in set (0.00 sec)

现在我们删除一行,并再次检测:

  1. (root@localhost) [frag_test]> delete from frag_test where c1 = 'this is row 2';
  2. Query OK, 1 row affected (0.00 sec)
  3. (root@localhost) [frag_test]> show table status from frag_test\G;
  4. *************************** 1. row ***************************
  5. Name: frag_test
  6. Engine: MyISAM
  7. Version: 10
  8. Row_format: Dynamic
  9. Rows: 2
  10. Avg_row_length: 20
  11. Data_length: 60
  12. Max_data_length: 281474976710655
  13. Index_length: 1024
  14. Data_free: 20
  15. Auto_increment: NULL
  16. Create_time: 2011-02-23 14:55:27
  17. Update_time: 2011-02-23 15:07:49
  18. Check_time: NULL
  19. Collation: latin1_swedish_ci
  20. Checksum: NULL
  21. Create_options:
  22. Comment:
  23. 1 row in set (0.00 sec)

需要注意的是,“data_free”一栏显示出了我们删除第二行后所产生的留空空间。想象一下如果你有两万行指令的话,结果是什么样的。以此推 算,它们将耗费四十万字节的存储空间。现在如果你将两万条命令行删到只剩一行,列表中有用的内容将只占二十字节,但MySQL在读取中会仍然将其视同于一 个容量为四十万字节的列表进行处理,并且除二十字节以外,其它空间都被白白浪费了。

清理碎片

幸运的是一旦你锁定了这一问题,MySQL提供了一种简便的修正方法。这就是所谓的优化列表,具体内容如下:

  1. (root@localhost) [frag_test]> optimize table frag_test;
  2. +---------------------+----------+----------+----------+
  3. | Table               | Op       | Msg_type | Msg_text |
  4. +---------------------+----------+----------+----------+
  5. | frag_test.frag_test | optimize | status   | OK       |
  6. +---------------------+----------+----------+----------+
  7. 1 row in set (0.00 sec)
  8. (root@localhost) [frag_test]> show table status from frag_test\G;
  9. *************************** 1. row ***************************
  10. Name: frag_test
  11. Engine: MyISAM
  12. Version: 10
  13. Row_format: Dynamic
  14. Rows: 2
  15. Avg_row_length: 20
  16. Data_length: 40
  17. Max_data_length: 281474976710655
  18. Index_length: 1024
  19. Data_free: 0
  20. Auto_increment: NULL
  21. Create_time: 2011-02-23 14:55:27
  22. Update_time: 2011-02-23 15:11:05
  23. Check_time: 2011-02-23 15:11:05
  24. Collation: latin1_swedish_ci
  25. Checksum: NULL
  26. Create_options:
  27. Comment:
  28. 1 row in set (0.00 sec)

性能考量

“优化列表”功能在进行中会对整个列表进行锁定。对于小型列表,这一功能的效果非常好,因为整个列表的读取和修改速度都会很快。但对于那些体积巨大的列表来说,这一过程将消耗很长时间,并且其间会中断或减少可用的应用程序数量。怎么办?

再一次,MySQL幸运地提供了一项堪称伟大的功能,名为“主-主复制”。 在这种配置之下,你的后台数据库实际上成为两个单独的数据库,一个主动可调用的,一个被动可调整的。这两个数据库在各方面来说都是完全相同的。要实现各种 在线操作——包括“优化列表”操作——只需在你的被动数据库中即可进行。这将不会对你的应用程序造成丝毫影响。一旦优化操作完成,主、被动数据库将互相转 换,以便应用程序直接指向二号数据库,对还未进行优化的主动数据库部分自动开始优化工作。

这时,两套数据库的角色已经互换,而应用程序也将顺利指向二号数据库,执行与在一号数据库上相同的列表优化。而现在主动已经转换为被动,因此不会中断主要任务处理。

其它命令

显示你数据库中存在碎片的全部列表:

  1. (root@localhost) [(none)]> select table_schema, table_name, data_free, engine from information_schema.tables where table_schema not in ('information_schema', 'mysql') and data_free > 0;
  2. +--------------+-----------------------------+-----------+--------+
  3. | table_schema | table_name                  | data_free | engine |
  4. +--------------+-----------------------------+-----------+--------+
  5. | aitc         | wp_comments                 |    346536 | MyISAM |
  6. | aitc         | wp_options                  |     64308 | MyISAM |
  7. | aitc         | wp_postmeta                 |       124 | MyISAM |
  8. | cactidb      | poller_item                 |       160 | MyISAM |
  9. | cactidb      | poller_output               |       384 | MyISAM |
  10. | drupal       | sessions                    |     30976 | MyISAM |
  11. | drupal       | users                       |        92 | MyISAM |
  12. | drupal       | variable                    |        20 | MyISAM |
  13. | gg           | wp_comments                 |       232 | MyISAM |
  14. | gg           | wp_options                  |       696 | MyISAM |
  15. | gg           | wp_postmeta                 |       560 | MyISAM |
  16. | ihi          | wp_comments                 |       536 | MyISAM |
  17. | ihi          | wp_options                  |       444 | MyISAM |
  18. | ihi          | wp_postmeta                 |       288 | MyISAM |
  19. | ihi          | wp_redirection_items        |      1292 | MyISAM |
  20. | ihi          | wp_redirection_logs         |    140352 | MyISAM |
  21. | nds          | wp_comments                 |      4704 | MyISAM |
  22. | nds          | wp_options                  |    150580 | MyISAM |
  23. | nds          | wp_postmeta                 |        76 | MyISAM |
  24. | oos          | wp_comments                 |    317124 | MyISAM |
  25. | oos          | wp_options                  |     88196 | MyISAM |
  26. | oos          | wp_postmeta                 |        76 | MyISAM |
  27. | phplist      | phplist_listuser            |       252 | MyISAM |
  28. | phplist      | phplist_sendprocess         |        52 | MyISAM |
  29. | phplist      | phplist_user_user           |     32248 | MyISAM |
  30. | phplist      | phplist_user_user_attribute |       120 | MyISAM |
  31. | phplist      | phplist_user_user_history   |       288 | MyISAM |
  32. | phplist      | phplist_usermessage         |      1428 | MyISAM |
  33. | pn_nds       | nuke_session_info           |     12916 | MyISAM |
  34. | psa          | exp_event                   |     10024 | MyISAM |
  35. | test         | active_sessions             |     30144 | MyISAM |
  36. +--------------+-----------------------------+-----------+--------+
  37. 31 rows in set (0.26 sec)

如果你更改了某个列表的存储引擎,你也应该对这一列表进行碎片清理。这是因为MySQL的工作原理导致其必须读取整个列表,然后利用新的存储引擎将内容写回磁盘,而在此过程中碎片所在的位置及影响到的数据都对执行效率造成了严重的不良影响。

上述情况如下所示:

  1. (root@localhost) [frag_test]> alter table frag_test engine = innodb;
  2. Query OK, 2 rows affected (0.17 sec)
  3. Records: 2  Duplicates: 0  Warnings: 0
  4. (root@localhost) [frag_test]> show table status from frag_test
  5. -> \G;
  6. *************************** 1. row ***************************
  7. Name: frag_test
  8. Engine: InnoDB
  9. Version: 10
  10. Row_format: Compact
  11. Rows: 2
  12. Avg_row_length: 8192
  13. Data_length: 16384
  14. Max_data_length: 0
  15. Index_length: 0
  16. Data_free: 0
  17. Auto_increment: NULL
  18. Create_time: 2011-02-23 15:41:12
  19. Update_time: NULL
  20. Check_time: NULL
  21. Collation: latin1_swedish_ci
  22. Checksum: NULL
  23. Create_options:
  24. Comment: InnoDB free: 7168 kB
  25. 1 row in set (0.00 sec)

结论

如果你发现一些列表中包含了大量的数据留空现象,那么对其进行优化是绝对值得的,因为这一过程会大大提升列表的读取性能及应用表现。

原文地址:http://www.databasejournal.com/features/mysql/article.php/3927871/article.htm

浅析MySQL数据碎片的产生(data free)的更多相关文章

  1. 浅析Mysql 数据回滚错误的解决方法

    介绍一下关于Mysql数据回滚错误的解决方法.需要的朋友可以过来参考下 MYSQL的事务处理主要有两种方法.1.用begin,rollback,commit来实现begin 开始一个事务rollbac ...

  2. 浅析Mysql数据回滚错误的解决方法

    介绍一下关于Mysql数据回滚错误的解决方法.需要的朋友可以过来参考下   MYSQL的事务处理主要有两种方法.   1.用begin,rollback,commit来实现   begin 开始一个事 ...

  3. astgo经常死机变慢?试试mysql数据碎片整理吧

    使用SSH之类的工具或navicat链接数据库后(注意:是链接数据库后哦,不是直接SSH后就弄,这样提示命令错误的) 执行下面命令(目的是对ASTGO的数据库内除话单之外的所有表进行数据碎片整理,特别 ...

  4. mysql数据库-mysql数据定义语言DDL (Data Definition Language)归类(六)

    0x01 创建数据库并指定字符集和排序规则 -- 三种实例写法 create database temptab2 character set utf8 collate utf8_general_ci; ...

  5. MYSQL数据回流

         一般的网站应用中,总会有部分二次数据(处理过的原始数据)展现给前台,比如,拿购物网站来说,购买进口奶粉最多的用户群体:哪类产品消费增长趋势最旺盛:用户的消费历史归类等都是二次数据.由于这部分 ...

  6. mysql快速导入5000万条数据过程记录(LOAD DATA INFILE方式)

    mysql快速导入5000万条数据过程记录(LOAD DATA INFILE方式) 首先将要导入的数据文件top5000W.txt放入到数据库数据目录/var/local/mysql/data/${d ...

  7. 辛星浅谈mysql中的数据碎片以及引擎为MyISAM下的操作

    对于mysql中的数据碎片,事实上和我们删除数据是息息相关的,删除数据的时候必定会在数据文件里造成不连续的空白空间,对于少量的数据的删除,并不会产生多少的空白空间.假设在一段时间内的大量的删除操作,会 ...

  8. Mysql备份系列(4)--lvm-snapshot备份mysql数据(全量+增量)操作记录

    Mysql最常用的三种备份工具分别是mysqldump.Xtrabackup(innobackupex工具).lvm-snapshot快照.前面分别介绍了:Mysql备份系列(1)--备份方案总结性梳 ...

  9. 两种适用于中小量数据的mysql数据备份

    近来项目的业务量开始大了,感觉如果数据不周期性地备份一下,很可能会出现问题,虽然我每天都有阿里云的自动快照,上网找了一下方法,找到两种相对简单而又适合中小项目或者中小公司的数据备份策略,以下都是数据库 ...

随机推荐

  1. Android 隐式意图的配置

    本文地址:http://www.cnblogs.com/wuyudong/p/5677473.html,转载请注明源地址. <Android 显示意图激活另外一个Actitity>一文介绍 ...

  2. android关于线程的那些事

    今天发现之前自己一直有个误区,new Runnable(run()方法){}原来它不是一定创建一个线程 如果用主线程的handler去post(Runnable),他就不会创建子线程,而是在主线程上执 ...

  3. Android 中MyApplication

    package liu.basedemo; import android.app.Activity; import android.app.Application; import java.lang. ...

  4. Java ThreadLocal

    ThreadLocal类,代表一个线程局部变量,通过把数据放在ThreadLocal中,可以让每个线程创建一个该变量的副本.也可以看成是线程同步的另一种方式吧,通过为每个线程创建一个变量的线程本地副本 ...

  5. 布局display

    什么是布局: 浏览器以正确的大小将元素摆放在正确的位置上. 布局:元素摆放的模式. 影响元素大小和位置的css属性: display  position   float  flex display 设 ...

  6. js技术发展

    将.NET代码编译为JavaScript 你可以使用如下工具将C#.F#以及其他.NET代码编译为JavaScript代码. Apps in Motion:允许使用C#来构建可以运行在任何设备上的We ...

  7. [20140117]疑似checkpoint堵塞数据库连接

    注:这个说法是不成立的,问题已经解决,但是无法正确的定位到具体什么原因:[20140702]奇怪的应用程序超时 背景: 开发通过应用程序的日志发现间歇性的出现,数据库连接超时 原因: 只能大概猜测,没 ...

  8. form.submit() not a function的元凶

    今天晚上学习jquery form plugin时,在明白了该插件的用法时, (1)该插件是将form的HTTP请求 改为AJax请求. (2)支持像jQuery.ajax(options)一样 的o ...

  9. SQLServer基本函数

    1.字符串函数  长度与分析用 datalength(Char_expr) 返回字符串包含字符数,但不包含后面的空格 substring(expression,start,length) 取子串 ri ...

  10. Mysql中使用find_in_set函数查找字符串

    mysql有个表的字段的存储是以逗号分隔的,如domain字段login.s01.yy.com,s01.yy.com,s02.yy.com.现在要查找s01.yy.com这个.我们用like查找好像不 ...