我有一个需要在大量条目上更新大量数据的应用。基本上它会进行大约7,000次插入和/或更新,但需要花费很长时间(比如差不多9分钟......平均每次查询大约0.08秒)。基本上我正在寻找一般的加速来提出多个这样的请求(我不期待对我模糊的例子的具体答案......这只是希望,有助于解释)。
以下是分析请求的一些示例:
SELECT `habitable_planets`.* FROM `habitable_planets` WHERE (timestamp = '2010-10-15T07:30:00-07:00') AND (planet_id = '2010_Gl_581_c')
INSERT INTO `habitable_planets` (`planet_id`, `timestamp`, `weather_air_temp`, `weather_cell_temp`, `weather_irradiance`, `weather_wind_float`, `biolumin_to_date`, `biolumin_detected`, `craft_energy_usage`, `craft_energy_consumed_to_date`) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
SELECT `habitable_planets`.* FROM `habitable_planets` WHERE (timestamp = '2010-10-15T07:45:00-07:00') AND (planet_id = '2010_Gl_581_c')
INSERT INTO `habitable_planets` (`planet_id`, `timestamp`, `weather_air_temp`, `weather_cell_temp`, `weather_irradiance`, `weather_wind_float`, `biolumin_to_date`, `biolumin_detected`, `craft_energy_usage`, `craft_energy_consumed_to_date`) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
重复广告恶心(好吧,约7,000次)。这是一个更新,它收集24小时内间隔生成的数据,然后每天对数据库进行一次大量更新。鉴于我所展示的有限位,你有什么建议加快这个过程吗?
例如......是否有意义,而不是为每个时间戳做一个选择,一次选择一个范围,然后在脚本中迭代它们?
模糊地说:
SELECT `habitable_planets`.* FROM `habitable_planets` WHERE (planet_id = '2010_Gl_581_c')
将结果分配给$foo
,然后执行:
foreach ($foo as $bar)
{
if ($bar['timestamp'] == $baz) // where $baz is the needed timestamp
{
// do the insert here
}
}
编辑:为此添加一点,在我的情况下改善响应性的一件事是更改一堆检查现有记录的代码,并根据具体情况进行插入或更新使用INSERT... ON DUPLICATE KEY UPDATE
sql查询的结果。在我的特定情况下,这导致了大约30%的速度增益,因为它减少了至少一次数据库之外的数量,并且实际上增加了数千个请求。
答案 0 :(得分:16)
一些有用的链接:
来自MySQL文档:
如果要同时从同一客户端插入多行,请使用 具有多个VALUES的INSERT语句 列表在a处插入多行 时间。这要快得多 (在某些情况下要快很多倍) 使用单独的单行INSERT 声明。如果要添加数据 一张非空表,你可以调整 bulk_insert_buffer_size变量为 使数据插入更快。
如果多个客户端插入了大量行,则可以获得更高的速度 使用INSERT DELAYED语句。
对于MyISAM表,您可以使用并发插入来添加行 SELECT语句的同时 如果没有删除的行,则运行 在数据文件的中间。
从文本文件加载表时,请使用LOAD DATA INFILE。这是 通常比使用速度快20倍 INSERT语句。
通过一些额外的工作,可以使LOAD DATA INFILE运行均匀 更快的MyISAM表时 表有很多索引。
答案 1 :(得分:2)
如果您还没有,请使用预准备语句(通过mysqli
,PDO
或其他支持它们的数据库库。重复使用相同的预准备语句并简单地更改参数值将有助于加快速度,因为MySQL服务器只需要解析一次查询。
INSERT
可以通过提供多组VALUES
进行批处理 - 插入多行的单个查询比插入一行的等效数量的单个查询快得多。
答案 2 :(得分:2)
你的建议是正确的。尝试减少发送到服务器的查询量,因为这样可以节省多个通信开销。
当然,如果初始选择范围查询返回太多数据,那么您可能在PHP上遇到瓶颈。
答案 3 :(得分:1)
如果可能的话,我可能会使用存储过程,只需从我的应用程序代码中调用它。此外,我正在考虑正确的索引,并可能为planet_id添加一个基于整数的替换代理键,因为13字节字符键在连接和查找中不会像4字节整数一样。
(我刚刚读到宇宙中估计有1000万亿个可居住的行星,所以也许你最好使用bigint unsigned:P)
drop procedure if exists update_insert_habitable_planets;
delimiter #
create procedure update_insert_habitable_planets
(
in p_planet_id int unsigned,
in p_timestamp datetime,
)
proc_main:begin
start transaction;
-- bulk update / insert whatever
commit;
end proc_main #
delimiter ;