问题描述
我在Windows 10(i5,ssd)计算机上使用WAMP,并注意到网站运行缓慢。比我的旧Windows 7(i3,hd)PC慢得多。
当我使用计算循环一个简单的脚本时: Win10:0.4秒 Win7:9.5秒
但是当我循环添加数据库查询时,情况恰恰相反: Win10:147秒 Win7:15秒
我使用的脚本在表“ test”中插入一个简单的哈希值:
CREATE TABLE `test` (
`id` int(11) NOT NULL AUTO_INCREMENT,`testvalue` varchar(255) COLLATE utf8mb4_unicode_ci NOT NULL,PRIMARY KEY (`id`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci
PHP测试脚本:
<?PHP
set_time_limit(0);
$time_start = microtime(true);
$insertTotal = 100000;
$servername = "127.0.0.1";
$username = "root";
$password = "";
$dbname = "speedtest";
$db = new MysqLi($servername,$username,$password,$dbname);
$db->query("TruncATE test");
for($i=0;$i<$insertTotal;$i++)
{
$db->query("INSERT INTO test VALUES(null,'".md5(time().rand(0,999999999))."')");
}
$time_end = microtime(true);
$execution_time = ($time_end - $time_start);
echo 'Total exec time: '.$execution_time.' sec.';
有很多与此相关的主题,所以我将总结我已经做过的所有事情:
- 将服务器名从localhost更改为127.0.0.1
- Apache:禁用CGI
- PHP:禁用Xdebug
- 禁用的防火墙
- 禁用的病毒扫描程序
- 不同硬盘上的数据目录
在my.ini中增加了很多缓冲:
key_buffer_size = 512M
max_allowed_packet = 64M
table_open_cache = 256
sort_buffer_size = 4M
net_buffer_length = 8K
read_buffer_size = 2M
read_rnd_buffer_size = 8M
myisam_sort_buffer_size = 128M
那么我在这里还想念什么?
一些其他信息:执行脚本时,SSD的负载为0%,cpu的负载约为30%。
更新:
- 重新安装了Wamp 3.2.3。 使用MysqL 5.7.31、8.0.21和MariaDB 10.4.10、10.4.13、10.5.5对其进行了测试。 到处都有几秒钟的差异,但仍然很慢。
- 我还更改了脚本以使用$ db-> multi_query($ sql)看看是否可行。在旧计算机上插入10.000行的结果是0.13秒,在新计算机上插入8.5秒。
- 请确保这不是SSD或我这次仅使用sqlite3编写了相同的测试脚本,并在7秒钟内插入了1.000.000行,所以它仅是MysqL和MariaDB。
- 在装有Wamp 2.5的新PC上安装了VMWare Windows 7。有趣的是,执行时间差不多,也很慢。
解决方法
- 从MyISAM移至InnoDB
- 在单个
INSERT
中批处理100行;它将以大约10倍的速度运行。 - 取决于备用RAM的数量和所使用的引擎,应该进行一些调整。
- 切勿使用多查询。
-
autocommit
与MyISAM无关。
单个事务中的 - 100K
INSERTs
还有其他问题。要么进行上述批处理,要么仅在事务中放入100个插入内容。 (无论哪种情况,都超过100就是“收益递减”。)
#update# 实际上,我的PC确实存在问题。我终于将其修复(https://superuser.com/questions/1584203/windows-10-very-slow-how-to-find-the-cause),现在测试脚本的运行速度提高了34倍。因此,使用多值插入的更好的脚本也会更快。现在,整个WAMP的运行速度快了很多倍。很高兴这解决了。 #update#
在这个问题上花费了很多时间之后,我继续研究自己的实际导入脚本,突然意识到我一直在错误的树上吠叫。我一直在尝试解决实际上不是问题的问题。
当然,这是不正确的,当旧PC可以做到50.000左右时,我的写入速度为每秒500个独立查询,但是我绝对不应该使用独立查询。我非常关注这个问题,以至于我没有意识到性能问题并没有影响MySQL和MariaDB可以做的所有其他事情。
里克·詹姆斯(Rick James)的回答实际上是正确的想法。
抱歉,浪费您的时间。感谢你们对我的帮助!我以前一直在研究问题并解决问题,但是从来没有解决过这么久的问题,那根本不是一个真正的问题!
举个例子,我修改了测试脚本。这可以在大约14分钟内插入2亿行:
<?php
set_time_limit(0);
$time_start = microtime(true);
$insertTotal = 200000000;
$servername = "127.0.0.1";
$username = "root";
$password = "";
$dbname = "speedtest";
$db = new mysqli($servername,$username,$password,$dbname);
$db->query("TRUNCATE test");
$counter = 0;
$sql = array();
for($i=0;$i<$insertTotal;$i++)
{
$sql[] = "(null,'".md5(time().rand(0,999999999))."')";
if($counter == 5000)
{
$sql = implode(",",$sql);
$db->query("INSERT INTO test VALUES ".$sql.";");
$counter = 0;
$sql = array();
}
$counter++;
}
$sql = implode(",$sql);
$db->query("INSERT INTO test VALUES ".$sql.";");
$time_end = microtime(true);
$execution_time = ($time_end - $time_start);
echo 'Total exec time: '.$execution_time.' sec.';