PHP:循环处理数千个项目时出现内存问题。

huangapple go评论62阅读模式
英文:

PHP: memory issues while looping thousand of items

问题

这是一个WordPress与WooCommerce项目。

我必须循环遍历一个包含超过20万个项目的数组。每个项目都是数据库中的一个订单ID。我必须对每个订单的元数据求和以得到总和。但是循环总是出现内存问题。

以下是我的代码:

function woq_orders_total(){
	$orders = get_option( 'woq_orders_ids' ); // ID数组
	$meta = array();

	$i = 0;
	foreach( $orders as $order ) :
		$meta[] = get_post_meta( $order, '_order_total', true );
		if ( $i % 500 == 0 )
			sleep( 5 ); // 每500个项目停顿5秒

		$i++;
	endforeach;

	update_option( 'woq_orders_total', array_sum( $meta ) );
}

我尝试每100个项目停顿一次,但问题仍然存在。这在处理少量项目时效果良好,但在处理这么多项目时不起作用。

感谢任何帮助。

英文:

This is a WordPress with Woocommerce project.

I have to loop an array with more than 200 thousand of items. Every item is an order's ID in the data base. I have to sum the value of every order's meta to get the total sum. But the loop allways ends with memory issue.

Here is my code:

function woq_orders_total(){
	$orders = get_option( 'woq_orders_ids' ); // array of IDs
	$meta = array();

	$i = 0;
	foreach( $orders as $order ) :
		$meta[] = get_post_meta( $order, '_order_total', true );
		if ( $i % 500 == 0 )
			sleep( 5 ); // stop for 5 seconds every 500 items

		$i++;
	endforeach;

	update_option( 'woq_orders_total', array_sum( $meta ) );
}

I've try stoping every 100 items, but the problem persists. This works well with a few numbers of items, but not with this big amount.

Thanks for any help

答案1

得分: 2

你不必将所有数据读入数组中以进行求和。
你只需要存储总和。

```php
function woq_orders_total(){
    $orders = get_option( 'woq_orders_ids' ); // array of IDs
    $total = 0;

    foreach( $orders as $order ) :
        $total += (float)get_post_meta( $order, '_order_total', true );
    endforeach;

    update_option( 'woq_orders_total', $total);
}

<details>
<summary>英文:</summary>

You don&#39;t have to read all the data into the array to sum them up.
You only need to store the sum.

```php
function woq_orders_total(){
    $orders = get_option( &#39;woq_orders_ids&#39; ); // array of IDs
    $total = 0;

    foreach( $orders as $order ) :
        $total += (float)get_post_meta( $order, &#39;_order_total&#39;, true );
    endforeach;

    update_option( &#39;woq_orders_total&#39;, $total);
}

答案2

得分: 2

我已经找到了一个解决方案,感谢 Markus AO 的评论。

现在我的代码看起来像这样:

function woq_orders_total(){
	global $wpdb;
	$orders = get_option( 'woq_orders_ids' );
	$orders = join( ',', $orders );
	$meta_key = '_order_total';

	$total = $wpdb->get_var(
		$wpdb->prepare(
			"
			SELECT SUM(meta_value)
			FROM $wpdb->postmeta
			WHERE meta_key = %s
			AND post_id IN ({$orders})
			",
			$meta_key
		)
	);

	update_option( 'woq_orders_total', $total );
}

另外,$wpdb 文档中的这些评论对我帮助很大:https://developer.wordpress.org/reference/classes/wpdb/#comment-1975

谢谢大家。

英文:

I've found a solution thanks to the comment by Markus AO

Now my code looks like this:

function woq_orders_total(){
	global $wpdb;
	$orders = get_option( &#39;woq_orders_ids&#39; );
	$orders = join( &#39;,&#39;, $orders );
	$meta_key = &#39;_order_total&#39;;

	$total = $wpdb-&gt;get_var(
		$wpdb-&gt;prepare(
			&quot;
			SELECT SUM(meta_value)
			FROM $wpdb-&gt;postmeta
			WHERE meta_key = %s
			AND post_id IN ({$orders})
			&quot;,
			$meta_key
		)
	);

	update_option( &#39;woq_orders_total&#39;, $total );
}

Also these comment in $wpdb documentation help a lot https://developer.wordpress.org/reference/classes/wpdb/#comment-1975

Thanks you all.

huangapple
  • 本文由 发表于 2023年5月25日 02:43:05
  • 转载请务必保留本文链接:https://go.coder-hub.com/76326536.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定