Php 将27000*2密钥从纯文本文件插入DB的优化代码

Php 将27000*2密钥从纯文本文件插入DB的优化代码,php,optimization,mysqli,Php,Optimization,Mysqli,我需要从纯文本文件中插入数据,将每行分解为两部分,然后插入数据库。我是这样做的,但是这个程序能优化速度吗 该文件大约有27000行条目 数据库结构[唯一键(外部,信息)] 分机[varchar] 信息[varchar] 代码: $string=file\u get\u contents('list.txt'); $file\u list=explode(“\n”,$string); $entry=0; $db=newmysqli('localhost','root','file_type')

我需要从纯文本文件中插入数据,将每行分解为两部分,然后插入数据库。我是这样做的,但是这个程序能优化速度吗

该文件大约有27000行条目
数据库结构[唯一键(外部,信息)]

  • 分机[varchar]
  • 信息[varchar]
代码:

$string=file\u get\u contents('list.txt');
$file\u list=explode(“\n”,$string);
$entry=0;
$db=newmysqli('localhost','root','file_type');
$sql=$db->prepare('INSERT-INTO-info(ext,info)值(?,));
$j=计数($file\u list);
对于($i=0;$ibind_参数($ss',$data[0],$data[1]);
$sql->execute();
$entry++;
}   
$sql->close();
echo$entry.“已插入条目!
”;
如果您确定文件包含唯一的ext/info对,您可以尝试禁用导入密钥:

ALTER TABLE `info` DISABLE KEYS;
进口后:

ALTER TABLE `info` ENABLE KEYS;
这样,将为所有记录重建一次唯一索引,而不是每次插入某个内容


为了进一步提高速度,您应该将此文件的格式更改为CSV兼容,并使用mysql避免解析php中的每一行。

如果您确定该文件包含唯一的ext/info对,您可以尝试禁用导入密钥:

ALTER TABLE `info` DISABLE KEYS;
进口后:

ALTER TABLE `info` ENABLE KEYS;
这样,将为所有记录重建一次唯一索引,而不是每次插入某个内容


为了进一步提高速度,您应该将此文件的格式更改为CSV兼容,并使用mysql来避免解析php中的每一行。

当要插入多个项目时,您通常将所有数据放在CSV文件中,创建一个包含与CSV匹配的列的临时表,然后执行a,然后将该数据移动到目标表中。B但正如我所看到的,您不需要太多额外的处理,所以您甚至可以将输入文件作为CSV处理,而不需要任何额外的麻烦

$db->exec('CREATE TEMPORARY TABLE _tmp_info (ext VARCHAR(255), info VARCHAR(255))');
$db->exec("LOAD DATA LOCAL INFILE '{$filename}' INTO TABLE _tmp_info
           FIELDS TERMINATED BY ' '
           LINES TERMINATED BY '\n'"); // $filename = 'list.txt' in your case
$db->exec('INSERT INTO info (ext, info) SELECT t.ext, t.info FROM _tmp_info t');

您可以运行
COUNT(*)
在临时表上显示有多少条记录。

当有多个项目要插入时,通常将所有数据放入CSV文件中,创建一个列与CSV匹配的临时表,然后执行一个,然后将该数据移动到目标表中。但正如我所见,您不需要太多额外的处理,因此可以即使将您的输入文件视为CSV,也不会有任何额外的麻烦

$db->exec('CREATE TEMPORARY TABLE _tmp_info (ext VARCHAR(255), info VARCHAR(255))');
$db->exec("LOAD DATA LOCAL INFILE '{$filename}' INTO TABLE _tmp_info
           FIELDS TERMINATED BY ' '
           LINES TERMINATED BY '\n'"); // $filename = 'list.txt' in your case
$db->exec('INSERT INTO info (ext, info) SELECT t.ext, t.info FROM _tmp_info t');

在此之后,您可以在临时表上运行
COUNT(*)
,以显示有多少条记录。

如果您有一个要读入的大文件,我不会使用
file\u get\u contents
。使用它会迫使解释器一次性将全部内容存储在内存中,这有点浪费

以下是摘自的片段:


这是不同的,因为在单个实例中,您在内存中保存的所有文件都是一行(而不是文件的全部内容),在您的情况下,这可能会降低脚本的运行时内存占用。在您的情况下,您可以使用相同的循环来执行插入操作。

如果您有一个要读入的大文件,我不会使用
file\u get\u contents
。使用它可以强制解释器将所有内容都存储在内存中一次也不要,这有点浪费

以下是摘自的片段:


这是不同的,因为在单个实例中,您在内存中保存的所有文件都是一行(而不是文件的全部内容),在您的情况下,这可能会降低脚本的运行时内存占用。在您的情况下,您可以使用相同的循环来执行插入操作。

如果您可以使用类似。这是一个ETL程序,简单而免费(它有付费版本)。

如果您可以使用类似。这是一个ETL程序,简单而免费(它有付费版本)。

这是神奇的解决方案[3秒vs 240秒]

更改表
info
禁用键;

$db->autocommit(FALSE);
//insert
$db->commit();

更改表
info
启用键;

这是神奇的解决方案[3秒vs 240秒]

$db->autocommit(FALSE);
//insert
$db->commit();
更改表
info
禁用键;

$db->autocommit(FALSE);
//insert
$db->commit();

ALTER TABLE
info
启用密钥;

根据具体的表类型,如果您在第一次插入前调用LOCK TABLE进行写入,然后在最后一次插入后再次解锁,您可能会获得更好的性能。但我认为,如果它是INNODB,那么锁定/解锁将自动完成!具体取决于fic表类型,如果您在第一次插入之前调用LOCK table进行写入,然后在最后一次插入之后再次解锁,您可能会获得更好的性能。但是我认为如果它是INNODB,那么锁定/解锁会自动完成!但我认为它会使我的硬盘旋转多一点,不确定:/但是我认为它会使我的硬盘旋转多一点,而不是sure:/看一看dev null Resident在下面写的关于键的内容,在如此大的插入中加快了速度:看一看dev null Resident在下面写的关于键的内容,在如此大的插入中加快了速度:这不是dev null Resident写的吗?不管怎样,如果这对你来说是“魔法”——只要你同时拥有这两个键就行了(web和db)在同一台服务器上。您必须同时使用禁用键和使用
加载数据
,而不是单独插入;这在任何服务器配置上都节省了大量时间。加载数据实际上失败了:(这不是dev null Resident写的吗?无论如何,如果这对您来说是“魔法”——只要您同时拥有这两个键(web和db)就可以了在同一台服务器上。您必须同时使用禁用键和使用
加载数据
,而不是单独插入;这在任何服务器配置上都可以节省大量时间。加载数据实际上失败了:(
$db->autocommit(FALSE);
//insert
$db->commit();