Pourquoi est-MySQL 'insert into ... sélectionner de manière beaucoup plus lente d'un seul?
Je suis en train de stocker le résultat d'une requête dans une table temporaire pour un traitement ultérieur.
create temporary table tmpTest
(
a FLOAT,
b FLOAT,
c FLOAT
)
engine = memory;
insert into tmpTest
(
select a,b,c from someTable
where ...
);
Mais pour une raison que l'insert prend une minute, alors que celle-ci lui seul ne prend que quelques secondes. Pourquoi serait-il beaucoup plus de temps pour écrire les données dans une table temporaire à la place de l'impression sur mon SQL outil de gestion de sortie de la???
Mise à JOUR
Ma Configuration:
MySQL 7.3.2 Cluster avec
8 Debian Linux ndb données des nœuds
1 SQL Nœud (Windows Server 2012)
La table, je suis en cours d'exécution de la sélectionner sur un ndb table.
J'ai essayé de savoir, si le plan d'exécution serait différente lors de l'utilisation de 'insert into..', mais ils ont la même apparence:
(désolé pour la mise en forme, stackoverflow n'ont pas de tables)
id select_type type de table possible_keys clé key_len ref lignes Supplémentaires 1 PRIMAIRE <subquery3> TOUS les \N \N \N \N \N \N 1 PRIMAIRE foo ref PRIMAIRE PRIMAIRE 3 <subquery3>.fooId 9747434 à l'Aide de où 2 sous-REQUÊTE someTable gamme de PRIMAIRE de PRIMAIRE 3 \N 136933000 à l'Aide de où les à poussé l'état de santé; l'Aide de ce taux; l'Aide temporaire; à l'Aide de filesort 3 MATÉRIALISÉ tmpBar TOUS \N \N \N \N 1000 \N
CREATE TABLE ... SÉLECTIONNEZ est lent, trop. 47 secondes vs 5 secondes sans table insert/créer.
INSERT .. SELECT
syntaxe est différente. Votre exemple de s'entraîner dans l'erreur.bonne question. Je ne sais pas vraiment comment mysql réserves
memory
pour lui-même. Si elle passe par le système d'exploitation de l'api, il pourrait juste demande pour la mémoire, ce qui serait alors servi comme ram ou disque dur de l'espace, selon l'état du système. Voir windows octets virtuels de gestion.Avez-vous essayé un
CREATE TABLE ... SELECT
-type de requête pour la comparaison? dev.mysql.com/doc/refman/5.0/en/create-table-select.htmlpourquoi ne vous dire que ma syntaxe est mauvaise? Je ne reçois pas toutes les erreurs.
J'ai fait 🙁 Même résultat que INSERT INTO ... SÉLECTIONNEZ
OriginalL'auteur Ben | 2013-10-09
Vous devez vous connecter pour publier un commentaire.
J'ai écrit un commentaire ci-dessus, puis suis tombé sur ça comme une solution de contournement.
Cela permettra d'accomplir ce que vous voulez faire.
Notez que cela signifie que la gestion de l' /tmp tables d'une certaine façon. Si vous essayez de SÉLECTIONNER des données dans un OUTFILE qui existe déjà, vous obtenez un message d'erreur. Si vous avez besoin de générer unique les noms de fichiers temporaires. Et puis exécutez une tâche cron de quelque sorte pour aller nettoyer.
Je suppose que INFILE et OUTFILE se comportent différemment. Si quelqu'un peut jeter quelque lumière sur ce qui se passe ici, pour expliquer mysql comportement, je l'apprécierais.
D
Ici est un meilleur moyen que d'utiliser INFILE /OUTFILE.
SET TRANSACTION ISOLATION LEVEL LIRE COMMIS;
INSÉREZ DANS aTable
SELECT ... FROM ...
En voici un post à lire :
Comment améliorer INSERT INTO ... SÉLECTIONNEZ comportement de verrouillage
OriginalL'auteur Don Wool
J'ai vécu le même problème et a joué avec des sous-requêtes en fait résolu.
Si le select a une énorme quantité de lignes, de sa prendre très longtemps pour insérer les données.
Exemple:
l'aide de la LIMITE en combinaison pour INSÉRER des données n'est pas une bonne option. Vous pouvez utiliser 2 séparés des requêtes pour l'obtention de données et de l'insertion, ou vous pouvez utiliser une sous-requête.
Exemple:
qui serait une solution rapide sans changer votre script.
Donc je ne sais pas pourquoi sa prise de 0,01 secondes pour exécuter la sous-requête et 60 secondes pour exécuter l'insérer. Je reçois de plus de 1000 résultats sans Limite. Dans mon cas, la sous-requête amélioration du rendement de 60 secondes à 0,01 secondes.
oui, c'est vrai, mais im écrit seulement 1 ligne tout en utilisant la LIMITE de 1.
WHERE customer_name LIKE "%john%"
- c'est un full table scan. Une fois que chaque dossier est analysé et la réduction de récupérer ce qui contientjohn
. Cela prend un certain temps. Ensuite, vous écrivez 1 enregistrement. Il est inefficace.si mysql est l'écriture de toutes les données dans une table temporaire et à la fin, il reconnaît que j'ai mis une LIMITE de 1 et n'écrit que le premier enregistrement dans la table ? cela expliquerait également pourquoi mon encapsulage avec la sous-requête irait beaucoup plus vite.
Elle tamponne les enregistrements qu'il a trouvé (on peut dire qu'il écrit dans la table temporaire, oui) et ensuite, il utilise uniquement un enregistrement correct.
OriginalL'auteur joevette
La raison a à voir avec la façon dont l'ordinateur lit et écrit et de la façon dont un fichier temp œuvres. Sélectionnez lecture des données dans un fichier indexé sur le disque dur, alors que insert à l'aide d'un fichier temporaire et de l'écriture à ce fichier. Plus de RAM est nécessaire et cela est plus difficile.
Quant à savoir pourquoi ça prend une minute, je ne sais pas exactement mais je pense que le code peut être un peu incorrect de sorte que contribuerait.
wehich os?
voir ma mise à jour.
Avez-vous jamais obtenir une réponse à cela? Ou à comprendre comment améliorer les performances? J'obtiens le même comportement, où l'SÉLECTIONNEZ prend inférieure à la seconde, mais l'INSERT prend que 30 secondes. C'est complètement déroutant. Je me demande si c'est un bug? Pour contourner ce problème, j'ai essayé de créer un curseur sur les données que j'étais à choisir et INSÉRÉ une ligne à la fois et il était plus rapide. Ce qui est fou. Je vais essayer une question similaire à la vôtre, mais il semble qu'il n'y a pas de réponse à cela.
OriginalL'auteur Ben Cartwright