MySQL - 创建索引需要多长时间?

时间:2010-03-20 13:35:56

标签: mysql indexing

有谁能告诉我如何在MySQL中添加密钥?我在数据库中有500,000,000行,trans,列i(INT UNSIGNED),j(INT UNSIGNED),nu(DOUBLE),A(DOUBLE)。 我尝试索引一列,例如

ALTER TABLE trans ADD KEY idx_A (A);
我等了。对于一张14,000,000行的表格,我花了大约2分钟在我的MacBook Pro上执行,但对于整个5亿,这需要花费15个小时来计算。我做错了什么,或者我只是天真地对数据库的索引如何与行数进行扩展?

4 个答案:

答案 0 :(得分:34)

有几个因素需要考虑:

  • 排序是N.log(N)操作。
  • 14M行的排序可能很适合主内存; 500M行的排序可能没有,因此排序溢出到磁盘,这会大大减慢速度。

由于因子大小约为30,因此大数据集的名义排序时间大约为50倍 - 在两小时之内。但是,每个数据值需要8个字节,另外还需要8个字节的开销(这是猜测 - 如果您对索引中存储的内容有更多了解,请调整到mySQL)。所以,14M×16≈220MB主存。但500M×16≈8GB主存。除非您的计算机有足够的内存(并且MySQL已配置为使用它),否则大部分内容将溢出到磁盘,并且其余时间占很多。

答案 1 :(得分:5)

首先,您的表定义可能会在这里产生很大的不同。如果您的列中不需要NULL值,请定义它们NOT NULL。这将节省索引中的空间,并且可能是创建它时的时间。

CREATE TABLE x ( 
  i INTEGER UNSIGNED NOT NULL, 
  j INTEGER UNSIGNED NOT NULL, 
  nu DOUBLE NOT NULL, 
  A DOUBLE NOT NULL 
);

至于创建索引所需的时间,这需要进行表扫描,并显示为REPAIR BY SORTING。在您的情况下(即海量数据集)应该更快地创建具有所需索引的新表并将数据插入其中,因为这将避免REPAIR BY SORTING操作,因为索引是在插入上顺序构建的。在this article中解释了类似的概念。

CREATE DATABASE trans_clone;
CREATE TABLE trans_clone.trans LIKE originalDB.trans;
ALTER TABLE trans_clone.trans ADD KEY idx_A (A);

然后将插入脚本编入块(根据文章),或使用MYSQLDUMP转储数据:

mysqldump originalDB trans  --extended-insert --skip-add-drop-table --no-create-db --no-create-info > originalDB .trans.sql
mysql trans_clone < originalDB .trans.sql

这将插入数据,但不需要索引重建(索引是在插入每一行时构建的),并且应该更快地完成。

答案 2 :(得分:2)

根据我的经验:如果硬件可以应对它,使用MySQL索引大型表通常可以非常线性地扩展。到目前为止,我已经尝试过大约100,000,000行的表,但不是在笔记本上 - 主要是在强大的服务器上。

我想这主要取决于硬件因素,你正在使用的表引擎的类型(MyIsam,INNO或其他),如果在其他方面使用表,还有一点。当我这样做的时候,通常磁盘使用率会高得惊人,与CPU使用率不同。不确定MacBook的硬盘,但我想它们并不是最快的。

如果您正在使用MyISAM表,可能需要仔细查看表目录中的索引文件,看看它在一段时间内是如何变化的。

答案 3 :(得分:0)

所以理论上如果排序步骤是N.log(N)操作,对大表进行分区可以节省操作时间

在100个相同文件中分区的500 000 000行的表增益约为30%:因为 500 000 000 * log(500 000 000)= 4 349 485 002 和 100 *(500 000 000/100 * LOG(500 000 000/100))= 3 349 485 002