PHP最有效的检查行是否存在的方法

3
请看下面的表格:
+-------------+---------+------+-----+---------+----------------+
| 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天内的所有数据(可能超过50,000条记录)。
然而,由于某些事情的影响,例如:
第1天的数据可能会因为原始插入之后的变化而发生改变。
Date: 2015-01-01
SKU:  ABCD
Impressions:  100
Sales: 0

第二天。

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

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

对于从数据下载中得到的任何记录,可能会出现以下情况:

a) 已经被看到并且与以前相同 - 忽略 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个回答

2
我建议您使用新下载的数据完全替换先前90天的数据。
原因很简单:
  • 这样做的处理时间是微不足道的。在数据库术语中,50000行是微不足道的。即使有一百万行,我也可能会这样做。
  • 尝试仅替换更改的行是复杂的,并可能引入错误。

1
当你说“同以前一样”时,似乎键是datesku(组合),而销售额和印象是可以更新的字段。如果是这样的话,在MySQL中最有效的方法是使用INSERT ... ON DUPLICATE KEY UPDATE ...查询:
  1. Create a unique key on date and sku columns.

  2. In your php script pre-parse all data from file (or do it in batches if you'd like).

  3. Run a query similar to this (substitute actual data from parsed values in step 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)
    

以下是一些注意事项:

  • 查看 文档 以了解此语法
  • 如果次日数据更新包含前一天的记录是补充的,你可以执行 sales = sales + VALUES(sales),但我认为这不是你的情况

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接