php 순환 에서 sql 문 구 를 사용 하 는 것 을 어떻게 피 합 니까?
4448 단어 php 개발
순환 문 에서 데이터 베 이 스 를 실행 하 는 것 은 데이터 베이스 에 큰 부담 이 되 는 것 으로 알려 져 있다.예 를 들 어:
for(int I=0;I<500;I++){ }
이렇게 하면 이 검색 어 는 500 번 실 행 됩 니 다.조금 극단 적 으로 데이터베이스 내부 실행 문 구 를 무시 하 는 시간 입 니 다.서버 에서 데이터베이스 서버 사이 의 네트워크 가 원활 하지 않 습 니 다.서버 에서 조회 요청 을 데이터베이스 에 보 내 는 데 만 1 초 걸 립 니 다.다시 1 초 걸 립 니 다.이렇게 인터넷 상의 이유 만으로 도 대기 시간 은 1000 초 입 니 다.만약 당신 이 for 문장 밖에서 500 개의 데 이 터 를 한꺼번에 가 져 오 는 것 이 라면,이 네트워크 요청 대기 시간 은 2 초 입 니 다.
순환 량 이 매우 많 을 때 한편 으로 는 심각 한 네트워크 지연 을 초래 하고 한편 으로 는 데이터 베 이 스 를 연결 하 는 데 실패 할 수 있 기 때문에 순환 에서 sql 을 집행 하지 않 는 것 도 업계 의 준칙 이 라 고 할 수 있다.
어떻게
대전제:블 로 거들 이 사용 해 온 laravel 프레임 워 크 이기 때문에 laravel 특유 의 방법 을 사용 할 것 입 니 다.길 은 다 르 지만 여러분 의 마음 은 알 면 됩 니 다.
1.순환 내 sql 문 구 를 연결 하고 순환 외 실행
예 를 들 면:
// $users ,
foreach($users as $user){
// sql 。 sql
$sql .= " ('{$order_sn}', '{$this->user_id}', '{$deliver_fee}', 0, "
. " '', '', '', "
. " '{$add_time}','{$order_status}', '{$order_amount}', '{$remark}', "
. " '{$pickup_code}', '{$self_pickup}', '{$collect_order_sn}', '{$key}', {$reservation_time}),";
}
// sql ,
$sql = substr($sql, 0, -1);
DB::statement($sql);
2.where 조건 을 where in()으로 변경
예 를 들 어 우리 의 where()조건 에서 대규모 배열 을 사용 하려 면 문 구 는 다음 과 같 아야 한다.
foreach($arr as $v){
DB::table('')->where('id',$v->id);
}
이때 우 리 는 좀 바 꿀 수 있다.
// $arr, whereIn
DB::table('')->whereIn('id',$arr);
주의:만약 에 데이터 양 이 많 으 면 예 를 들 어 몇 십 만 개의 데이터 가 있 으 면 wherein 도 코드 의 병목 이 될 수 있 습 니 다.이 함 수 는 데이터 양 에 적용 되 는 것 이 많 지 않 습 니 다.
3.laravel 의 chunk 방법
공식 문서:https://laravel-china.org/docs/laravel/5.5/eloquent/1332
수천 개의 Eloquent 기록 을 처리 해 야 한다 면,chunk 명령 을 사용 할 수 있 습 니 다.chunk 방법 은 Eloquent 모델 의'블록 나 누 기'를 검색 하여 지정 한 Closure 에 제공 합 니 다.대형 결과 집합 을 처리 할 때 chunk 방법 을 사용 하면 메모 리 를 절약 할 수 있 습 니 다.
Flight::chunk(200, function ($flights) {
foreach ($flights as $flight) {
//
}
});
방법 에 전달 되 는 첫 번 째 매개 변 수 는 모든'블록'이 받 기 를 원 하 는 데이터 양 입 니 다.패 킷 을 닫 으 면 두 번 째 매개 변수 로 전달 되 며,데이터베이스 조 회 를 실행 할 때마다 블록 마다 호출 됩 니 다.
위의 이 코드 는 200 개 를 먼저 실행 하고 실행 한 후에 200 개 를 계속 실행 한 다 는 뜻 이다.페이지 를 나 누 는 것 과 유사 한 방법 으로 데이터 베 이 스 를 소 규모 로 호출 하면 빅 데이터 양의 조작 을 피 할 수 있다.
4.laravel 의 chunk()방법의 허점
메모:laravel 의 chunk 방법 은 조건 을 선별 하고 데 이 터 를 업데이트 할 때 데이터 가 누락 된 bug 가 나타 납 니 다.구체 적 으로 블 로 그 를 참고 할 수 있 습 니 다.https://www.jianshu.com/p/5dafd0d6e69a 예 를 들 면:
User::where('approved', 0)->chunk(100, function ($users) {
foreach ($users as $user) {
$user->update(['approved' => 1]);
}
});
위의 코드 를 실행 하려 면 오류 가 발생 하지 않 습 니 다.그러나 where 조건 은 approved 가 0 인 user 를 선별 한 다음 에 approved 의 값 과 새 값 을 1 로 합 니 다.
이 과정 에서 첫 번 째 데이터 베 이 스 를 수정 한 후에 다음 데이터 블록 의 데 이 터 는 수 정 된 데이터 에서 선 택 될 것 이다.이때 데이터 가 바 뀌 었 고 page 도 1 을 추가 했다.그래서 실행 이 끝 난 후 데이터 의 절반 만 업데이트 작업 을 했 습 니 다.
만약 이해 하지 못 한다 면,우 리 는 chunk 의 밑바닥 실현 을 살 펴 보 자.또한 위의 코드 를 예 로 들 면 모두 400 개의 데이터 가 있 으 면 데 이 터 는 100 개 에 따라 블록 처 리 됩 니 다.
page=1:처음에 page 는 1 이 고 1-100 개의 데 이 터 를 선택 하여 처리 합 니 다.
page=2:이때 100 번 째 데이터 의 approved 값 이 모두 1 이면 다음 에 선별 할 때 데이터베이스 에 조건 에 맞 는 데 이 터 는 300 개 에 불과 하고 데 이 터 는 101 번 째 조 에서 시작 되 며 이때 page=2 는 200-300 번 째 데이터 로 처 리 됩 니 다.그 후에 도 여전히.
public function chunk($count, callable $callback)
{
$results = $this->forPage($page = 1, $count)->get();
while (count($results) > 0) {
// On each chunk result set, we will pass them to the callback and then let the
// developer take care of everything within the callback, which allows us to
// keep the memory low for spinning through large result sets for working.
if (call_user_func($callback, $results) === false) {
return false;
}
$page++;
$results = $this->forPage($page, $count)->get();
}
return true;
}
물론 chunk()의 이 구멍 에 대해 서 는 chunk()의 소스 코드 를 찾 지 못 했 지만 저 는 laravel 5.5 로 이 문제 가 발생 하지 않 았 습 니 다.만약 큰 신 이 이 블 로 그 를 본다 면,아낌없이 가르침 을 주 십시오.
end