web-dev-qa-db-fra.com

Insertion de grandes quantités de données dans une table personnalisée lors de l'installation du plugin

Je travaille sur un plugin WordPress qui crée plusieurs nouvelles tables dans la base de données. Il charge également certaines données par défaut dans les tables à partir de fichiers CSV. La plupart d'entre elles sont petites et le chargement des données fonctionne bien. L’une, cependant, est une base de données de codes postaux censée être chargée avec un peu plus de 43 000 lignes de données.

La première fois, j’ai essayé de faire exactement ce que j’avais fait pour les tables contenant beaucoup moins de données à insérer. WordPress a répondu par "Le plugin n'a pas pu être activé car il a provoqué une erreur fatale." Après avoir consulté la base de données, j’ai constaté qu’elle dépassait un peu plus de 1 000 codes Zip avant de s’arrêter. J'ai donc pris les 1 500 premières lignes de ce fichier CSV et les ai divisées en 2 fichiers CSV (750 lignes chacun). J'ai utilisé le code ci-dessous pour lire en boucle le chargement des deux fichiers CSV afin de vérifier si je pouvais le faire avec une solution incroyablement lente, mais au moins une solution qui aurait fonctionné. Il s’est avéré qu’il n’était encore capable de lire que 1099 codes Zip avant de s’arrêter.

Est-ce que quelqu'un a une solution pour insérer de très grandes quantités de données dans une table à partir d'un plugin WordPress? Merci d'avance à tous ceux qui essaient de m'aider ici.

Voici un exemple de ligne tirée du fichier CSV zips:

%1%;%00544%;%NY%;%HOLTSVILLE%;%-73.047623%;%40.813296%;%0%

Voici la fonction create table:

function Zip_table_create() {

global $wpdb;
$table_name = $wpdb->prefix . "Zip";

$sql = "CREATE TABLE $table_name (
     `Zip_id` bigint(20) NOT NULL AUTO_INCREMENT,
     `Zip` char(5) DEFAULT NULL,
     `state` char(2) NOT NULL DEFAULT '',
     `name` char(40) DEFAULT NULL,
     `lng` double NOT NULL DEFAULT '0',
     `lat` double NOT NULL DEFAULT '0',
     `population` int(10) unsigned NOT NULL DEFAULT '0',
     PRIMARY KEY (`Zip_id`)
     );";

dbDelta($sql);

// Check to see if any records are stored in table
// If not, load default data from CSV
$Zip = $wpdb->get_row("SELECT * FROM $table_name WHERE Zip_id = 1");
if ($Zip == null) {
    for ($z=1; $z<3; $z++)
    {
        $csvpath = plugin_dir_path(__FILE__);
        $csvpath = $csvpath."csv/zips".$z.".csv";

        $csv_array = csv2array($csvpath, ";", "%");

        for ($x=0; $x < count($csv_array); $x++) {
            $wpdb->insert( 
                $table_name, 
                array(  
                    'Zip_id' => $csv_array[$x][0],
                    'Zip' => $csv_array[$x][1],
                    'state' => $csv_array[$x][2],
                    'name' => $csv_array[$x][3],
                    'lng' => $csv_array[$x][4],
                    'lat' => $csv_array[$x][5],
                    'population' => $csv_array[$x][6]
                )
            );
        }
    }
}

}

Voici la fonction csv2array appelée dans la fonction create:

function csv2array($file, $delimiter, $Enclosure) {
if (($handle = fopen($file, "r")) !== FALSE) { 
    $i = 0; 
    while (($lineArray = fgetcsv($handle, 4000, $delimiter, $Enclosure)) !== FALSE) { 
        for ($j=0; $j<count($lineArray); $j++) { 
        $data2DArray[$i][$j] = $lineArray[$j]; 
        } 
        $i++; 
    } 
    fclose($handle); 
} 
return $data2DArray;
}
1
Brett Clapper

J'ai quelques suggestions pour vous:

  • 1, créez vous-même des requêtes d'insertion MySQL.
  • 2, combinez plusieurs insérez des requêtes de valeurs dans une même valeur (1,2,3), (4,5,6)
  • 3, utilisez $wpdb->query puis

vous devez déterminer le nombre approprié de " multiples ".

J'ai essayé avec 100 et cela a fonctionné pour moi, mais je pense que le nombre varie en fonction des paramètres du serveur.

2
Jesse

Une autre suggestion est d'étendre la limite de temps d'exécution php dans le script. comme utiliser:

set_time_limit($seconds);

Où $ secondes est la durée pendant laquelle le script doit être exécuté.

1
Dominic Yun