向大型mysql表添加索引


13

我有桌子

| base_schedule_line_items | CREATE TABLE base_schedule_line_items
idint(10)unsigned NOT NULL AUTO_INCREMENT,
installmentint(10)unsigned NOT NULL,
on_date日期NOT NULL,
actual_date日期默认值,
payment_typeint(11)NOT NULL,
scheduled_principal_outstanding十进制(65,0)NOT NULL,
scheduled_principal_due十进制(65,0) NOT NULL,
scheduled_interest_outstanding十进制(65,0)NOT NULL,
scheduled_interest_due十进制(65,0)NOT NULL,
currencyint(11)NOT NULL,
updated_at日期时间NOT NULL缺省'2013-01-06 14:29:16',
created_atdatetime NOT NULL默认值' 2013-01-06 14:29:16',
loan_base_schedule_idint(10)unsigned NOT NULL,
lending_idint(10)unsigned NOT NULL,
rescheduletinyint(1)DEFAULT'0',
PRIMARY KEY(id),
KEY index_base_schedule_line_items_loan_base_scheduleloan_base_schedule_id),KEY index_bslt_spdscheduled_principal_due),
index_bslt_lendinglending_id),
KEY index_bslt_actualdateactual_date),
KEY index_bslt_spsilaloan_base_schedule_idscheduled_principal_duescheduled_interest_dueactual_date),
KEY index_bslt_ondateon_date),
KEY index_bslt_oaon_dateactual_date),
KEY index_bslt_olon_dateloan_base_schedule_id),
KEY index_bslt_olion_datelending_id
)ENGINE = InnoDB的AUTO_INCREMENT = 30410126默认字符集= UTF8 |

现在该表中有3000万条记录,我需要为此添加两个索引,并且添加它需要花费数年的时间。

更改表base_schedule_line_items并添加索引index_bslt_sla(scheduled_principal_due,actual_date,lending_id);
更改表base_schedule_line_items添加索引index_bslt_ssla(scheduled_principal_due,scheduled_interest_due,lending_id,actual_date);

我使用下面提到的查询来找出表的大小

SELECT table_name AS“ Tables”,圆形((((data_length + index_length)/ 1024/1024),2)“以MB为单位的大小” FROM information_schema.TABLES WHERE table_schema =“ my_database_name”;

结果出来是

base_schedule_line_items | 20111.00

我只是用来计算数据长度,而忽略了索引长度

SELECT table_name AS“ Tables”,round((((data_length)/ 1024/1024),2)“在MB中的大小” FROM information_schema.TABLES WHERE table_schema =“ my_database_name”;

结果是

base_schedule_line_items | 9497.00

指标

KEY index_bslt_actualdate(actual_date),
KEY index_bslt_spsila(loan_base_schedule_id,scheduled_principal_due,scheduled_interest_due,actual_date),
KEY index_bslt_ondate(on_date),
KEY index_bslt_oa(on_date,actual_date),
KEY index_bslt_ol(on_date,loan_base_schedule_id),
KEY index_bslt_oli(on_date,lending_id)

是由我添加的,但我不确定或添加其他索引的目的是什么。这是相当大的应用程序。现在,我需要添加上面提到的这两个索引,因为它们可以帮助我使用select语句提取报告,并且发现添加它们非常困难。任何帮助将不胜感激

Answers:


16

更改大表的活动分阶段完成:

  1. 在测试数据库(仅结构)中创建具有所需字段和索引的新表
  2. 从现有表中转储数据并将其加载到测试数据库中新创建的表中
  3. 现在宣布您的停机时间:)
  4. 通过重命名交换表- RENAME table ur_db.table_name to test.temp, test.table_name to ur_db.table_name, test.temp to test.table_name;这是耗时不到一秒的原子操作。
  5. 将多余的记录加载到新创建的表中(转储然后加载后出现的记录)。此步骤可以在步骤:3之前完成,也可以减少一次停机时间。
  6. 您的系统又回来了

几点注意事项:

  1. 您不需要像这样直接点击信息模式,请尝试使用 SHOW TABLE STATUS from db like 'table_name'
  2. alter table的速度或多或少与I / O速度相关。上次运行直接更改表(不执行上述步骤)时,我们拥有40GB +的表大小,大约花了4个小时。如果20GB的数据要花费数年,则说明您正在使用某些过时的计算机。
  3. index_bslt_ondate, index_base_schedule_line_items_loan_base_schedule其他一些索引一样,删除不需要的索引也将最左边的列作为索引列

如果您需要对这些步骤中的任何一个进行澄清,请告诉我。

编辑:一个简单的python脚本来自动化过程https://github.com/georgecj11/hotswap_mysql_table.git


10

您可以使用pt-online-schema-change之类的工具来添加索引,而不会阻塞您的应用程序。基本逻辑如下:

  • 使用新索引创建表的空副本
  • 向现有表添加触发器,以便将对表进行的任何更改应用于表的副本*
  • 开始将行从旧表复制到新表
  • 复制完成后,将表换出
  • 放下旧桌子

*如果表格上已有触发器,则该工具不起作用

可以根据传递给工具的选项来调整交换和删除行为。

另外,外键存在问题,因此请务必阅读该工具的文档以完全了解其功能。

当然,明智的做法是确保您具有表的备份,以便能够根据需要进行还原。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.