mysql 作為業務庫,不太適合去作為分析,要不可能扛不住。先將mysql的資料同步到mongodb中,然後再從mongodb中去分析。
資料同步
將mysql中的資料同步到mongodb中,這裡分為兩步,第一步全量同步,不去檢查mongo是否存在這條資料,要不會耗時,直接插入。可以將id作為同步的校準,比如,同步過程中中斷了,此時在進行全量同步資料的時候,這樣不會導至重複插入。
$minId = OrderMongo::min('id');//基準id
Order::oldest('id')->where('id','>',$minId)->chunk(1000,function($items){
OrderMongo::insert($items->toArray());
})
嫌插入慢的時候,可以放進佇列執行。
$minId = OrderMongo::min('id');
Order::oldest('id')->where('id','>',$minId)->chunk(1000,function($items){
$a = $lists->pluck('id');
$data = [
'max' =>$a->max(),
'min' =>$a->min()
];
dispatch( new InsertQueue($data))->onQueue('insert-queue');
})
InsertQueue
public $data;
public function __construct($data)
{
$this->data = $data;
}
public function handle()
{
OrderModel::oldest('id')->where('id', '>=',$this->data['min'] ))->where('id','<=',$this->data['max'])->chunk(100,function(items){
OrderMongo::insert($items->toArray());
});
}
記得用一個程式去消費,要不插入資料的順序會亂掉。
全量同步完後,為了保持資料的一致性,要考慮增量同步,分為插入和更新。此時根據,update_time 的時間,來對資料進行更新或插入,增量同步的時間間隔,要比定時任務的時間間隔大一分鐘。這樣可以避免在當前時間點丟單的情況,像這樣
$schedule->command('sync:zengLiang')->everyThirtyMinutes();//30分鐘
//這裡 31分鐘
Order::where('update_time','>',now()->subMinutes(31))->each(function($item){
OrderMongo::updateOrInsert(['id'=>$item->id,$titem->toArray());
})
資料分析
使用慣了mysql的聚合語句後,使用mongo來查會一時適應不過來,mysql 使用 join 比較多,基本上 mongo 弄明白來”join”後,使用起來就舒服多了。這裡以orders和order_items 作為例子。上程式碼
$data = OrderMongo::query()->raw(function ($collection) {
$aggregate = [];
$aggregate[] = [
'$match'=>[//相當於mysql 的 where 和orWhere
'$and'=>[
['date' => ['$gte' => $start, '$lt' => $end]]
],
'$or'=>[
['store_id' => 1]
],
]
];
$aggregate[] = [
'$project' => [
'id' =>1,//欄位展示 相當於 mysql 的 select id ,total from orders
'store_id'=>1,
'total'=>1,//欄位展示
]
];
//$lookup 相當於 join
$aggregate [] = [
'$lookup'=>[
'from' =>'order_items',
'localField'=>'order_id',
'foreignField'=>'id',
'as'=>'items',
]
];
//不過這裡 查出的資料是 [[id,store_id,total,items]] items 是一個陣列,現在把它展開
$aggregate[] = [
'$unwind'=>'$items'
];
//假如 一個order 有三條 items 這裡會展開三條資料 [[id,store_id,total,items],[id,store_id,total,items],[id,store_id,total,items]] //這裡的items 是一個物件
//聚合
'$group'=>[
'_id' => [//這裡相當於 mysql 的groupBy field1,field2
'store_id'=>'$store_id'
],
'store_total' => [
'$sum' => '$total',
],//相當於 select sum(total) as store_total //這裡並不是門店的資料,因為 oreder_items 展開了,只是作為示例
];
return $collection->aggregate($aggregate);
})
這只是最基礎的分析資料,分析的時候,可以將各個維度的模組分析資料,分開,模擬資料弄的多一點,放進佇列跑,跑得快點,跑錯了沒關係,刪除掉資料重新跑。可能最後總資料只差了10 幾款錢,這時不要慌,先確定範圍,再將範圍一步步的縮小,最後找到造成資料錯誤的一條資料和幾條資料,修復,在和基準資料確認,再跑~總之就是不斷跑~~因為這一條資料錯誤,假如後面的資料依賴這條資料的話,那麼資料多多少少會有一點誤差
以上
待定
可能會寫一個資料同步的擴充套件包,因為寫的過程中,發現可以結構化,這樣在後臺點點點就可以同步了
本作品採用《CC 協議》,轉載必須註明作者和本文連結