2010-03-20 302 views
32

任何人都可以告诉我如何在MySQL中添加一个关键的缩放比例吗?我在数据库中有500,000,000行trans,列i(INT UNSIGNED),j(INT UNSIGNED),nu(DOUBLE),A(DOUBLE)。 我尝试索引一列,例如MySQL - 创建索引需要多长时间?

ALTER TABLE trans ADD KEY idx_A (A); 

我等。对于一张14,000,000行的表格,在我的MacBook Pro上执行大约需要2分钟,但是在整个五十亿的时间内,它需要花费15个小时并计数。我做错了什么,还是我只是天真的关于如何索引数据库与行数的比例?

+0

你可能想看看分裂(数据库分片)你的表 – 2010-03-20 14:02:03

回答

27

有几个因素要考虑:

  • 排序是一个N.log(N)的操作。
  • 14M行的排序可能适合主内存; 500M行的排序可能不会,所以排序会溢出到磁盘上,这会极大地降低速度。

由于该因子大小约为30,所以大数据集的名义排序时间将是50小时的数量级 - 在两小时以内。但是,每个数据值需要8个字节,而另外需要8个字节的开销(如果你更了解它在索引中存储的内容,那么这是对mySQL的猜测)。所以,14M×16≈220 MB的主内存。但是500M×16≈8GB的主内存。除非你的机器有足够的内存空间(并且配置了MySQL),否则大部分内容都会溢出到磁盘上,并且在剩下的时间里占了很大一部分。

+1

非常感谢,这对我有意义 - 我只有4 GB。看起来像上面提到的那样分割(分割?)数据很有意义。 – xnx 2010-03-21 22:20:44

+0

你把你的桌子拆了吗?它花了多少时间? – juanpastas 2014-03-10 00:14:58

2

从我的经验来看:如果硬件能够应付它,用MySQL索引大型表格通常会非常线性地缩放。到目前为止,我已经尝试了大约100,000,000行的表格,但不是在笔记本上 - 主要是在强大的服务器上。我猜它主要取决于硬件因素,你使用的表引擎的类型(MyIsam,INNO,或其他),以及如果表格之间在其他地方使用的话,有点有点不同。当我这样做时,与CPU使用率不同,通常磁盘使用率跳高。不确定MacBook的硬盘,但我想他们不是最快的。

如果您拥有MyISAM表格,也许可以仔细查看表格目录中的索引文件,并查看它随时间变化的情况。

+0

感谢您的快速回复,Björn。我遵循你的建议。我把它的文件 #SQL-a8_6.MYD(目前7455506432字节)和 #SQL-a8_6.MYI(目前2148865024字节) 是数据库和新版本正在建造我分别要求的指标? 然后,如果原始表格是 trans.MYD(12,645,156,375字节) 我约完成了60%? 现在看起来我会更好地将巨大的桌子分成20个或更小的桌子。 谢谢, 基督徒 – xnx 2010-03-20 14:47:14

+0

总的来说应该是这样。那么,这一切都取决于你想要处理的数据量。 500.000.000行很多,所以如果你想在之后做一些奇妙的报告,尽量减少数据。试图分裂它,或者在MySQLs分区功能(从版本5.1)中获取战利品。 – Bjoern 2010-03-20 19:14:40

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。在你的情况下(即海量数据集)应该更快地创建一个具有所需索引的新表并将数据插入到该表中,因为这样可以避免操作,因为索引是按顺序在插入上构建的。在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 

这将插入的数据,但不会需要一个索引重建(索引随着每行插入而建立)并且应该更快地完成。

+1

请注意,您可以使用[pt-online-schema-change](http://www.percona),而不是执行一个'mysqldump'和一个恢复过程,这个恢复过程至少需要连续的表读锁从Percona工具包 - 它会照顾创建和复制数据在多个过程中,删除连续锁定要求。 – 2014-08-21 23:37:56

0

所以theorically如果排序步骤是N.log(N)操作,partitionning你的大表将节省时间操作

约30%的涨幅为100个等于文件partitionned 500个000 000行的表:因为 500 000 000 *日志(500 000 000)= 4 349 485 002 和 100 *(500 000 000/100 * LOG(500 000 000/100))= 3 349 485 002