Nombre d’éléments MySQL dans la clause «in clause»

J’ai trois tables pour définir les utilisateurs:

USER: user_id (int), username (varchar) USER_METADATA_FIELD: user_metadata_field_id (int), field_name (varchar) USER_METADATA: user_metadata_field_id (int), user_id (int), field_value (varchar) 

Je voudrais créer un utilisateur de niveau intermédiaire ayant un access certain aux autres utilisateurs de l’application. Pour déterminer à quels utilisateurs l’utilisateur connecté peut accéder, j’utilise une sous-requête comme celle-ci:

 SELECT user_id FROM user WHERE user_id IN (SELECT user_id FROM user_metadata WHERE user_metadata_field_id = 1 AND field_value = 'foo') 

Actuellement, je stocke la chaîne de sous-requête dans une variable, puis l’insère dynamicment dans la requête externe chaque fois que je dois extraire une liste d’utilisateurs. Après avoir fait cela, j’ai pensé: “il faut mieux stocker simplement une chaîne du user_id s”.

Donc, au lieu de le stocker dans une variable …

 $subSql = "SELECT user_id FROM user_metadata WHERE user_metadata_field_id = 1 AND field_value = 'foo'"; 

… J’effectue effectivement la requête et stocke le résultat comme ceci …

 $subSql = "12, 56, 89, 100, 1234, 890"; 

Ensuite, lorsque je dois extraire une liste d’utilisateurs auxquels l’utilisateur connecté a access, je peux le faire avec:

 $sql = "SELECT user_id FROM user WHERE user_id IN ($subSql)"; 

Et enfin les questions:

Combien d’articles pouvez-vous utiliser dans MySQL IN CLAUSE? Stocker les identifiants réels au lieu de l’instruction sub-sql doit être plus rapide pour effectuer cette requête externe à chaque fois, non?

À partir d’un certain nombre, les tables IN sont plus rapides.

MySQL a quelque chose à l’intérieur de son code qui rend la construction d’une plage sur un grand nombre de valeurs constantes plus lente que de faire la même chose dans une boucle nestede.

Voir cet article sur mon blog pour plus de détails sur les performances:

  • Passage des parameters dans MySQL: liste IN vs table temporaire

A partir du manuel :

Le nombre de valeurs dans la liste IN est uniquement limité par la valeur max_allowed_packet .

Comme indiqué dans la réponse de Quassnoi, on tombe sur d’autres considérations pratiques, avant d’ atteindre une limite éventuelle imposée par l’implémentation d’une version MySql donnée (*). Par conséquent, à mesure que le nombre d’utilisateurs admin (ou d’autres critères pouvant nécessiter une construction IN) augmente, il convient de chercher des alternatives à un “IN” littéral, comme l’utilisation de tables temporaires (voire permanentes).

Étant donné que vous envisagez un traitement spécial des critères “administrateur”, à des fins de performances, je souhaiterais proposer un commentaire et une suggestion.

Commentaire: S’agit-il d’une optimisation prématurée?
Je ne suis pas au courant des spécificités de cette firebase database, de son volume, de sa complexité, etc. Et, oui, je suis au courant de l’hommage aux performances au format EAV (Entity-Atsortingbute-Value), mais je pense que Même pour les entresockets prospères, la firebase database compte rarement plus de 10 000 utilisateurs. Donc, même avec de très nombreux atsortingbuts par utilisateur, nous examinons toujours une table EAV relativement petite, qui peut ne pas nécessiter ce type d’optimisation. (D’autre part, quelques autres astuces d’optimisation peuvent être les bienvenues dans d’autres domaines).
De plus, les cas d’utilisation typiques impliquent un nombre relativement faible de requêtes dans la firebase database du compte, par rapport à d’autres requêtes, ce qui constitue une autre raison de reporter toute considération de performances non sortingviale pour les fonctionnalités de l’application liées aux comptes.

Suggestion: Peut être utiliser des “atsortingbuts normalisés”
Pour les atsortingbuts à valeur unique, et en particulier s’ils sont courts, ils peuvent être déplacés (ou dupliqués) dans la table Entity (tableau ‘USER’ dans ce cas). Cela introduit un peu de logique au moment de l’insertion ou de la mise à jour des éléments, mais cela crée de nombreuses jointures (ou sous-requêtes) et offre la possibilité de prendre en compte les index multi-champs pour prendre en charge les cas d’utilisation les plus courants.

(*) Y a-t-il une boue?
Je n’ai pas lu sur une telle limite; Je sais qu’Oracle a (avait) une limite de 1.000 à un moment donné, MSSQL ne le fait pas; Bien sûr, tous les serveurs ont une limite basée sur la longueur totale de l’instruction SQL, mais c’est vraiment un grand nombre! si quelqu’un tombe sur celui-là, il / elle a d’autres problèmes … 😉

La clause IN de MySQL n’a pas cette limite. J’ai essayé avec 8000 éléments son travail bien pour moi. L’erreur de dépassement de stack peut être de variable déclarée,