mysql - votre - toutes les balises php pdf




Performances de l'opérateur MySQL «IN» sur(grand?) Nombre de valeurs (4)

J'ai expérimenté avec Redis et MongoDB dernièrement et il semblerait qu'il y ait souvent des cas où vous stockeriez un tableau d' id dans MongoDB ou Redis. Je vais rester avec Redis pour cette question car je parle de l'opérateur MySQL IN .

Je me demandais comment il était performant de lister un grand nombre (300-3000) d' id dans l'opérateur IN, ce qui ressemblerait à ceci:

SELECT id, name, price
FROM products
WHERE id IN (1, 2, 3, 4, ...... 3000)

Imaginez quelque chose d'aussi simple qu'une table de produits et de catégories que vous pourriez normalement rejoindre pour obtenir les produits d'une certaine catégorie . Dans l'exemple ci-dessus, vous pouvez voir cela dans une catégorie donnée dans Redis ( category:4:product_ids ) Je retourne tous les identifiants de produit de la catégorie avec l'ID 4 et les place dans la requête SELECT ci-dessus dans l'opérateur IN .

Est-ce que c'est performant?

Est-ce une situation "ça dépend"? Ou y a-t-il un "ceci est (un) acceptable" ou "rapide" ou "lent" concret ou devrais-je ajouter un LIMIT 25 , ou cela n'aide-t-il pas?

SELECT id, name, price
FROM products
WHERE id IN (1, 2, 3, 4, ...... 3000)
LIMIT 25

Ou devrais-je réduire le tableau des identifiants de produit renvoyés par Redis pour le limiter à 25 et ajouter seulement 25 ID à la requête plutôt que 3000 et LIMIT it à 25 à partir de la requête?

SELECT id, name, price
FROM products
WHERE id IN (1, 2, 3, 4, ...... 25)

Toutes les suggestions / commentaires sont très appréciés!


En règle générale, si la liste IN devient trop grande (pour une valeur mal définie de «trop grand» qui est généralement de l'ordre de 100 ou moins), il devient plus efficace d'utiliser une jointure, créant une table temporaire si nécessaire. être à tenir les chiffres.

Si les nombres sont un ensemble dense (pas de lacunes - ce que l’échantillon suggère de données), alors vous pouvez faire encore mieux avec WHERE id BETWEEN 300 AND 3000 . Cependant, il y a probablement des lacunes dans l'ensemble, à ce stade, il peut être préférable d'aller avec la liste des valeurs valides après tout (sauf si les écarts sont relativement peu nombreux, auquel cas vous pourriez utiliser: WHERE id BETWEEN 300 AND 3000 AND id NOT BETWEEN 742 AND 836 ou peu importe les lacunes.


IN est bien et bien optimisé. Assurez-vous de l'utiliser sur un champ indexé et vous allez bien. C'est fonctionnellement équivalent à (x = 1 OU x = 2 OU x = 3 ... OU x = 99) jusqu'au moteur concerné.


L'utilisation de IN avec un grand jeu de paramètres sur une grande liste d'enregistrements sera en fait lente.

Dans le cas que j'ai résolu récemment, j'avais deux clauses where, une avec 250 paramètres et l'autre avec 3500 paramètres, interrogeant une table de 40 millions d'enregistrements. Ma requête a pris 5 minutes en utilisant la norme WHERE IN. En utilisant plutôt une sous-requête pour l'instruction IN (en mettant les paramètres dans leur propre table indexée), j'ai obtenu la requête à DEUX secondes. J'ai travaillé pour MySQL et Oracle dans mon expérience.


Lorsque vous fournissez de nombreuses valeurs pour l'opérateur IN , il doit d'abord être trié pour supprimer les doublons. Au moins je le soupçonne. Il ne serait donc pas bon de fournir trop de valeurs, car le tri prend N log N heure.

Mon expérience a prouvé que le découpage de l'ensemble de valeurs en sous-ensembles plus petits et la combinaison des résultats de toutes les requêtes dans l'application offrent les meilleures performances. J'admets que j'ai accumulé de l'expérience sur une base de données différente (Pervasive), mais la même chose peut s'appliquer à tous les moteurs. Mon compte de valeurs par set était de 500-1000. Plus ou moins était significativement plus lent.







operators