J'ai une table mysql qui ressemble à ceci:
P>
La SQL pour créer la structure est la suivante: p> Il stocke un ID code> unique code>, J'ai une URL pour correspondre à chaque Le script fait cette requête sur le statut code> Tableau: P> où Quoi qu'il en soit, tout ce qui est Bien, mais ce que je veux faire, c'est peupler la table à l'avance avec dire une série comme celle-ci: p> avis, seul l'ID est incrémenté, mais ce n'est pas nécessairement Commencez à 1 pour mes besoins. Je veux que la table pré-peuplée comme ceci, car alors la requête ci-dessus peut continuer à saisir J'ai essayé d'utiliser Java, (bien que Php, c # ou quoi que ce soit le même concept et que je ne compte pas pour moi quelle langue j'utilise ici): p> Ceci commence les inserts, mais le problème est que Il faut une quantité de temps extraordinaire pour peupler la table (je n'ai pas de temps exact, mais c'était couru pendant des heures). Donc, ma question se résume à: Y a-t-il un moyen simple et efficace de remplir une table MySQL avec une masse de rangées comme celle-ci? P> p> Respectecode code>, et < Code> LastUpdate code>. Le responsable code> est un code de réponse HTTP: 404, 500, 503, 200, etc. p> ID code> pour Ce que je fais une demande HTTP et enregistrer dans ce tableau l'heure que j'ai apportée la demande et la réponse reçue. p> xxxx code> serait une date où je décide que quelque chose de plus âgé que cette date ne doit être rafraîchie quel que soit le code de réponse. En outre, je souhaite remédier à la demande HTTP si je n'ai pas reçu de 200 code> ou 404 code> quel que soit le dernier lastUpdate code> date. I limite code> à 100 parce que je ne fonctionne que 100 à la fois, puis je l'ai dormi pendant un certain temps et que je le fais plus 100 plus tard, et ainsi de suite. P> ID code> est pour ceux que nous devons être recouverts, et je voudrais ne pas avoir à insérer quelque chose de plus dans la Status CODE> TABLE AS L'ID CODE> S est fini et ne changera pas (mais il y en a beaucoup). P>
4 Réponses :
Vous créez une grande déclaration par lots à effectuer. Essayez de le diviser en petits paquets en utilisant, par exemple. Appelez ExecuteBatch () Tous les 1000 incréments de I (à l'aide de MOD (I) Yaddayadda) à l'intérieur de la boucle. Cela devrait accélérer le processus:
J'ai remarqué que l'exécution du lot (comme dans ma question) remplit toujours la table activement (par exemple, je peux regarder le remplissage de DB) comme votre extrait ici. Cependant, je n'aiffectueusement aucune différence majeure dans la performance des inserts.
Que diriez-vous de paramètres Ensuite, insérez les centaines de cent (ou mille) de la manière dont vous aimez (votre exemple ou l'exemple de Docjones vous a donné). P > Ensuite, utilisez P> auto_incrènement code> sur la clé primaire. INSERT INTO table SELECT NULL, '503', NOW() FROM table AS t1 CROSS JOIN table t2;
Je pense que cette idée est vraiment désireuse. Je vais essayer cela.
Attention avec le croix rejoindre code> Vous pouvez entrer 10 valeurs manuellement puis exécuter croix jointure code> et obtenir 10 + 10 ^ 2 = 110, puis vous répéterez la joindre CODE> et POOF Vous avez 110 + 110 ^ 2 = 12.210, à la troisième répétition, vous avez déjà 149 096 310 - cent quarante neuf millions d'entrées B>, qui chowleront sur certains Disk-io - et prenez le temps d'écrire un peu de temps.
En règle générale, vous pouvez utiliser un ou plusieurs des éléments suivants:
insérer dans ... Sélectionnez CODE> si approprié li>
ul> la première (utiliser des transactions) est le plus susceptible d'aider, mais je ne suis pas sûr que cela fonctionne sur des tables myisam, avec Innodb, il fait un très bon travail - je n'utilise que ceux quand je suis forcé Pour utiliser MySQL, je préfère PostgreSQL. P>
Dans votre cas spécifique, insérez 100 000 lignes de données, vous pouvez effectuer les éléments suivants: P>
Query OK, 100000 rows affected (0.70 sec)
Records: 100000 Duplicates: 0 Warnings: 0
Si vous exécutez de nombreuses instructions inserves, le regrouper dans des transactions empêche la DB de l'écriture sur le disque après chacune, elle garantit qu'ils se sont engagés à être déterminés à la fois à la fin de la transaction.
Cela semble assez rapide, pouvez-vous expliquer brièvement ce qui se passe dans cette requête?
Je crée des numéros consécutifs, en joignant 5 tables contenant 0 à 9, puis sélectionnez le numéro, la constante, la constante ... ce qui est très rapide ... puis insérez toutes les entrées 100 000 dans une seule transaction puisqu'il s'agit d'une seule requête.
Oh, pourriez-vous s'il vous plaît cocher la réponse car cela fonctionne et je ne pense pas que cela puisse être fait plus vite que cela (du moins pas dans MySQL), cependant, si quelqu'un propose une solution plus rapide plus tard, vous pouvez simplement marquer cela comme le bonne réponse à la place.
@ user17753 J'ai écrit un équivalent postgreSQL pour cette énorme sélection, espérons-le, il sera plus facile de comprendre ce que je faisais sqlfiddle.com/#!1/d41d8/501 ... Je l'ai écrit seulement jusqu'à 20 000 au lieu de 100 000 parce que je ne voulais pas trop surcharger les serveurs Sqlfiddle trop
Solution parfaite pour dupliquer les lignes lorsque les données sont exactement les mêmes. Avant que l'insert ne prend 20s chaque 10000 rangées. Maintenant 1s. Vraiment parfait.
Tout simplement génial ;)
solution PHP pour les charger par lots de 100:
for ($i = 0; $i < 100000; $i+=100) {
$vals = implode(', ',
array_map(function($j) { return "($j, default, default)";},
range($i, $i+100)));
mysqli_query($dbh, 'insert into status values ' . $vals) or die mysqli_error($dbh);
}
Ajout d'une solution pure SQL à ma réponse, faites-moi savoir si vous trouvez quelque chose plus rapide.
Dupliqué possible de Comment insérer 20 millions d'enregistrements dans la base de données MySQL aussi vite que possible .