Aller au contenu

Principe de base "tampon"


Sujets conseillés

Posté (modifié)

Bonjour,

J'ai un gros process de mise à jour d'un site. Il se décompose comme ceci :

- copie de gros fichiers XML sur le serveur (env 100 Mo au total)

- import des xml par un parsing avec php dans une table temporaire "pt_products_temp" --> dure 10 min

- on vide la table "pt_products" (table de production)

- on copie "pt_products_temp" dans "pt_products" --> dure quelques secondes

Mon code :

	// on vide la table de prod
$sql = "TRUNCATE TABLE `pt_products`";
$resultat = mysql_query($sql);

// on copie les données
$sql = 'INSERT INTO `pt_products` SELECT * FROM `pt_products_temp`;';
$resultat = mysql_query($sql);

// on vide la table temp
$sql = "TRUNCATE TABLE `pt_products_temp`";
$resultat = mysql_query($sql);

Ca se passe plutôt bien sauf que des erreurs apparaissent en front :

Warning: mysql_fetch_array(): supplied argument is not a valid MySQL result resource in /home/sd/shopping/www/includes/database.php on line 21

Warning: mysql_num_rows(): supplied argument is not a valid MySQL result resource in /home/sd/shopping/www/includes/database.php on line 26

Pourtant, un coup de "Réparer les table" dans PhpMyAdmin et c'est reparti...

Savez-vous pourquoi ? Existerait-il une solution plus fiable (en intervenant que sur le script d'import) ?

Merci pour votre aide

Modifié par bobdeo
Posté

Tu peux coller ici les lignes 21 et 26 de database.php ?

A priori il y aurait un problème d'index, mais comme je n'ai pas tout le code... il manquerait un index FULLTEXT sur toutes les colonnes de la recherche...

Posté

Merci pour ton aide

De la ligne 21 à 26 :

	while($row = mysql_fetch_array($result,MYSQL_ASSOC))
{
$rows[] = $row;
}

return mysql_num_rows($result);

Posté

Voilà tout le fichier :

<?php

function database_querySelect($sql,&$rows)
{
global $config_databaseServer;

global $config_databaseName;

global $config_databaseUsername;

global $config_databasePassword;

$link = _AT_mysql_connect($config_databaseServer,$config_databaseUsername,$config_databasePassword);

@mysql_select_db($config_databaseName,$link);

$result = mysql_query($sql,$link);

$rows = array();

while($row = mysql_fetch_array($result,MYSQL_ASSOC))
{
$rows[] = $row;
}

return mysql_num_rows($result);
}

function database_queryModify($sql,&$insertId)
{
global $config_databaseServer;

global $config_databaseName;

global $config_databaseUsername;

global $config_databasePassword;

$link = _AT_mysql_connect($config_databaseServer,$config_databaseUsername,$config_databasePassword);

@mysql_select_db($config_databaseName,$link);

$result = mysql_query($sql,$link);

$insertId = mysql_insert_id();

return mysql_affected_rows();
}

function database_safe($text)
{
return mysql_escape_string($text);
}
?>

Je ne sais pas si tu arriveras à quelque chose. Existe-il un moyen de "refaire" l'index en fin d'import (puisque c'est lui qui met la zone)...

Posté

Bon ça c'est la fonction, mais il manque $sql pour voir quelle est la requête... donc je sais pas quels champs ni quelles tables sont concernées.

Rajoute :

if ( mysql_error() ) echo $sql;

Posté (modifié)

Voici un exemple de la requête :

SELECT * , MIN( price ) AS minPrice, MAX( price ) AS maxPrice, COUNT( id ) AS numMerchants, MATCH name AGAINST ('Hitachi DZ HS500E') AS relevance FROM `pt_products` WHERE category = 'Camescopes' AND MATCH name AGAINST ('Hitachi DZ HS500E') AND name <> 'Hitachi DZ HS500E' GROUP BY name ORDER BY relevance LIMIT 5

Merci

Modifié par bobdeo
  • 2 semaines plus tard...
Posté (modifié)

C'est au niveau du MATCH ... AGAINST ('...')

Essaye de créer un Fulltext sur le champ de la table "name" (dans ton exemple) où tu recherches avec ça ...

Modifié par Occi
Posté

Bonjour,

J'ai un gros process de mise à jour d'un site. Il se décompose comme ceci :

- copie de gros fichiers XML sur le serveur (env 100 Mo au total)

- import des xml par un parsing avec php dans une table temporaire "pt_products_temp" --> dure 10 min

si ce n'est pas déjà fait essayes de passer directement du xml à une requête sql (ou un fichier cvs)

xml -> confrontation à un xsl ou dtd pour validation -> transformation xslt -> sortie sql ou texte

reste ensuite à donner directement la commande générée à mysql (ou faire un load data infile)

le tout placé dans un bash sh (éventuellement appelé par php ou cron)

il y a par exemple xsltproc comme processeur xml utilisable en ligne de commande (et donc via exec de php)

il faut bien sûr avoir les droit suffisant sur l'hébergement mais il y a de grande chance que xsltproc + "load data infile" aille plus vite que php/extention+requête ; et sur 10 minutes de traitement la différence peut être sensible. (maintenant si c'est à faire tous les 36 du mois à 3h du mat c'est peut-être pas la priorité)

- on vide la table "pt_products" (table de production)

- on copie "pt_products_temp" dans "pt_products" --> dure quelques secondes

Mon code :

	// on vide la table de prod
$sql = "TRUNCATE TABLE `pt_products`";
$resultat = mysql_query($sql);

// on copie les données
$sql = 'INSERT INTO `pt_products` SELECT * FROM `pt_products_temp`;';
$resultat = mysql_query($sql);

// on vide la table temp
$sql = "TRUNCATE TABLE `pt_products_temp`";
$resultat = mysql_query($sql);

il semble que TRUNCATE ne prenne pas en compte les transactions en cours, donc un LOCK serait adéquat (et peut être déjà en oeuvre)

et si un LOCK/UNLOCK est nécessaire, peut être que quelque secondes peuvent être gagnées en évitant le SELECT et en interchangeant les tables

après traitement dex xml > `pt_products_temp`:

LOCK TABLES `pt_products` WRITE, `pt_products_temp` WRITE`;
RENAME TABLE `pt_products` TO `pt_backup`,
`pt_products_temp` TO `pt_products`,
`pt_backup` TO `pt_products_temp`;
TRUNCATE `pt_products_temp`;
UNLOCK TABLES `pt_products`, `pt_products_temp`;

... à voir si le temps d'indisponibilité est plus court (temps total éventuellement plus long car le LOCK va attendre que les transactions en cours se terminent)

Ca se passe plutôt bien sauf que des erreurs apparaissent en front :

Warning: mysql_fetch_array(): supplied argument is not a valid MySQL result resource in /home/sd/shopping/www/includes/database.php on line 21

Warning: mysql_num_rows(): supplied argument is not a valid MySQL result resource in /home/sd/shopping/www/includes/database.php on line 26

comme ça a été dit il y a un problème d'index après que la table ait été supprimée puis recrée avec TRUNCATE

après quelques recherche j'ai trouvé entre autres ce post qui pourrait expliquer l'erreur sur certaines versions de mysql

il semble que ce soit une histoire d'index non "activés" à la recréation qui suit le TRUNCATE, ceci quand ces index ne sont pas PRIMARY ou UNIQUE

donc le MATCH qui nécessite un index ne fonctionne plus

la solution serait à priori de modifier tes index, car les réactiver avec ANALYSE ou OPTIMIZE TABLE tout de suite après le TRUNCATE ne fonctionnera sans doute pas ("table already up to date...") et le faire après l'insertion de toute les données prendra plus de temps (après un premier enregistrement ça devrait toutefois fonctionner)

là aussi c'est à tester...

il y a aussi la solution d'upgrader mysql

Pourtant, un coup de "Réparer les table" dans PhpMyAdmin et c'est reparti...

Savez-vous pourquoi ? Existerait-il une solution plus fiable (en intervenant que sur le script d'import) ?

cf au dessus, la commande utilisée par le "Réparer les table" de PhpMyAdmin reconstruit les index entre-autres

A+

Nsg

Posté

Intéressant ... Et du coup quand on sauvegarde sa base de données via phpMyadmin ça fait le même effet que le TRUNCATE (suppression du FULLTEXT) ?

Veuillez vous connecter pour commenter

Vous pourrez laisser un commentaire après vous êtes connecté.



Connectez-vous maintenant
×
×
  • Créer...