我应该在哪里从foreach循环中编写db\u select(),这样可以减少性能问题?

jhdbpxl9  于 2021-06-25  发布在  Mysql
关注(0)|答案(1)|浏览(347)

我一直致力于drupal的性能改进,因为我想删除foreach循环中的db\u select()查询来提高性能。在这里我添加我的代码

foreach( $order->commerce_line_items['und'] as $line_item ) {
      $line_item = commerce_line_item_load($line_item['line_item_id']);
      $product = commerce_product_load($line_item->commerce_product['und'][0]  ['product_id']);
      $stock = $product->commerce_stock['und'][0]['value'];

      $query = db_select('commerce_order', 'c');
      $query->join('commerce_line_item', 'l', 'c.order_id = l.order_id');
      $query->addExpression('SUM(quantity)', 'quantity');
      $query->condition('l.line_item_label', $product->sku, '=');
      $query->condition('c.status', 'completed', '<>');
      $result = $query->execute()->fetchAssoc();
      $quantity = $result['quantity'];
      if ( ($stock > 0) && ($quantity > $stock) ) {
        $num_updated = db_update('commerce_order')
                       ->fields(array(
                        'status' => 'manufacturer'
                       ))
                       ->condition('order_id', arg(1), '=')
                       ->execute();
      }
    }
jtjikinw

jtjikinw1#

对循环中的数据库有多个可以移动的查询。
每次呼叫 commerce_ENTITY_TYPE_load 是数据库访问。你应该使用 commerce_ENTITY_TYPE_load_multiple 功能。这意味着在数组中收集所有需要的对象,通过它们各自的id进行索引,这需要一些基本的代码。

// Collect line item IDs (indexed by delta);
$line_item_ids = array_map(function ($line_item) {
  return $line_item['line_item_id'];
}, field_get_items('commerce_order', $oder, 'commerce_line_items'));
// Get line items, indexed by IDs.
$line_items = commerce_line_items_load_multiple($line_item_ids);

// Collect product IDs, indexed by line item IDs.
$product_ids = array_map(function ($line_item) {
  return field_get_items('commerce_line_item', $line_item, 'commerce_product')[0]['product_id'];
}, $line_items);
// Get products, indexed by IDs.
$products = commerce_product_load_multiple($product_ids);

自定义选择查询用于检索与行项目的产品sku匹配的行项目的数量。您已经将所有行项目和产品作为实体加载。所以不需要更多的数据库查询和sku的使用。此外,由于查询在找到quantity>stock的行项目后会更新订单本身,因此您可以中断第一个项目的循环。

foreach ($line_items as $line_item_id => $line_item) {
  $product = $products[$products_ids[$line_item_id]];
  $stock = field_get_items('commerce_product', $product, 'commerce_stock')[0]['value'];
  $quantity = $line_item->quantity;
  if (($stock > 0) && ($quantity > $stock)) {
    $num_updated = db_update('commerce_order')
      ->fields(array(
        'status' => 'manufacturer'
      ))
      ->condition('order_id', $order->order_id)
      ->execute();
    break;
  }
}

相关问题