有谁能告诉我如何在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个小时来计算。我做错了什么,或者我只是天真地对数据库的索引如何与行数进行扩展?
答案 0 :(得分:34)
有几个因素需要考虑:
由于因子大小约为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