向大型mysql表添加索引

use*_*477 16 mysql index index-tuning

我有一张桌子

| base_schedule_line_items | CREATE TABLE base_schedule_line_items(
idint(10) unsigned NOT NULL AUTO_INCREMENT,
installmentint(10) unsigned NOT NULL,
on_datedate NOT NULL,
actual_datedate DEFAULT NULL,
payment_typeint(11) NOT NULL,
scheduled_principal_outstandingdecimal(65,0) NOT NULL,
scheduled_principal_duedecimal(65,0) NOT NULL,
scheduled_interest_outstandingdecimal(65,0) NOT NULL,
scheduled_interest_duedecimal(65,0) NOT NULL,
currencyint(11) NOT NULL,
updated_atdatetime NOT NULL DEFAULT '2013-01-06 14:29:16',
created_atdatetime NOT NULL DEFAULT ' 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_schedule ( loan_base_schedule_id), KEY index_bslt_spd( scheduled_principal_due),
钥匙index_bslt_lending(lending_id),
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)
) ENGINE=InnoDB AUTO_INCREMENT=30410126 DEFAULT CHARSET=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", round(((data_length + index_length) / 1024 / 1024), 2) "Size in 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) "Size in 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 语句提取报告,我发现添加它们非常困难。任何帮助将不胜感激

geo*_*j11 17

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

  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. 将额外的记录加载到新创建的表(转储然后加载后出现的记录)。此步骤可以在 Step: 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


Der*_*ney 11

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

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

* 如果表上存在触发器,则该工具不起作用

交换和丢弃行为可以根据传递给工具的选项进行调整。

此外,外键也存在问题,因此请务必阅读该工具的文档以完全了解它在做什么。

当然,明智的做法是确保您有表的备份,以便在需要时能够恢复。