考虑下表
+-------------+---------+------+-----+---------+----------------+
| 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);
}
然而,具有更新数据的行将是最小的,并且对每一行进行选择将意味着由于行的数量,该作业将非常慢。
所以我的问题是可以使用哪些模式尽可能有效地解决这个问题?
欢迎任何想法
答案 0 :(得分:2)
我建议您使用新下载的数据完全替换之前的90天数据。
推理很简单:
答案 1 :(得分:1)
当您说“与以前相同”时,似乎密钥为date
和sku
(合并),销售和展示次数是可以更新的字段。如果这是正确的,那么在MySQL中执行此操作的最有效方法是使用INSERT ... ON DUPLICATE KEY UPDATE ...
查询:
在date
和sku
列上创建唯一键。
在您的php脚本中预先解析文件中的所有数据(或者如果您愿意,可以批量执行)。
运行与此类似的查询(替换步骤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)
但我不认为你是这种情况