加速大量的mysql更新和插入

时间:2010-10-17 06:42:32

标签: php mysql

我有一个需要在大量条目上更新大量数据的应用。基本上它会进行大约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%的速度增益,因为它减少了至少一次数据库之外的数量,并且实际上增加了数千个请求。

4 个答案:

答案 0 :(得分:16)

一些有用的链接:

来自MySQL文档:

Speed of INSERT Statements说:

  
      
  • 如果要同时从同一客户端插入多行,请使用   具有多个VALUES的INSERT语句   列表在a处插入多行   时间。这要快得多   (在某些情况下要快很多倍)   使用单独的单行INSERT   声明。如果要添加数据   一张非空表,你可以调整   bulk_insert_buffer_size变量为   使数据插入更快。

  •   
  • 如果多个客户端插入了大量行,则可以获得更高的速度   使用INSERT DELAYED语句。

  •   
  • 对于MyISAM表,您可以使用并发插入来添加行   SELECT语句的同时   如果没有删除的行,则运行   在数据文件的中间。

  •   
  • 从文本文件加载表时,请使用LOAD DATA INFILE。这是   通常比使用速度快20倍   INSERT语句。

  •   
  • 通过一些额外的工作,可以使LOAD DATA INFILE运行均匀   更快的MyISAM表时   表有很多索引。

  •   

答案 1 :(得分:2)

如果您还没有,请使用预准备语句(通过mysqliPDO或其他支持它们的数据库库。重复使用相同的预准备语句并简单地更改参数值将有助于加快速度,因为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 ;