如何优化统计生成的速度-涉及多变量口才模型?

时间:2019-08-13 09:36:37

标签: laravel

我们开发了一个门户,我们的客户及其员工可以跟踪他们的销售,工作时间等。在这些门户中,经理们可以通过创建新的统计信息来定义自己的统计信息,并选择需要监控的产品。

在“统计信息”部分,他们可以获取所有雇员(150)的表,用于其选定的统计信息。

更具体一点:我们有一个SaleItem模型。在此sale_item中,引用了product_id。 (产品型号)

我们有一个统计模型。在此模型中,我们与许多StatisticProduct模型有关。 (它们属于统计信息)

我们的模型:

class SaleItem extends Model 
{

   /**
     * @return \Illuminate\Database\Eloquent\Relations\BelongsTo
     */
    public function product()
    {
        return $this->belongsTo(Product::class);
    }

    /**
     * @return \Illuminate\Database\Eloquent\Relations\BelongsTo
     */
    public function user()
    {
        return $this->belongsTo(User::class);
    }
}

class Statistic extends Model
{

/**
     * @return \Illuminate\Database\Eloquent\Relations\HasMany
     */
    public function statistic_products()
    {
        return $this->hasMany(StatisticProduct::class);
    }

}

class StatisticProduct extends Model
{

    public function product()
    {
        return $this->belongsTo(Product::class);
    }

    /**
     * @return \Illuminate\Database\Eloquent\Relations\BelongsTo
     */
    public function statistic()
    {
        return $this->belongsTo(Statistic::class);
    }

}

在我们的控制器内:

public function showAllUserStats(Request $request)
{

    $start = Carbon::createFromFormat('Y-m-d',$request->get('start'));
    $end = Carbon::createFromFormat('Y-m-d',$request->get('end'));

    $stats = Statistic::where('active',1)
            ->select(
                'statistics.name',
                'statistics.id as statistic_id'
            )          
            ->get();
    $users = User::where('active', '=', 1)->get();

    foreach ($stat as $skey => $s) {          

                if (!Cache::has('products_statistic_'.$s->statistic_id))
                    $stat[$skey]->s_products = Cache::rememberForever('products_statistic_'.$s->statistic_id, function() use($s){
                        return StatisticProduct::where('statistic_id', '=', $s->statistic_id)
                            ->pluck('product_sku')
                            ->toArray();
                    });
                else $stat[$skey]->s_products = Cache::get('products_statistic_'.$s->statistic_id);
}

    foreach ($users as $key => $user) {
                $users[$key]->commission = SaleItem::whereBetween('created_at', [$start,$end])                    ->where('user_id', '=', $user->id)
                    ->sum('commission');
                $users[$key]->commission_base = SaleItem::whereBetween('created_at', [$start,$end])
                    ->where('user_id', '=', $user->id)
                    ->sum('commission_base');
                $users[$key]->works = Work::whereBetween('day', [$start,$end])
                    ->where('user_id', '=', $user->id)
                    ->sum('hours');
                foreach ($stat as $skey => $s) {
                    $sales = SaleItem::where('user_id','=',$user->id)
                        ->whereBetween('created_at',[$start,$end])
                        ->whereIn('sku',$s->s_products)
                        ->select(DB::raw('COUNT(user_id) as count'))
                        ->get();
                    $salesWithCategory =  SaleItem::where('user_id', $user->id)
                        ->whereBetween('sale_items.created_at', [$start,$end])
                        //->join('sale_items', 'sale_items.sale_id', '=', 'sales.id')
                        ->join('products','sale_items.product_id','=','products.id')
                        ->join('product_categories','products.product_category_id','=','product_categories.id')
                        ->whereIn('sale_items.sku', $s->s_products)
                        ->groupBy('product_category_id')
                        ->select([DB::raw('COUNT(sale_items.id) as sum'),DB::raw('product_categories.name as category_name')])
                        ->get();
                    //winback
                    if($s->statistic_id == 48)
                        $sales[0]->count += Sale::whereBetween('created_at',[$start,$end])->where('winback','=',1)->where('user_id','=',$user->id)->count();
                    $stat[$skey]->count = $sales[0]->count;
                    $stat[$skey]->salesWithCategory = $salesWithCategory;
                }
                $users[$key]->sales = $stat->toArray();

}

    return view('statistics.users',['stats' => $users]);

}


视图:

<table class="table table-condensed table-striped table-responsive dataTable" id="usersTable">
                                <thead>
                                <tr>
                                    <th>Name</th>
                                    <th>Umsatz</th>                                   
                                    <th>Stunden</th>
                                    @foreach($stats[0]->sales as $sale)
                                        <th>{{ $sale['name'] }}</th>
                                    @endforeach
                                </tr>
                                </thead>
                                <tbody>
                                @foreach($stats as $user)
                                    <tr>
                                        <td>{{ $user->name }}, {{ $user->first_name }} / {{ $user->shop->shortname }}, {{ $user->shop->micro_region }} / {{ $user->role[0]->display_name }}</td>
                                        <td>{{ $user->commission }} €</td>                                       
                                        <td>{{ round($user->works,2) }}h</td>
                                        @foreach($user->sales as $sale)
                                            <td><span data-html="true" data-toggle="tooltip" data-placement="top" data-original-title="<table>@foreach($sale['salesWithCategory'] as $category)<tr><td>{{ $category->sum }}</td><td>{{ $category->category_name }}</td></tr> @endforeach </table>">{{  $sale['count'] }}</span></td>
                                        @endforeach
                                    </tr>
                                @endforeach
                                </tbody>
                            </table>

我所做的一切都符合预期-但例如,如果经理选择10个不同的统计数据,则统计信息生成会非常缓慢。感谢您在优化此方面的任何帮助。

我已经尝试过急于加载statistic_products-这对我目前正在缓存产品,并且仅在统计信息已更改时才获取它们没有太大帮助...

1 个答案:

答案 0 :(得分:0)

有时它仅有助于描述问题,考虑问题并重写您的类;)我现在正在使用group并遍历它。我能够将工作量从1800个查询减少到17个查询,并将内存消耗从80MB减少到9.8 MB