2012-05-20 18 views
8

estoy haciendo un servicio Web en php, que mi sitio web se utilizará para buscar información con Ajax llamadas.PHP Red Bean ORM Problema de rendimiento

Al principio solo lo hice de forma estándar con el php mysql lib incorporado, y escribí todas las consultas de forma manual e hice todo el modelo de datos en MySQL Workbench y más. Esto llevó MUCHO tiempo y si tenía que cambiar el modelo de datos después, todo empezaría a ser muy complicado, así que decidí buscar PHP ORM, y encontré RedBean que me parece pura magia y alegría .

Excepto que tengo muchas dificultades con los problemas de rendimiento. Mi sitio es un sitio para que los usuarios creen sus propias listas de series de televisión. Solicito una fuente externa para una serie e la inserto en mi base de datos si no está allí, de lo contrario la obtengo de mi propia base de datos.

el xml que obtengo de esta fuente externa enumera la serie, temporadas, episodios, etc. y lo guardo todo de esta manera.

function InsertSerie($serie) { 
    $serieBean = $this->CreateSerieBean($serie->Series); 
    $genreBeans = $this->CreateGenreBeans($serie->Series->Genre); 
    $actorBeans = $this->CreateActorBeans($serie->Series->Actors); 
    $episodeBeans = array(); 
    foreach ($serie->Episode as $episode) { 
     $episodeBean = $this->CreateEpisodeBean($episode); 
     $seasonBean = $this->CreateSeasonBean($episode); 
     $writerBeans = $this->CreateWriterBeans($episode->Writer); 
     $guestBeans = $this->CreateActorBeans($episode->GuestStars); 
     $directorBeans = $this->CreateDirectorBeans($episode->Director); 
     R::associate($episodeBean, $seasonBean); 
     foreach ($writerBeans as $bean) { 
      R::associate($episodeBean, $bean); 
     } 
     foreach ($guestBeans as $bean) { 
      R::associate($episodeBean, $bean); 
     } 
     foreach ($directorBeans as $bean) { 
      R::associate($episodeBean, $bean); 
     } 
     $episodeBeans[] = $episodeBean; 
    } 
    foreach ($genreBeans as $bean) { 
     R::associate($serieBean, $bean); 
    } 
    foreach ($actorBeans as $bean) { 
     R::associate($serieBean, $bean); 
    } 
    foreach ($episodeBeans as $bean) { 
     R::associate($serieBean, $bean); 
    } 
} 

function CreateGenreBeans($genres) { 
    if(empty($genres)) { return; } 
    $genre = explode("|", $genres); 
$genreBeans = array(); 
foreach ($genre as $g) { 
    if($g != '') { 
      $genreBeans[] = $this->CreateGenreBean($g); 
     } 
    } 
    return $genreBeans; 
} 

function CreateGenreBean($genre) { 
    $bean = R::dispense('genre'); 
    $bean->name = (string)$genre; 
    return $bean; 
} 

function CreateDirectorBeans($directors) { 
    if(empty($directors)) { return; } 
    $director = explode("|", $directors); 
$directorBeans = array(); 
foreach ($director as $d) { 
    if($d != '') { 
      $directorBeans[] = $this->CreateDirectorBean($d); 
     } 
    } 
    return $directorBeans; 
} 

function CreateDirectorBean($director) { 
    $bean = R::dispense('director'); 
    $bean->name = (string)$director; 
    return $bean; 
} 

function CreateActorBeans($actors) { 
    if(empty($actors)) { return; } 
    $actor = explode("|", $actors); 
$actorBeans = array(); 
foreach ($actor as $a) { 
    if($a != '') { 
      $actorBeans[] = $this->CreateActorBean($a); 
     } 
    } 
    return $actorBeans; 
} 

function CreateActorBean($actor) { 
    $bean = R::dispense('actor'); 
    $bean->name = (string)$actor; 
    return $bean; 
} 

function CreateWriterBeans($writers) { 
    if(empty($writers)) { return; } 
    $writer = explode("|", $writers); 
$writerBeans = array(); 
foreach ($writer as $w) { 
    if($w != '') { 
      $writerBeans[] = $this->CreateWriterBean($w); 
     } 
    } 
    return $writerBeans; 
} 

function CreateWriterBean($writer) { 
    $bean = R::dispense('writer'); 
    $bean->name = (string)$writer; 
    return $bean; 
} 

function CreateSerieBean($serie) { 
    $bean = R::dispense('serie'); 
    $bean->serie_id = (string)$serie->id; 
    $bean->airs_day_of_week = (string)$serie->Airs_DayOfWeek; 
    $bean->airs_time = (string)$serie->Airs_Time; 
    $bean->content_rating = (string)$serie->ContentRating; 
    $bean->first_aired = (string)$serie->FirstAired; 
    $bean->imdb_id = (string)$serie->IMDB_ID; 
    $bean->language = (string)$serie->Language; 
    $bean->network = (string)$serie->Network; 
    $bean->overview = (string)$serie->Overview; 
    $bean->rating = (string)$serie->Rating; 
    $bean->rating_count = (string)$serie->RatingCount; 
    $bean->run_time = (string)$serie->Runtime; 
    $bean->serie_name = (string)$serie->SeriesName; 
    $bean->status = (string)$serie->Status; 
    $bean->last_updated = (string)$serie->lastupdated; 
    $bean->thumbnail = (string)$serie->thumbnail; 
    return $bean; 
} 

function CreateSeasonBean($episode) { 
    $bean = R::dispense('season'); 
    $bean->season_id = (string)$episode->seasonid; 
    $bean->season_number = (string)$episode->SeasonNumber; 
    return $bean; 
} 

function CreateEpisodeBean($episode) { 
    $bean = R::dispense('episode'); 
    $bean->episode_id = (string)$episode->id; 
    $bean->episode_name = (string)$episode->EpisodeName; 
    $bean->episode_number = (string)$episode->EpisodeNumber; 
    $bean->first_aired = (string)$episode->FirstAired; 
    $bean->imdb_id = (string)$episode->IMDB_ID; 
    $bean->language = (string)$episode->Language; 
    $bean->overview = (string)$episode->Overview; 
    $bean->rating = (string)$episode->Rating; 
    $bean->rating_count = (string)$episode->RatingCount; 
    $bean->last_updated = (string)$episode->lastupdated; 
    return $bean; 
} 

El problema es que tarda unos 5 minutos para insertar una serie y se inserta duplicados, así, haciendo R::freeze(); no ayuda, ya sea el rendimiento.

P: ¿Cómo puedo solucionar este problema, qué puedo hacer para que redbean funcione mejor, qué puedo hacer con mi propio código para que funcione mejor, o simplemente debería utilizar una solución/marco de enfoque diferente, etc. ?

Se trataron listas compartidas como las sugeridas pero con el mismo resultado.

function InsertSerie($serie) { 
    $serieBean = $this->CreateSerieBean($serie->Series); 
    ... 
    foreach ($serie->Episode as $episode) { 
     $episodeBean = $this->CreateEpisodeBean($serieBean ,$episode); 
     ... 
     $this->CreateDirectorBeans($serieBean, $episode->Director); 
     $serieBean->sharedEpisode[] = $episodeBean; 
    } 
    R::store($serieBean); 
} 

function CreateDirectorBeans($bean, $directors) { 
    if(empty($directors)) { return; } 
    $director = explode("|", $directors); 
    foreach ($director as $d) { 
     if($d != '') { 
      $bean->sharedDirector[] = $this->CreateDirectorBean($d); 
     } 
    } 
} 

function CreateDirectorBean($director) { 
    $bean = R::dispense('director'); 
    $bean->name = (string)$director; 
    return $bean; 
} 
    .... 
+3

La solución de problemas de rendimiento comienza con el perfilado. Esto se debe a que tiene poco sentido intentar solucionar un problema antes de haber identificado cuál es el problema. Puede usar microtime() o una herramienta como xdebug. – goat

+0

No sé cómo reducir la pregunta más que esto:/Supongo que estoy usando redbean de la manera incorrecta aquí haciendo reparto de transacciones en lugar de un lote grande o algo así? – furier

+1

perfilar significa medir cuánto tardan en ejecutarse ciertas partes de su código. El objetivo es identificar las partes más lentas, ya que a menudo habrá una cosa en particular que se destaca.Entonces, puedes enfocar tus esfuerzos donde obtengas la mayor recompensa por tu tiempo. – goat

Respuesta

7

fin he encontrado la manera de reducir el tiempo de ejecución de 5 minutos a aproximadamente 11sec, todavía se lleva a destinar de tiempo, pero teniendo en cuenta la cantidad de datos y el trabajo que tiene que hacer, creo que es bueno para ese hardware.

que añaden estas líneas de código

R::Begin(); 
R::associate($bean1, $bean2); 
... 
R::commit(); 

Ahora se reúne todo el trabajo y lo realiza en una transacción grande como la unidad del patrón de trabajo. También para evitar duplicados inserción i pasado a utilizar

$bean = R::findOrDispense($type, $sql, $values); 

Entonces me acabo de volver del grano si ya existe, si no puedo crear uno nuevo y lo devuelve.

0

¿Ha intentado utilizar listas compartidas en lugar de pasar por las relaciones?

$serieBean->sharedActor[] = $actorBeans; 
$serieBean->sharedEpisode[] = $episodeBeans; 

http://www.redbeanphp.com/manual/shared_lists

+0

solo se creó la tabla de serie y con solo los datos de serie insertados, no hay otras tablas ... – furier

+0

en realidad cometí un error, fui rápido y no leí que compartió es una palabra clave y que el resto de la lista tiene que coincidir con el tipo de frijol. Ahora funciona igual que anteriormente, insertando duplicados y tarda unos 5 minutos en insertar una serie. El uso de CPU y ram en el servidor parece muy bajo, pero puedo escuchar el disco funcionar como el infierno, pero no creo que ese sea el problema aquí – furier

+0

He leído algo sobre la unidad de trabajo, que es un contenedor para todo su trabajo y hace todo el sql en una transacción. http://redbeanphp.com/community/wiki/index.php/Unit_of_Work Pero no puedo encontrar ningún ejemplo de código sobre cómo obtener un objeto $ uow que puedo agregarWork(); también... – furier

Cuestiones relacionadas