考虑下表
+-------------+---------+------+-----+---------+----------------+
| 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
因此对于数据下载中的任何给定记录,它可能是
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);
}
然而,将具有更新数据的行将是最少的,并且对每一行进行选择将意味着由于行数过多,这项工作将非常慢。
所以我的问题是可以使用哪些模式来尽可能高效地解决这个问题?
欢迎任何想法
最佳答案
我建议您用新下载的数据完全替换之前 90 天的数据。
推理很简单:
- 执行此操作的处理时间微不足道。50,000 行在数据库中是微不足道的。即使它是一百万行,我也可能会这样做。
- 尝试仅替换更改的行很复杂,并且可能会引入错误。
关于PHP 检查行是否存在的最有效方法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/36574030/