Prestashop后台批量产品导入
Prestashop background bulk product import
我正在尝试在解析 ASCII 文件 (3.5MB) 并仅使用 Prestashop 的 API.
的 Prestashop 电子商务中定期高效地导入 15K+ 产品
docker 下的所有 运行,官方图片来自 docker hub。
如果不存在具有相同参考字段的产品,我将不得不插入一个新产品(如果存在)以更新它。
我开发了一个模块,可以通过单击自定义管理选项卡来实现此功能,并且可以正常工作,但是整个系统会冻结,直到该过程完成或终止:(将近 77 分钟)。
我还尝试将(不是这样的)大文件分成 500、100、50 个块,但处理时间线性减少,它没有太大帮助:
- 500 个元素平均 153 秒
- 100 个元素平均 31 秒
- 50 个元素平均 15 秒
我当然可以每 90 秒配置一个 cron 来处理 50 个元素,并在每晚 7-8 小时内完成整个导入,但这似乎是一个非常糟糕的妥协:每 90 秒离线 15 秒。
我不能使用 pthreads 因为这将是一个生产网络服务器。
我尝试调整 Apache 增加 memory_limit、max_input_vars、max_execution_time 但没有任何差异:数据库使用 450MB 到 550MB 的 RAM 和服务器几乎相同。
Linux #1 SMP Debian 4.9.110-3+deb9u6 (2018-10-08) x86_64
Versione software del server: Apache/2.4.10 (Debian)
Versione di PHP: 5.6.35
memory_limit=2048M
max_input_vars=1000000
max_execution_time=600000
MySQL: 5.6.40
我是不是以错误的方式面对问题,或者 Prestashop 的 API 性能不佳并且是为批量(和高性能)产品导入而设计的?
public function batchImportAllProductsFromFile($productsToBeInserted){
foreach ($productsToBeInserted as $key => $customProduct ) {
$productIDs = $this->getProductIDsByReference($customProduct->MS_CODMAG);
if (sizeof($productIDs) == 0) {
$product = new Product();
} else if (sizeof($productIDs) == 1) {
$product = new Product($productIDs[0]);
} else {
continue;
}
$product->reference = $customProduct->MS_CODMAG;
$product->name = trim($customProduct->MS_DESCRIZIONE);
$product->price = $customProduct->MS_PREZZO_1;
$product->out_of_stock = ($customProduct ->MS_ESAURITO === "S" ? true : false);
$category = null;
$msGruppoConverted = $this->buildSubGroupCode($customProduct->MS_GRUPPO, $customProduct->MS_SGRUPPO);
if ($customProduct->MS_GRUPPO !== 0 && $msGruppoConverted !== 0) {
$product->id_category = [$customProduct->MS_GRUPPO, $msGruppoConverted];
} else if ($customProduct->MS_GRUPPO === 0 && $msGruppoConverted !== 0) {
$product->id_category = [$msGruppoConverted];
} else if ($customProduct ->MS_GRUPPO !== 0 && $msGruppoConverted === 0) {
$product->id_category = [$customProduct->MS_GRUPPO];
}
try {
if (sizeof($productIDs) == 0) {
if ($product->add()) {
$product->updateCategories($product->category);
$product->addFeatureProductImport($product->id, 1, $customProduct->MS_FAM);
//StockAvailable::setQuantity((int)$product->id, 0, $product->quantity, Context::getContext()->shop->id);
}
} else if (sizeof($productIDs) == 1) {
if ($product->update()) {
$product->updateCategories($product->category);
$alreadySavedFeatures = $product->getFeaturesStatic($productIDs[0]);
if (sizeof($alreadySavedFeatures) != 1 || $alreadySavedFeatures[0] != $customProduct->MS_FAM) {
$product->deleteProductFeatures();
$product->addFeatureProductImport($product->id, 1, $customProduct->MS_FAM);
}
}
}
} catch (Exception $e) {
var_dump("Errore: ", $e, $product);
}
}
}
编辑 22/10/2018:
升级到 PHP7.2 并使用 MariaDB 10.3.10 没有给我带来任何变化:时间仍然相同。
带来好处的是在 /etc/fstab 中使用选项 barrers=0 安装 FS (EXT4),其中数据库存储信息: performances 500 个元素的时间从 153 秒提高到 35 秒,总共大约需要 18 分钟(原为 77 分钟)。
仍然存在的问题是系统在导入时变得无响应的原因。
您应该在更新之前检查您的产品是否需要更新。
这是我在 Prestashop 上导入实体时所做的(高度简化):
<?php
class myProductImporter {
protected $products;
protected $products_checksum;
public function __construct($products) {
// Your products from the csv file
$this->products = $products;
// Here you get an associative array of products references and checksums
// ex: array('REF01158' => '489f9ze4f4ze9f49ze8', 'REF15616' => '48949844561233132')
$this->products_checksum = getProductsChecksum();
}
public function run() {
foreach ($this->products as $product) {
// If the product ref is present in my checksum list, then its an update
if (isset($this->products_checksum[$product['reference']])) {
// If the checksum is different, the product needs an update
if ($this->products_checksum[$product['reference']] != $this->getChecksum($product)) {
$this->updateProduct($product);
}
// Else it's a new product
} else {
$this->addProduct($product);
}
}
}
protected function updateProduct($product) {
$PSProduct = getProductByReferebce($product['reference']);
// Update your product and save its new checksum
}
protected function addProduct($product) {
$PSProduct = new Product();
// Create the product and save its checksum
}
protected function getChecksum($product) {
// Create a string containing all your product properties
$checksum = $product['reference'];
$checksum .= $product['name'];
$checksum .= $product['description'];
$checksum .= $product['id_category'];
return md5($checksum);
}
}
如果没有修改,您的导入将立即完成,因为没有正在处理的查询。
关于您的安装冻结,这似乎是一个 Docker 问题,并且未链接到 Prestashop。
如@bruno-leveque 所述,您应该考虑升级到 PHP7。
真正解决我的 Prestashop 在导入产品时被卡住的问题是将我的代码从 ModuleAdminController 中移动到 WebserviceSpecificManagementInterface:这样导入在后台进行,不会使系统饱和。
我正在尝试在解析 ASCII 文件 (3.5MB) 并仅使用 Prestashop 的 API.
的 Prestashop 电子商务中定期高效地导入 15K+ 产品docker 下的所有 运行,官方图片来自 docker hub。
如果不存在具有相同参考字段的产品,我将不得不插入一个新产品(如果存在)以更新它。 我开发了一个模块,可以通过单击自定义管理选项卡来实现此功能,并且可以正常工作,但是整个系统会冻结,直到该过程完成或终止:(将近 77 分钟)。 我还尝试将(不是这样的)大文件分成 500、100、50 个块,但处理时间线性减少,它没有太大帮助:
- 500 个元素平均 153 秒
- 100 个元素平均 31 秒
- 50 个元素平均 15 秒
我当然可以每 90 秒配置一个 cron 来处理 50 个元素,并在每晚 7-8 小时内完成整个导入,但这似乎是一个非常糟糕的妥协:每 90 秒离线 15 秒。
我不能使用 pthreads 因为这将是一个生产网络服务器。
我尝试调整 Apache 增加 memory_limit、max_input_vars、max_execution_time 但没有任何差异:数据库使用 450MB 到 550MB 的 RAM 和服务器几乎相同。
Linux #1 SMP Debian 4.9.110-3+deb9u6 (2018-10-08) x86_64
Versione software del server: Apache/2.4.10 (Debian)
Versione di PHP: 5.6.35
memory_limit=2048M
max_input_vars=1000000
max_execution_time=600000
MySQL: 5.6.40
我是不是以错误的方式面对问题,或者 Prestashop 的 API 性能不佳并且是为批量(和高性能)产品导入而设计的?
public function batchImportAllProductsFromFile($productsToBeInserted){
foreach ($productsToBeInserted as $key => $customProduct ) {
$productIDs = $this->getProductIDsByReference($customProduct->MS_CODMAG);
if (sizeof($productIDs) == 0) {
$product = new Product();
} else if (sizeof($productIDs) == 1) {
$product = new Product($productIDs[0]);
} else {
continue;
}
$product->reference = $customProduct->MS_CODMAG;
$product->name = trim($customProduct->MS_DESCRIZIONE);
$product->price = $customProduct->MS_PREZZO_1;
$product->out_of_stock = ($customProduct ->MS_ESAURITO === "S" ? true : false);
$category = null;
$msGruppoConverted = $this->buildSubGroupCode($customProduct->MS_GRUPPO, $customProduct->MS_SGRUPPO);
if ($customProduct->MS_GRUPPO !== 0 && $msGruppoConverted !== 0) {
$product->id_category = [$customProduct->MS_GRUPPO, $msGruppoConverted];
} else if ($customProduct->MS_GRUPPO === 0 && $msGruppoConverted !== 0) {
$product->id_category = [$msGruppoConverted];
} else if ($customProduct ->MS_GRUPPO !== 0 && $msGruppoConverted === 0) {
$product->id_category = [$customProduct->MS_GRUPPO];
}
try {
if (sizeof($productIDs) == 0) {
if ($product->add()) {
$product->updateCategories($product->category);
$product->addFeatureProductImport($product->id, 1, $customProduct->MS_FAM);
//StockAvailable::setQuantity((int)$product->id, 0, $product->quantity, Context::getContext()->shop->id);
}
} else if (sizeof($productIDs) == 1) {
if ($product->update()) {
$product->updateCategories($product->category);
$alreadySavedFeatures = $product->getFeaturesStatic($productIDs[0]);
if (sizeof($alreadySavedFeatures) != 1 || $alreadySavedFeatures[0] != $customProduct->MS_FAM) {
$product->deleteProductFeatures();
$product->addFeatureProductImport($product->id, 1, $customProduct->MS_FAM);
}
}
}
} catch (Exception $e) {
var_dump("Errore: ", $e, $product);
}
}
}
编辑 22/10/2018:
升级到 PHP7.2 并使用 MariaDB 10.3.10 没有给我带来任何变化:时间仍然相同。 带来好处的是在 /etc/fstab 中使用选项 barrers=0 安装 FS (EXT4),其中数据库存储信息: performances 500 个元素的时间从 153 秒提高到 35 秒,总共大约需要 18 分钟(原为 77 分钟)。
仍然存在的问题是系统在导入时变得无响应的原因。
您应该在更新之前检查您的产品是否需要更新。
这是我在 Prestashop 上导入实体时所做的(高度简化):
<?php
class myProductImporter {
protected $products;
protected $products_checksum;
public function __construct($products) {
// Your products from the csv file
$this->products = $products;
// Here you get an associative array of products references and checksums
// ex: array('REF01158' => '489f9ze4f4ze9f49ze8', 'REF15616' => '48949844561233132')
$this->products_checksum = getProductsChecksum();
}
public function run() {
foreach ($this->products as $product) {
// If the product ref is present in my checksum list, then its an update
if (isset($this->products_checksum[$product['reference']])) {
// If the checksum is different, the product needs an update
if ($this->products_checksum[$product['reference']] != $this->getChecksum($product)) {
$this->updateProduct($product);
}
// Else it's a new product
} else {
$this->addProduct($product);
}
}
}
protected function updateProduct($product) {
$PSProduct = getProductByReferebce($product['reference']);
// Update your product and save its new checksum
}
protected function addProduct($product) {
$PSProduct = new Product();
// Create the product and save its checksum
}
protected function getChecksum($product) {
// Create a string containing all your product properties
$checksum = $product['reference'];
$checksum .= $product['name'];
$checksum .= $product['description'];
$checksum .= $product['id_category'];
return md5($checksum);
}
}
如果没有修改,您的导入将立即完成,因为没有正在处理的查询。
关于您的安装冻结,这似乎是一个 Docker 问题,并且未链接到 Prestashop。
如@bruno-leveque 所述,您应该考虑升级到 PHP7。
真正解决我的 Prestashop 在导入产品时被卡住的问题是将我的代码从 ModuleAdminController 中移动到 WebserviceSpecificManagementInterface:这样导入在后台进行,不会使系统饱和。