2010-10-17 166 views
9

我有一個應用程序需要更新大量數據的大量條目。基本上它有7,000個插入和/或更新,但它需要一個懶惰的時間(比如近9分鐘......平均每個查詢約0.08秒)。本質上,我正在尋找一般的加速器來製作多個這樣的請求(我不希望對我的模糊示例有特定的答案......這只是希望能夠幫助解釋)。加速大量的mysql更新和插入

下面是剖析請求一些樣品:

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 (?, ?, ?, ?, ?, ?, ?, ?, ?, ?) 

重複生厭(當然,約7000倍)。這是一個收集24小時內間隔生成的數據的更新,然後每天對數據庫進行一次大規模更新。鑑於我已經顯示的有限的位,你是否有任何建議加快這個過程?

例如......它是否有意義,而不是爲每個時間戳做一個選擇,一次選擇一個範圍,然後在腳本中迭代它們?

依稀像:

foreach ($foo as $bar) 
{ 
    if ($bar['timestamp'] == $baz) // where $baz is the needed timestamp 
    { 
    // do the insert here 
    } 
} 

編輯:要有點添加到此,一兩件事,在我的情況好轉反應是

SELECT `habitable_planets`.* FROM `habitable_planets` WHERE (planet_id = '2010_Gl_581_c') 

導致對$foo,然後做分配更改一堆檢查現有記錄的代碼,並根據結果執行插入操作或更新,以使用SQL查詢語句INSERT... ON DUPLICATE KEY UPDATE。這導致我在特定情況下的速度增加了大約30%,因爲它至少減少了一次到數據庫的行程,並且超過了成千上萬的請求。

回答

16

一些有用的鏈接:

從MySQL文檔:

Speed of INSERT Statements說:

  • 如果您在同一時間將來自同一客戶多行,請使用具有多個值 列表 INSERT語句在 一次插入幾行。使用分開的單行INSERT 語句,這比使用單獨的INSERT 語句的 (在某些情況下,速度快很多)要快得多,爲 。如果要將數據添加到 非空表中,可以將 bulk_insert_buffer_size變量調整爲 使數據插入更快。

  • 如果多個客戶端插入很多行,可以通過使用INSERT DELAYED語句獲得更高的速度 。

  • 對於MyISAM表,你可以使用並行插入到該SELECT語句 運行後, 同時添加行,如果有數據文件的中間沒有刪除的行 。

  • 從文本文件加載表格時,請使用LOAD DATA INFILE。這是 通常比使用 INSERT語句快20倍。

  • 有了一些額外的工作,當 表有很多索引時,可以使MyISAM表的LOAD DATA INFILE甚至更快地運行 。

+1

+1。良好的綜合答案。 – sberry 2010-10-18 15:10:52

2

如果你沒有準備好,用準備好的語句(通過任何mysqliPDO,或支持他們一些其他DB庫)。重用相同的準備好的語句並簡單地更改參數值將有助於加快速度,因爲MySQL服務器只需解析查詢一次。

INSERT s可以通過提供多組VALUES來進行批處理 - 插入多行的單個查詢比每個插入一行的等效數量的單個查詢快得多。

2

你的建議是正確的。嘗試減少發送到服務器的查詢量,因爲這樣可以節省您的通信開銷。

當然,如果inital select範圍的查詢返回的數據太多,那麼您可能在PHP上存在瓶頸。

1

我可能會使用存儲的過程,如果可能的話,只是從我的應用程序代碼調用。此外,我會考慮正確的索引,並可能爲planet_id添加一個基於整數的替換代理鍵,因爲13字節字符鍵不會像連接和查找中的表達式那樣是4字節整數。

(我剛讀,有估計是宇宙千萬萬億適合居住的行星,所以也許你最好使用BIGINT的無符號: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 ; 
+0

*「10萬億」* - 10十億分之:) – BadHorsie 2016-02-19 21:08:00