【问题标题】:Prestashop background bulk product importPrestashop后台批量产品导入
【发布时间】:2018-10-16 15:21:02
【问题描述】:

我正在尝试通过解析 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 的 DB 和服务器几乎相同。

Linux #1 SMP Debian 4.9.110-3+deb9u6 (2018-10-08) x86_64

版本软件删除服务器:Apache/2.4.10 (Debian)

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);
        }
    }
}

2018 年 10 月 22 日编辑:

升级到 PHP7.2 并使用 MariaDB 10.3.10 并没有给我带来任何变化:时间仍然相同。 带来的好处是在 /etc/fstab 中使用选项 barrers=0 安装数据库存储信息的 FS (EXT4):性能从 153 秒提高到 35 秒500 个元素,总共大约 18 分钟(原为 77 个)。

仍然存在的问题是为什么系统在导入时变得无响应。

【问题讨论】:

  • 您是否尝试过将 SQL 引擎从 MyISAM(我想)切换到 InnoDB 以避免任何表锁定问题?此外,切换到 PHP 7+ 和 MariaDB 可能会大大提高您的性能。
  • DB 和所有表(CRON 的 2 个表除外)已经是 InnoDB,但感谢有关 PHP 7+ 和 MariaDB 的提示:我将使用 PHP7.2 和MariaDB 10.3.10 并试一试

标签: php mysql apache prestashop-1.7


【解决方案1】:

您应该在更新之前检查您的产品是否需要更新。

这是我在 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。

【讨论】:

  • 感谢关于校验和的建议,这在第一次导入后肯定会有用:它是我算法中缺失的部分。我将使用 PHP7.2 和 MariaDB 10.3.10 设置所有内容,我将使用结果更新帖子
  • 你能告诉我这段代码要添加到哪个文件吗?
【解决方案2】:

真正解决我在导入产品时 Prestashop 卡住的问题是将我的代码从 ModuleAdminController 中移动到 WebserviceSpecificManagementInterface em>:这样导入在后台进行而不会使系统饱和。

【讨论】:

    猜你喜欢
    • 2016-04-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-09-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多