2013-06-07 1 views
0

이 스크립트로 부품 번호 테이블을 작성하려고합니다. 나는 빨리 추리하고있다. 약 16 $mat_codes의 값과 $shape_codes 16가 당연히이 기록을 위해중첩 된 for 루프로 메모리 hogging PHP 스크립트를 자르십시오.

PHP Fatal error: Allowed memory size of 134217728 byets exhauseted (tried to allocate 71 bytes)

을 반환

foreach ($mat_codes as $mat_code) { 
    for ($n = 0; $n < count($shape_codes); $n++){ 
     for ($d1 = 0; $d1 <= 12; $d1++){ 
      for ($d1_dec = 1; $d1_dec <= 16; $d1_dec++){ 
      for ($d2 = 0; $d2 <= 12; $d2++){ 
       //for ($d2_dec = 1; $d2_dec <= 16; $d2_dec++){ 
       $build_part = (object) NULL; 
       $build_part = $mat_code->part_code; 
       $build_part .= $shape_codes[$n]->part_code; 
       $build_part .= '.'; 
       if ($d1 != 0) { 
        $build_part .= $d1 . '-'; 
       } 
       $build_part .= $d1_dec; 
       $build_part .= '.'; 
       // if ($d2 != 0) { 
       // $build_part .= $d2 . '-'; 
       // } 
       // $build_part .= $d2_dec; 
       // $build_part .= '.'; 

       // * save $build_part to MYSQL * // 
      //} 
      } 
     } 
     } 
    } 
    } 

: 나는도를 가져올 수 없습니다 루프를 주석있다. 필자의 계산에 따르면이 예제에서는 692,224 개의 부품 번호 만 작성하려고합니다. 나는 더 많은 것을 추가하고 ~ 3400 만까지 가지고있을 것이라고 생각한다. IMHO, 그냥 작업에 더 많은 메모리를 할당하여이 작업을 시도하는 것은 어리석은 일입니다. 물론 내 질문 -이 스크립트를 작은 조각으로 나누려면 어떻게해야합니까?

편집 : 해결 방법이 있습니다. 나는 그것이 원래 질문에서 정의한 범위를 벗어 났음을 사과한다. 나는 이것이 단순히 잠재적 인 부품 번호의 테이블이라는 것을 언급하지 않았다. 특히 부품 번호 시스템의 논리에 의해 허용되는 모든 잠재적 부품 번호. 부품 번호의 마스터 목록을 준비 중에 사용하기 위해 기다리는 대신 부품 번호 지정 논리에 대한 새 부품 입력의 유효성을 검사하는 것이 더 좋을 수도 있습니다 (could_this_be_a_part_number($input)과 같은 기능). 그것은 체크 할 필요가있는 몇몇 마스터 테이블을 갖는 것과 대조적으로 부품 번호 매김 로직에 대해 입력 된 문자열을 테스트 할 수 있습니다.

x2 편집 : 죄송합니다. 최악입니다. 나는 안쪽 for 루프로 unset($build_part)을 옮겼다. 문제는 내가 Drupal에서 $ build_part를 설정하기 전에 출력하기 위해 개발 기능에 노력하고 있었다는 것입니다. dpm($build_part). 스크립트가 잘 돌아가고, 많은 부분 번호가 인쇄 된 웹 페이지를 작성하려고하면 스크립트가 손상됩니다.

+1

이 문맥은 무엇입니까? 많은 데이터가 있으면 데이터베이스 나 Redis와 같은 메모리 내 구조에 더 많은 데이터를 넣을 수 있습니다. –

+0

오 잘이 모든 것이 내 MYSQL 데이터베이스에 저장 될 것입니다. 나는 그 데이터베이스를 채우기위한 스크립트를 작성하려고하고있다. – kevinaskevin

+0

내부 루프에서 생성 된 값을 저장하지 않는 이유가 있습니까? 당신은 (거의) 끝없이 연결되어 있기 때문에 기억이 부족합니다. 각 결과를 DB에 저장하면 메모리 문제가 줄어 듭니다. –

답변

1

우선, $ build_part은 개체가 아니 듯이 보입니다. 문자열과 같이 취급하므로 개체를 초기화하지 마십시오.

$build_part = NULL;이면 충분합니다.

둘째로 : 우리는 데이터를 데이터베이스에 저장하는 방법을 모르지만 (원래의 대답으로 제안했듯이) 쿼리를 작성하여 데이터베이스로 보낸 다음 잇다. 이제

의 당신의 코드를 살펴 보자 : 나는 결정했다

$i = 0; 
foreach ($mat_codes as $mat_code) { 
    for ($n = 0; $n < count($shape_codes); $n++){ 
     for ($d1 = 0; $d1 <= 12; $d1++){ 
      for ($d1_dec = 1; $d1_dec <= 16; $d1_dec++){ 
      for ($d2 = 0; $d2 <= 12; $d2++){ 
       for ($d2_dec = 1; $d2_dec <= 16; $d2_dec++){ 
       $i++; 
       $build_part = (object) NULL; 
       $build_part = $mat_code->part_code."."; 
       $build_part .= $shape_codes[$n]->part_code; 
       $build_part .= '.'; 
       if ($d1 != 0) { 
        $build_part .= $d1 . '-'; 
       } 
       $build_part .= $d1_dec; 
       $build_part .= '.'; 
       if ($d2 != 0) { 
        $build_part .= $d2 . '-'; 
       } 
       $build_part .= $d2_dec; 
       // echo "$i $build_part <br>"; 
       // * save $build_part to MYSQL * // 
      } 
      // This is first triggered when the count reaches 16 items 
      echo "--- lvl 5<br>"; 
      } 
      // 208 items 
      echo "--- lvl 4<br>"; 
     } 
     // 3328 items 
     echo "--- lvl 3<br>"; 
     } 
     echo "--- lvl 2<br>"; 
    } 
    echo "--- lvl 1<br>"; 
} 

을 (당신이 다른 곳에서 그것을 할 수있는) 일부 사전 제작 전송 될 수있는 지점으로 레벨 3 기호을 데이터베이스에 대한 MySQL 쿼리. 같은 뭔가 :

$mysqli->query("INSERT INTO parts ( part_id ) VALUES $very_long_string;");

는 또한이 MySQL의 명령을 살펴 : INSERT DELAYED, 나는 그것 (! 원문) 상황에서 매우 유용 할 수 있습니다 어쩌면 생각합니다.

$을 very_long_string하는 등의 가장 내부 루프에 내장 될 것이다 :

$very_long_string .= "('$build_part'),"; 

과 결국 (우리는 생성하고 최종 쿼리를 보내기 전에) 우리가 마지막 쉼표 잘라 것 :

$very_long_string = rtrim($very_long_string, ","); 

그런 다음 3000+ items long 쿼리를 데이터베이스로 보냅니다. 그런 다음 설정을 해제하고 ($ very_long_string) 다시 시작하십시오. 당신의 편집을 읽은 후

foreach ($mat_codes as $mat_code) { 
for ($n = 0; $n < count($shape_codes); $n++){ 
    for ($d1 = 0; $d1 <= 12; $d1++){ 
     $very_long_string = null; 
     for ($d1_dec = 1; $d1_dec <= 16; $d1_dec++){ 
      for ($d2 = 0; $d2 <= 12; $d2++){ 
       for ($d2_dec = 1; $d2_dec <= 16; $d2_dec++){ 
       $build_part = NULL; 
       $build_part = $mat_code->part_code."."; 
       $build_part .= $shape_codes[$n]->part_code; 
       $build_part .= '.'; 
       if ($d1 != 0) { 
        $build_part .= $d1 . '-'; 
       } 
       $build_part .= $d1_dec; 
       $build_part .= '.'; 
       if ($d2 != 0) { 
        $build_part .= $d2 . '-'; 
       } 
       $build_part .= $d2_dec; 
       $very_long_string .= "('$build_part'),"; 
       } 
      } 
     } 
     $very_long_string = rtrim($very_long_string, ","); 
     $mysqli->query("INSERT INTO parts (part_id) VALUES $very_long_string;"); 
     unset($very_long_string); 
    } 
} 
} 

편집 :

그래서 나는 최종 코드는 다음과 같은 것을을 보일 것 같아요 난 당신이 데이터베이스를 채우는 싶어한다는 사실을 다루는 과정이었다 : D를 .. 만약 당신이 검증 기능이 필요하다면 그것은 완전히 다른 이야기입니다.

+0

당신과 @ chris-henry 및 @jeroen에 응답합니다. 이것은 AAA.BBB. # - #. # - #. #. ###. EEE'의'.'과''사이의 잠재적 인 항목의 수는 16.16입니다. 13-16.13-16.24.10. 따라서 ~ 3400 만개의 고유 한 문자열이 필요합니다. 내가 어디에 데이터베이스에이 옵션을 작성 해야하는 기존 루프에 대한 이해가 안 돼. 완성되기 전에 부품 번호를 입력 할 수 없습니다. – kevinaskevin

+0

@fortmac 데이터베이스에 저장 한 후에는 '설정 해제'해야합니다. 다시 말해 완성 된 부품 번호의 692,224 개가 모두 완료되면 메모리에 남아 있지 않도록해야합니다. –

+0

사려 깊은 반응에 감사드립니다. 위의 편집 섹션에 대해 걱정하지 마십시오. 실용적인 해결 방법은 원래 질문 자체가 의미합니다. – kevinaskevin