2016-04-12 80 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)但我不认为你的情况如此
相关问题