Question simple. Vous vous demandez si une longue clause est une odeur de code? Je ne sais pas vraiment comment le justifier. Je ne peux pas mettre mon doigt pourquoi ça sent l'impression que je pense que ça fait. Comment une base de données implique-t-elle une telle recherche? Une table temporaire est-elle faite et rejointe? Ou est-il juste élargi dans une série d'ours logiques? P> On a l'impression d'avoir été une jointure ... P> Je ne dis pas que tous les clauses sont mauvaises. Parfois, vous ne pouvez pas l'aider. Mais il y a quelques cas (en particulier les plus longues qu'ils obtiennent) où l'ensemble d'éléments que vous correspondez contre est en fait de quelque part. Et ne devrait-il pas être joint à la place? P> vaut-il la peine de créer (via le niveau d'application) une table temporaire qui dispose de tous les éléments que vous souhaitez rechercher, puis de faire une vraie joindre contre cela? < / p>
5 Réponses :
Je pense que c'est une odeur de code. D'une part, des bases de données ont des limites quant au nombre d'éléments autorisés dans une clause Lorsque la liste commence à devenir longue-ish, je convertitais à l'aide d'une procédure stockée avec une table temporaire, afin d'éviter toute chance d'erreurs. P>
Je doute que la performance est une préoccupation majeure, dans code> et si votre SQL est généré de manière dynamique, vous risquez de résoudre ces limites. P>
dans code> est très rapide, car ils peuvent être court-circuit, contrairement à pas dans code> clauses. P>
+1. Récemment, j'ai récemment pris des travaux de maintenance pour une application existante (écrite par quelqu'un d'autre) qui a utilisé la clause dans l'exclusion d'adresses électroniques (par la chaîne de concaténation.) Le problème est que l'application était maintenant migrée vers une base de données avec plus de 20 millions d'enregistrements. et peut-être des millions à exclure. Je ne pouvais pas croire qu'il a été conçu de cette façon, même pour la base de données de tests d'origine. J'aime le dans (
"Je serais converti pour utiliser une procédure stockée avec une table temporaire" - supposer que la procédure stockée proposée est permanente, pourquoi ne pas utiliser également une table de base permanente?
@EnedayLorsque mon hypothèse est que les données ne sont utilisées qu'une fois pour cette requête, il n'ya donc aucun point de stocker de manière permanente.
@Redfilter: La façon dont je le vois, si la table doit exister chaque fois que la procédure est appelée, il ne reste plus de point de laisser tomber la table à moins que le procureur lui-même ne soit abandonné ... ou y a-t-il quelque chose que je ne vois pas?
Cela vaut-il la peine de créer (via le niveau d'application) une table temporaire. p> blockQuote>
Le problème avec
dans code> est qu'il n'utilise pas d'index et de la comparaison (pire des cas: x14 ici) em> est répété pour chaque rangée de votre table source. p>Création d'une table Temp est une bonne idée, si vous mettez un index sur les champs de jointure.
De cette façon, la requête peut rechercher la valeur directement, à l'aide d'un indice BTREE qui ne doit prendre que 3 ou 4 comparaisons pires cas log2 (14) = 3.Quelque chose de
Qui est beaucoup plus rapide. P>Si vous êtes intelligent, vous pouvez même utiliser un index de hachage code> auquel cas, le dB ne doit faire que 1 comparaison, vitesse de votre requête en hausse de 3 fois à l'index BTRee. P >
Conseils pour utiliser une table Temp forte>
Assurez-vous d'utiliser une table mémoire
Utilisez unindex de hachage code> comme clé primaire.
Essayez de faire les insertions dans une déclaration. p>Le temps semi-constant que vous passerez de la création de la table Temp-Table sera nain par le speedUp en raison de l'heure de la recherche O (1) à l'aide de l'index de hachage. P>
Ce genre de réglage n'est pas si général, cependant. N'oubliez pas que vous devez rendre compte du temps nécessaire pour construire la table TEMP et son index. Pour une question d'une table sur une table avec une petite rangée compte, il est préférable de simplement le laisser faire la force brute comparaison de la clause in. Pour les requêtes répétées avec la même clause de la clause ou pour de très grand rangs de rangée, il est préférable de créer la table et l'index temporaire. Il est préférable de se familiariser avec le planificateur de requête pour pouvoir peser ces choses vous-même.
@Ben Burns, si votre table Temp a 10 rangées et votre comparaison avec un million de rangées, la vitesse maximale sera suffisante pour justifier l'accumulation même si vous ne l'utilisez qu'une seule fois. Essaye le. Je pense que si vous comparez contre une table de 1 000 rangées, il sera toujours plus rapide de faire la table Temp.
@Ben, bon point, profilez toujours de vos solutions et essayez de sortir des choses, ne présumez jamais.
Nous disons la même chose, Johan. Je suppose que le seuil est supérieur à 1k lignes, mais c'est une sorte de profilage du point - W / O et une compréhension de la croissance des données, c'est juste une supposition.
Je ne sais pas que c'est une odeur de code, exactement. Parfois, vous avez juste une longue liste de choses comme pour effectuer une table Temp (ou même une table de recherche) avec les éléments et joindre contre (ou même faire un *: "Si et seulement si" p> dans code> que votre condition pourrait exister. P>
où [colonne] dans (Sélectionnez [Lookuptable] à partir de [lookuptable]) code> est Une de mes méthodes préférées IFF * A) Il existe un grand nombre de valeurs que b) changera rarement si jamais. P>
Vous pouvez également utiliser une sous-requête avec, comme décrit ici dans le manuel .
SELECT * FROM us_states WHERE code IN (SELECT code FROM state_codes);
-1 in (sélectionnez x à partir de y) code> est notoirement lent sur MySQL et peut simplement être remplacé par une jointure interne: joint interne STATE_CODES SC ON (SC.CODE = US_STATES.CODE) code> qui est beaucoup plus rapide dans mysql.
@Johan n'est-il pas la faute de MySQL pour ne pas pouvoir transformer le sous-sélection en une jointure équivalente?
Je pense aussi que c'est une "odeur". Un clause Selon les normes SQL, votre Je m'attendrais à ce qu'un analyseur typique étendait une clause code> code> de cette manière; Je sais que SQL Server fait parce que les clauses Nice et NEAT Il existe une règle de conception qui stipule que si l'ensemble des valeurs est faible et stable, utilisez une clause dans code> peut, à un observateur occasionnel, ressembler à un ensemble, liste, sac, table, etc. mais n'est pas. dans code > La clause est simplement sucre syntaxique pour p> dans CODE> ITILISE ITILISE pour créer certains Vérifier CODE> Les contraintes deviennent un ensemble laid de ou code> des clauses lorsque j'examine La définition de la contrainte dans l'information_schema. YMMV: Si vous êtes préoccupé par la performance, le test. P> dans code>, Sinon, utilisez une table. Que 14 sur 52 soit «petit» est subjectif. Si une petite table est la meilleure indexée peut dépendre de la manière dont elle est jointe à d'autres tables: Cette question de questions peut être une référence utile . p> p>
Que ce soit ou non dans code> est une odeur de code, c'est un argument terrible. Vous dictez fondamentalement "la norme dicte que ces deux syntaxes sont équivalentes, et l'une d'entre elles a l'air laide, nous devrions donc considérer l'autre laid et ne pas l'utiliser!" Cela ne peut pas avoir de sens parce que c'est un argument pleinement général que tout code est mauvais; La même logique pourrait être appliquée pour condamner à peu près tout élément de code jamais écrit dans n'importe quelle langue. Je ne vois pas comment l'équivalence (évidente) de x dans (a, b, c) code> et x = a ou x = b ou x = c code> a une pertinence À la question.
En disant «laid», je me suis plié sur SQL Server réécrit mon code et d'accord, il était hors de propos, donc je l'ai supprimé. Voyez-vous où je dis: "Simple Syntaxtic Sugar"? C'est censé vous dire que je ne pense pas qu'il est important si vous utilisez dans code> ou la forme normale disjonctive équivalente.
Après l'édition, je ne suis toujours pas un fan de cette réponse. Vous élevez l'équivalence ou x dans (A, B, C) CODE> au formulaire x = A ou X = B ou x = C code>, mais ma réponse est de demander ... Alors? I> Vous semblez avoir à obtenir quelque chose de performance, mais je ne comprends pas comment réécrit la clause comme x = a ou x = b ou x = c code> nous donne une idée de la performance. Vous mentionnez que les observateurs occasionnels pourraient percevoir des clauses comme étant comme des ensembles, mais encore une fois ... SO I>? Quelles mauvaises inférences sur la performance pourraient-elles donc dessiner? Je me sens comme si tu n'avais pas assez ttilisé tes pensées pour que je les comprends.
"Comment une base de données implique-t-elle généralement une telle recherche? ... Est-ce juste élargi dans une série d'ours logiques?"
Mais le fait que la norme dicte que x dans (a, b, c) code> et x = a ou x = b ou x = c code> équivalent nous ne nous dit rien du tout sur la façon dont la base de données implémente la recherche. Le moteur est libre de les exécuter de la même manière ou différemment, et libre de créer des tables temporaires pour les deux, à la fois ou non si elle le souhaite. Cette citation de la question est clairement la possibilité de rechercher des informations relatives à la performance sur la manière dont la recherche est mise en œuvre i> et l'équivalence à x = a ou x = b ou x = c code > est sans rapport avec ça.
@Markamery: Je ne suis pas d'accord sur le fait que l'OP recherche des informations relatives à la performance. Je pense qu'ils demandent à un point de vue de la programmation. Écrire in (valeurs) code> vs mettez ces valeurs dans une table et écrire un joindre code>. Je vous suggère d'écrire votre propre réponse liée à la performance, peut-être avec quelques preuves de synchronisation et voir si cela obtient des votes (peut-être de moi!). Si vous vous sentez fortement sur ma réponse, n'hésitez pas à la descendre.
Si vous voulez savoir comment votre base de données i> effectue ces questions, utilisez Expliquer pour obtenir une sortie sur l'exécution de la requête. dev.mysql.com/doc/refman/5.1/fr/ en utilisant-expliquer.html