Mysql - 估计下降时间索引

时间:2017-05-08 21:10:48

标签: mysql indexing

我们有一个相当未优化的表,其定义如下:

CREATE TABLE `Usage` (
 `TxnDate` varchar(30) DEFAULT NULL,
 `TxnID` decimal(13,2) NOT NULL,
 `UserID2015` varchar(20) DEFAULT NULL,
 `UserRMN` decimal(13,0) DEFAULT NULL,
 `CustomerNo` decimal(13,0) DEFAULT NULL,
 `OperatorName` varchar(50) DEFAULT NULL,
 `AggregatorName` varchar(30) DEFAULT NULL,
 `TransAmount` decimal(10,2) DEFAULT NULL,
 `MMPLTxnID` decimal(13,0) DEFAULT NULL,
 `ProductType` varchar(30) DEFAULT NULL,
 `YearMonthRMN` varchar(50) DEFAULT NULL,
 PRIMARY KEY (`TxnID`),
 UNIQUE KEY `TxnID` (`TxnID`) USING BTREE,
 KEY `TxnDate` (`TxnDate`),
 KEY `OperatorName` (`OperatorName`),
 KEY `AggregatorName` (`AggregatorName`),
 KEY `MMPLTxnID` (`MMPLTxnID`),
 KEY `ProductType` (`ProductType`),
 KEY `UserRMN` (`UserRMN`),
 KEY `YearMonthRMN` (`YearMonthRMN`) USING BTREE,
 KEY `CustomerNo` (`CustomerNo`) USING BTREE
) ENGINE=InnoDB DEFAULT CHARSET=latin1

该表有170万条记录。

我想删除主键,而是添加一个自动编号主键。到目前为止,指数下降了2小时。

为什么删除索引需要这么长时间,是否有任何排序?

我如何估计放弃指数的时间?

当我添加自动编号时,我是否需要估计对表格进行排序的时间,或者对于新的自动编号索引是否需要这样做?

3 个答案:

答案 0 :(得分:3)

你不只是丢弃索引,而是丢弃主键。

通常,InnoDB表存储为基于主键的聚簇索引,因此通过删除主键,它必须创建一个新表,该表使用辅助唯一键或其自身生成的密钥用于其聚簇索引。

我已经完成了大量的MySQL咨询,以及“需要花多少时间?”的问题。是一个常见的问题。

在服务器上构建新的聚簇索引需要花费很长时间。这很难预测。这取决于几个因素,例如服务器的CPU速度,存储速度以及其他负载同时发生的频率,以及CPU和I / O带宽的竞争。

换句话说,根据我的经验,我们无法预测需要多长时间。

您的表将使用TxnID重建为新的聚簇索引,这与主键完全相同。但显然MySQL服务器并不认为这种特殊情况可以使用可以使用in in alter alter的快捷方式。

您的表还有八个其他二级索引,其中五个是varchars。它必须在表重组期间构建这些索引。除了聚集索引之外,构建这些索引还有很多I / O.那很可能是花了那么多时间。

添加新的自动增量主键时,您将完成类似的过程。如果您删除了旧的主键并在一个ALTER TABLE语句中创建了新的自动增量主键,则可以节省一些时间。

答案 1 :(得分:2)

(我同意Bill的回答;这里有更多评论。)

我会终止这个过程并重新考虑AUTO_INCREMENT中是否有任何的好处。

我试图超越问题而不是“真实”的问题。在这种情况下,它似乎是一个尚未说出来的东西,需要AUTO_INCREMENT;请详细说明。

您当前的PRIMARY KEY是6个字节。如果INT,则新PK将为4个字节,如果为BIGINT,则为8个字节。因此,磁盘空间利用率只会微不足道地节省或损失。

TxnID的任何查找都会因为通过AI而放慢速度。由于TxnIDUNIQUE且非空,它似乎是最佳的“自然”PK。

PK 唯一键,因此UNIQUE(TxnID)完全是多余的; DROPping它可以节省空间而不会丢失任何东西。这是我的主要建议(只看模式)。

当我看到基本上每列都为NULL的表格时,我怀疑设计师没有对列的无效性做出有意识的决定。

DECIMAL(13,2)将是很多美元或欧元,但作为PK,这是非常不寻常的。怎么了?

latin1?没有全球化的计划?

很多单列索引? WHERE a=1 AND b=2需要复合INDEX(a,b)

回到估计时间......

如果ALTER重建了8-9个索引,那么 应该通过磁盘排序来做它能做的事情。这涉及使用基于磁盘的高效排序将内容写入磁盘,该排序涉及一些RAM,然后读取排序结果以重新创建索引。排序是O(log N),从而使其成为非线性的。这使得很难预测所花费的时间。一些较新版本的MariaDB 尝试估计剩余时间,但我不相信。

辅助索引包括作为索引的列以及PK的任何其他列。 表中的每个索引将占用大约5-10GB的磁盘空间。这个可以帮助您转换为IOP或其他任何东西。但请注意(假设您没有太多RAM),在重建索引的排序过程中,5-10GB将被重读几次(几次?)。

执行多个ALTERs时,请在单个ALTER语句中执行这些操作。这样,所有工作(特别是重建二级索引)只需要完成一次。

您还没有说出您使用的是哪个版本。旧版本提供一个选择:“复制”:创建新表;复制数据;重建索引;改名。新版本可以处理辅助索引“INPLACE”。注意:对PRIMARY KEY的更改需要复制方法。

答案 2 :(得分:0)

对任何有兴趣的人:

  • 这是在Amazon Aurora上运行的,存储了30GB的数据。我找不到有关如何为此配置IOPS的任何信息,但我预计在最坏的情况下将始终提供90IOPS。写10GB进出需要大约4个小时。

  • 我在运行alter table之前将实例升级到db.r3.8xlarge。

  • 然后跑

    alter table `Usage` drop primary key, add id bigint auto_increment primary key
    
它需要1小时21分钟,这比预期要好得多。