2016-04-12 116 views
3

下表考慮PHP檢查的最有效的方法,如果行存在

+-------------+---------+------+-----+---------+----------------+ 
| Field  | Type | Null | Key | Default | Extra   | 
+-------------+---------+------+-----+---------+----------------+ 
| id   | int(11) | NO | PRI | NULL | auto_increment | 
| date  | date | NO |  | NULL |    | 
| sku   | varchar(10) |  |   | NULL   |   
| impressions | int(11) | NO |  | NULL |    | 
| sales  | int(11) | NO |  | NULL |    | 
+-------------+---------+------+-----+---------+----------------+ 

表會從以前的日銷售記錄批量下載日常居住。

每天的下載不僅包含前幾天的銷售數據,而且還包括最近90天的所有數據(可能爲50k +記錄)。

但是,由於我們控制範圍之外的問題,原始插入數據可能會改變前幾天的數據,例如,

1.

Date: 2015-01-01 
SKU: ABCD 
Impressions: 100 
Sales: 0 

日2天

Date: 2015-01-01 
SKU: ABCD 
Impressions: 100 
Sales: 3 

Date: 2015-01-02 
SKU: ABCD 
Impressions: 105 
Sales: 0 

因此,對於任何給定的記錄從數據下載也可能是

一)已經看到了和以前一樣 - 忽略 b)新增 - 添加到數據庫 c)已經看到但新數據 - 更新

可以說,這可以通過檢查每個行作爲這樣

while (!$file->eof()) { 
     $row = $file->fgets(); 
     $data = explode("\t", $row); 
     $sku = $data[0]; 
     $date = $data[1]; 
     $impressions = $data[2]; 
     $sales = $data[3]; 
     $order = $em->getRepository('Orders')->findOneBy(['sku' => $sku, 'date' => $date]); 
     if($order && $order->getImpressions() != $impressions && $order->getSales() != $sales) { 
      $order->setImpressions($impressions); 
      $order->setSales($sales);    
     } else { 
     ... create new model 
     } 
     $em->persist($order); 
} 

而輕易解決。然而這將有更新的數據將是最小的,做一個選擇爲每行每列將意味着這項工作會因慢得令人難以置信到純粹的行數。

所以我的問題是什麼模式可以用來儘可能有效地解決這個問題?

任何想法表示歡迎

回答

2

我建議你完全新下載的數據取代以前的90天的數據。

理由很簡單:

  • 的處理時間做這將是微不足道的。 50,000行在數據庫術語中很小。即使它是一百萬行,我也可能會這樣做。
  • 試圖只替換已更改的行很複雜,可能會引入錯誤。
1

當你說:「和以前一樣」好像鍵是datesku(組合),銷售和印象是可以被更新的領域。如果這是正確的,那麼最有效的方式在MySQL做,這是使用INSERT ... ON DUPLICATE KEY UPDATE ...查詢:

  1. datesku列上創建一個唯一的密鑰。

  2. 在你的PHP腳本中預先解析所有來自文件的數據(或者如果你願意,可以批量執行)。

  3. 運行(在步驟1中代替實際數據從解析值)類似這樣的查詢:

    INSERT INTO 
        mytable (`date`, sku, impressions, sales) 
    VALUES 
        ('2015-01-01', 'ABCD', 100, 3), 
        ('2015-01-02','ABCD', 100, 3), 
        ... 
    ON DUPLICATE KEY UPDATE 
        impressions = VALUES(impressions), 
        sales = VALUES(sales) 
    

有兩點要注意:

  • 檢查出documentation此語法
  • 如果包含上一個日期記錄的第二天的數據更新是補充性的,那麼您可以執行sales = sales + VALUES(sales)但我不認爲你的情況如此
相關問題