J'ai quelques doublons dans une base de données que je veux inspecter, alors ce que j'ai fait pour voir lesquels sont des doublons, je l'ai fait:
SELECT relevant_field
FROM some_table
GROUP BY relevant_field
HAVING COUNT(*) > 1
De cette façon, j'obtiendrai toutes les lignes avec relevant_field se produisant plus d'une fois. Cette requête prend quelques millisecondes pour s'exécuter.
Maintenant, je voulais inspecter chacun des doublons, donc j'ai pensé que je pourrais SELECT chaque ligne dans some_table avec un relevant_field dans la requête ci-dessus, donc j'ai fait comme ceci:
SELECT *
FROM some_table
WHERE relevant_field IN
(
SELECT relevant_field
FROM some_table
GROUP BY relevant_field
HAVING COUNT(*) > 1
)
Cela s'avère extrêmement lent pour une raison quelconque (cela prend quelques minutes). Que se passe-t-il exactement ici pour le rendre aussi lent? relevant_field est indexé.
Finalement, j'ai essayé de créer une vue "temp_view" à partir de la première requête (SELECT relevant_field FROM some_table GROUP BY relevant_field HAVING COUNT(*) > 1)
, puis de créer ma deuxième requête comme ceci à la place:
SELECT *
FROM some_table
WHERE relevant_field IN
(
SELECT relevant_field
FROM temp_view
)
Et cela fonctionne très bien. MySQL le fait en quelques millisecondes.
Y a-t-il des experts SQL ici qui peuvent expliquer ce qui se passe?
Réponses:
Réécrivez la requête dans ce
Je pense que
st2.relevant_field
doit être dans le select, car sinon lahaving
clause donnera une erreur, mais je ne suis pas sûr à 100%Ne jamais utiliser
IN
avec une sous-requête; c'est notoirement lent.Ne jamais utiliser
IN
qu'avec une liste fixe de valeurs.Plus de conseils
SELECT *
uniquement les champs dont vous avez vraiment besoin.relevant_field
pour accélérer l'équi-jointure.group by
sur la clé primaire.Solution générale pour 90% de vos
IN (select
requêtesUtilisez ce code
la source
HAVING COUNT(*) > 1
. C'est généralement plus rapide dans MySQL.st2.relevant_field
n'est pas le casNULL
(c'est déjà inclus dans laON
clause), cela ne modifiera pas le résultat.afield
ce ne sera jamais le casnull
. Mercigroup by
est surst1.id
, passt1.relevant_field
.La sous-requête est exécutée pour chaque ligne car il s'agit d'une requête corrélée. On peut transformer une requête corrélée en une requête non corrélée en sélectionnant tout dans la sous-requête, comme ceci:
La requête finale ressemblerait à ceci:
la source
SELECT *
emballage est nécessaire.Sous-requêtes vs jointures
http://www.scribd.com/doc/2546837/New-Subquery-Optimizations-In-MySQL-6
la source
J'ai essayé votre requête sur l'une de mes bases de données et l'ai également réécrite en tant que jointure à une sous-requête.
Cela a fonctionné beaucoup plus rapidement, essayez-le!
la source
Essaye ça
la source
J'ai reformaté votre requête SQL lente avec www.prettysql.net
Lorsque vous utilisez une table à la fois dans la requête et la sous-requête, vous devez toujours aliaser les deux, comme ceci:
Est ce que ça aide?
la source
Tout d'abord, vous pouvez trouver des lignes en double et trouver le nombre de lignes utilisé combien de fois et le classer par numéro comme ceci;
après cela, créez une table et insérez-y le résultat.
Enfin, supprimez les lignes en double. Non est le début 0. À l'exception du premier numéro de chaque groupe, supprimez toutes les lignes en double.
la source
parfois, lorsque les données grossissent, mysql WHERE IN peut être assez lent à cause de l'optimisation des requêtes. Essayez d'utiliser STRAIGHT_JOIN pour dire à mysql d'exécuter la requête telle quelle, par exemple
mais attention: dans la plupart des cas, l'optimiseur mysql fonctionne plutôt bien, donc je recommanderais de ne l'utiliser que lorsque vous avez ce genre de problème
la source
C'est similaire à mon cas, où j'ai une table nommée
tabel_buku_besar
. Ce dont j'ai besoin c'estVous cherchez pour l' enregistrement qui ont
account_code='101.100'
entabel_buku_besar
qui ontcompanyarea='20000'
et aussiIDR
commecurrency
J'ai besoin d'obtenir tous les enregistrements
tabel_buku_besar
dont le code_compte est identique à l'étape 1 mais qui a le résultattransaction_number
de l'étape 1lors de l'utilisation
select ... from...where....transaction_number in (select transaction_number from ....)
, ma requête s'exécute extrêmement lentement et entraîne parfois l'expiration de la requête ou empêche mon application de répondre ...J'essaye cette combinaison et le résultat ... pas mal ...
la source
Je trouve que c'est le plus efficace pour trouver si une valeur existe, la logique peut facilement être inversée pour trouver si une valeur n'existe pas (c'est-à-dire IS NULL);
* Remplacez relevant_field par le nom de la valeur dont vous souhaitez vérifier l'existence dans votre table
* Remplacez primaryKey par le nom de la colonne de clé primaire sur la table de comparaison.
la source