L'importation de 50K+ Enregistrements dans MySQL Donne erreur Générale: 1390 instruction Préparée contient trop d'espaces réservés
Quelqu'un a déjà rencontré ce message d'erreur: erreur Générale: 1390 instruction Préparée contient trop d'espaces réservés
J'ai juste fait un import via SequelPro de plus de 50 000 enregistrements et maintenant, quand je vais à la consultation de ces dossiers, à mon avis (Laravel 4) - je obtenir de l'erreur: 1390 instruction Préparée contient trop d'espaces réservés.
Ci-dessous la méthode index() dans mon AdminNotesController.php fichier est quelle est la génération de la requête et le rendu de la vue.
public function index()
{
$created_at_value = Input::get('created_at_value');
$note_types_value = Input::get('note_types_value');
$contact_names_value = Input::get('contact_names_value');
$user_names_value = Input::get('user_names_value');
$account_managers_value = Input::get('account_managers_value');
if (is_null($created_at_value)) $created_at_value = DB::table('notes')->lists('created_at');
if (is_null($note_types_value)) $note_types_value = DB::table('note_types')->lists('type');
if (is_null($contact_names_value)) $contact_names_value = DB::table('contacts')->select(DB::raw('CONCAT(first_name," ",last_name) as cname'))->lists('cname');
if (is_null($user_names_value)) $user_names_value = DB::table('users')->select(DB::raw('CONCAT(first_name," ",last_name) as uname'))->lists('uname');
// In the view, there is a dropdown box, that allows the user to select the amount of records to show per page. Retrieve that value or set a default.
$perPage = Input::get('perPage', 10);
// This code retrieves the order from the session that has been selected by the user by clicking on a table column title. The value is placed in the session via the getOrder() method and is used later in the Eloquent query and joins.
$order = Session::get('account.order', 'company_name.asc');
$order = explode('.', $order);
$notes_query = Note::leftJoin('note_types', 'note_types.id', '=', 'notes.note_type_id')
->leftJoin('users', 'users.id', '=', 'notes.user_id')
->leftJoin('contacts', 'contacts.id', '=', 'notes.contact_id')
->orderBy($order[0], $order[1])
->select(array('notes.*', DB::raw('notes.id as nid')));
if (!empty($created_at_value)) $notes_query = $notes_query->whereIn('notes.created_at', $created_at_value);
$notes = $notes_query->whereIn('note_types.type', $note_types_value)
->whereIn(DB::raw('CONCAT(contacts.first_name," ",contacts.last_name)'), $contact_names_value)
->whereIn(DB::raw('CONCAT(users.first_name," ",users.last_name)'), $user_names_value)
->paginate($perPage)->appends(array('created_at_value' => Input::get('created_at_value'), 'note_types_value' => Input::get('note_types_value'), 'contact_names_value' => Input::get('contact_names_value'), 'user_names_value' => Input::get('user_names_value')));
$notes_trash = Note::onlyTrashed()
->leftJoin('note_types', 'note_types.id', '=', 'notes.note_type_id')
->leftJoin('users', 'users.id', '=', 'notes.user_id')
->leftJoin('contacts', 'contacts.id', '=', 'notes.contact_id')
->orderBy($order[0], $order[1])
->select(array('notes.*', DB::raw('notes.id as nid')))
->get();
$this->layout->content = View::make('admin.notes.index', array(
'notes' => $notes,
'created_at' => DB::table('notes')->lists('created_at', 'created_at'),
'note_types' => DB::table('note_types')->lists('type', 'type'),
'contacts' => DB::table('contacts')->select(DB::raw('CONCAT(first_name," ",last_name) as cname'))->lists('cname', 'cname'),
'accounts' => Account::lists('company_name', 'company_name'),
'users' => DB::table('users')->select(DB::raw('CONCAT(first_name," ",last_name) as uname'))->lists('uname', 'uname'),
'notes_trash' => $notes_trash,
'perPage' => $perPage
));
}
Tout conseil serait apprécié. Merci.
- Si vous importez permet de dire que 100 enregistrements. Il fonctionne ok?
- en fonction de l'erreur (je ne vais même pas essayer de regarder cette ÉNORME morceau de code), il semble que vous sont en train de préparer une requête avec X des espaces réservés et simplement les valeurs de Y, avec Y < X.
- Oui, il fonctionne très bien.
- Je ne suis pas sûr de ce que tu veux dire?
- si vous importez morceau sage, il fonctionne. voici un exemple simple foreach (array_chunk($data,1000) as $t) { DB::table('table-name')->insert($t); }
- Je voudrais juste importer ce que les morceaux de 500 pour être sûr.
Vous devez vous connecter pour publier un commentaire.
Il est limite 65,535 (2^16-1) les détenteurs de place dans MariaDB 5.5 qui est censé avoir le même comportement que MySQL 5.5.
Ne sais pas si pertinent, je l'ai testé sur PHP 5.5.12 utiliser MySQLi /MySQLND.
Alors que je pense que @Le Désintégrateur est correct sur les espaces réservés étant limitée. Je ne voudrais pas courir 1 requête par enregistrement.
J'ai une requête qui a bien fonctionné jusqu'à ce que je l'ajout de la colonne et maintenant, j'ai 72k des espaces réservés et j'obtiens cette erreur. Cependant, que 72k est composé de 9000 lignes avec 8 colonnes. L'exécution de cette requête 1 enregistrement à la fois prendrait des jours. (J'essaie d'importer des données d'AdWords dans une DB et il serait littéralement prendre plus de 24 heures pour importer un jours d'une valeur de données si je l'ai fait 1 enregistrement à la fois. J'ai essayé en premier.)
Ce que je recommande est quelque chose d'un hack. Tout d'abord, soit de déterminer de manière dynamique le nombre maximum d'espaces réservés que vous souhaitez autoriser à - dire 60k pour être sûr. Utilisez ce numéro pour déterminer, sur la base du nombre de colonnes, combien de dossiers complets, vous pouvez importer/retour à la fois. Créer l'ensemble de données de la requête. Utiliser un array_chunk et une boucle foreach pour saisir tout ce que vous voulez dans le minimum de nombre de requêtes. Comme ceci:
Cette erreur seulement qui se passe quand les deux les conditions suivantes sont remplies:
Si vous modifiez l'un de ces facteurs, cette erreur ne se produira pas. Cependant, gardez à l'esprit que faire les deux est recommandée, soit pour le rendement ou les problèmes de sécurité, de sorte que je ne recommande pas cette solution pour rien, mais en plus d'un temps ou temporaire problème que vous rencontrez. Pour éviter cette erreur, la solution est aussi simple que:
error: 1390 Prepared statement contains too many placeholders
disparu. Mais j'ai observé que les INSERTs de vitesse sera alors beaucoup plus lent. L'insertion de 25.000 lignes avec 7 colonnes a eu 106 Secondes. Après avoir réduit le nombre de lignes à 9200, l'Insertion a eu seulement environ. 15 secondes. En conséquence, je dirais que l'on doit garder un œil sur le nombre de substituants.À l'aide de Laravel modèle, la copie de tous 11000 enregistrements de base de données sqlite à mysql de la base de données en quelques secondes. Morceau tableau de données de 500 enregistrements:
Mon Fix pour le problème ci-dessus:
De mon côté, quand j'ai eu cette erreur je l'ai fixée par la réduction de la l'essentiel d'insertion morceau d'une taille de 1000 à 800 et il a travaillé pour moi.
En fait, il y avait trop de champs dans ma table, et la plupart d'entre eux contient les détails des descriptions de la taille comme une page complète de texte. quand je vais pour n'en vrac d'insertion le service causées s'est écrasé et par le biais de l'erreur ci-dessus.
Résolu ce problème en utilisant array_chunk fonction.
Voici la solution ci-dessous:
Je pense que le nombre de substituants est limitée à 65536 par requête (au moins dans les anciennes versions de mysql).
J'ai vraiment ne peut pas discerner ce que ce morceau de code à générer. Mais si c'est un gigantesque requête, Il y a votre problème.
Vous devez générer une requête par l'enregistrement à l'importation et les mettre dans une transaction.