J'ai une table avec au moins quelques millions de lignes et un schéma de tous les entiers qui ressemblent à ce qui ressemble à cela: Les lignes sont tirées à l'aide des requêtes suivantes: P> Je ne peux pas comprendre les meilleurs index pour accélérer ces requêtes. Le problème semble être l'ordre par parce que lorsque je suppose que les requêtes sont rapides. P> J'ai essayé tous les types d'index à l'aide du format d'index standard: P> SELECT *
FROM tbl_name
WHERE first_user_id=N
AND start >= M
ORDER BY start ASC
SELECT *
FROM tbl_name
WHERE first_user_id=N
AND second_user_id=N
AND start >= M
ORDER BY start ASC
3 Réponses :
Essayez d'éviter d'utiliser des gammes (par exemple>,> =, <, <=) comme la plus grande partie de la clause d'une clause Where. MySQL est incapable d'utiliser un index pour tous les champs de la clause WHERE à droite d'une plage. P>
Au premier abord, je dirais au moins créer un index sur first_user_id, arrêter, second_user_id. Spécifiez ensuite la requête en conséquence: P>
Sélectionnez * à partir de Tbl_name où first_user_id = N et stop> = m et second_user_id = n p>
MISE À JOUR: D'Oh, donc je me suis complètement contredit dans la requête ci-dessus - car incorporer second_user_id dans l'index est inutile lorsque vous le spécifiez dans le lieu de la section "Gamme", essayons donc à nouveau. P>
alter Table TBL_Name Ajouter index index_1 (first_user_id, arrêt) ALTER TABLE TBL_NAME Ajouter index index_2 (first_user_id, second_user_id, arrêt) p>
Afin de donner une réponse précise, j'aurais besoin de connaître beaucoup plus sur: la table, les données, le délai acceptable pour chaque traction, le matériel disponible, la croissance attendue, etc. En règle générale, vous obtiendrez la Meilleures performances en utilisant des requêtes qui ont l'endroit où les champs sont tous index (correctement). Cependant, étant donné qu'il semble que vous ayez toujours besoin de filtrer par une gamme de valeurs "stop", je ne suis pas sûr que vous puissiez créer un index qui aidera à la fois la plage d'arrêt et la commande par début.
Je peux totalement changer l'ordre des requêtes, cela ne devrait pas être un problème. Je me demande toujours si un index sur (first_user_id, stop, second_user_id) fonctionnerait pour la commande par laquelle semble être la partie qui ralentit vraiment la requête.
@Jaymon, en utilisant l'exemple de mon carnet d'emploi, un index sur Last_Name + Street_Name aide-t-il? Pour chaque nom distinct Last_Name, comme "Jones", les rues seraient triées correctement, mais vous obtenez une gamme de noms de Last_Neary, il aurait donc toujours besoin de réorganiser tout ce qui est de la répartition de Street_Name.
Tout d'abord, jetez un coup d'œil à la mise à jour que j'ai faite à ma réponse B / C I a goofed quelque chose dans l'original. Si le jeu de résultats est énorme, il n'y a pas vraiment rien de ce que vous puissiez faire B / C de la "gamme" d'arrêt. En dehors de la curiosité, veuillez exécuter ces requêtes et poster les résultats: "Sélectionnez Count (Démarrer) à partir de Tbl_Name où first_user_id = N et stop> = m;" et "SELECT COUNT (Démarrer) à partir de Tbl_Name où first_user_id = n et second_user_id = N et stop> = m;"
"Sélectionnez Count (Démarrer) à partir de TBL_NAME dans laquelle first_user_id = N et second_user_id = N et stop> = m;" a 30 rangées. Sélectionnez Compte (démarrage) à partir de Nom de Tbl_Name où first_user_id = N et Stop> = m; "a 4096 lignes. Il y a environ 4 millions de lignes totales dans TBL_Name.
Hmm, bien le 30 semble trivial et que vous pourriez toujours le punt et le faire avec le résultat en dehors de MySQL. Quant aux résultats plus importants, essayez peut-être une sous-requête comme: "Sélectionnez Démarrer, Stop, First_user_id, second_user_id à partir de (Sélectionnez Démarrer, STOP, FIRST_USER_ID, SECTEUR_USER_ID à partir de TBL_NAME LIRE_NAME_RESULTS COMMANDEZ par Démarrer ASC" . Je ne sais pas combien plus vite cela le fera mais pensé que je le jeter là-bas.
La chose étrange est que votre requête ne renvoie que 238 lignes (?)
Puisque vous avez indiqué que la requête est plus rapide sans la commande Aussi, n'oubliez pas de supprimer les index non utilisés par la suite :) p> edit em> p> C'est une supposition sauvage (parce que je ne suis pas sûr que MySQL ne facturez pas la requête à sa forme actuelle), mais vous pouvez essayer de procéder à ce qui suit: P> par code>, puis-je suggérer que vous faites le tri après la Query?
Cela peut être le moyen le plus rapide de résoudre le problème. P>
SELECT * FROM (
SELECT *
FROM tbl_name
WHERE stop >= M
AND first_user_id=N
) AS derived
ORDER BY start ASC
J'ai pensé à les trier après le fait, mais qu'il n'y ait que 238 rangées pour le seul ensemble de valeurs que j'ai utilisées, nous ne pouvons pas garantir qu'il y en aura aussi peu, et à l'avenir, il y aura très certainement beaucoup plus. C'est pourquoi j'essaie de le comprendre maintenant. Et oui, tous ces index sont juste sur mon DB DB. Lorsque je trouve un ensemble d'index qui fonctionne, ceux-ci seront les seuls à être ajoutés au serveur en direct.
Mais la simple existence de ces index a-t-elle un problème pour l'optimiseur? Ou est-ce juste quelque chose de coincé dans ma tête concernant Oracle qui n'a rien à voir avec MySQL?
Pourriez-vous faire votre table d'échantillons et expliquer la correspondance des résultats? Parce que, évidemment, ce n'est pas une même situation et que nous ne savons pas si vous avez peut-être commis une erreur en résumant votre vraie requête uniquement en regardant les résultats expliqués fournis. Si vous ne voulez pas montrer trop de structure, puis inversez-le et créez la structure de table citée et fournissez un résultat d'explication à ce sujet (peut-être que vous attraperez le problème de cette façon).
Maintenant, une chose est certaine - la tri Utilisation de FiltrySort , Ce qui est mauvais. p>
Simplifier (nous y reviendrons) - Index des composés utiles pour le tri doit avoir le champ de tri en avant. p>
exemple IDX (ID, Démarrage) P>
one_id_with_sort: [first_user_id, start]
Publiez la sortie d'expliquer sur vos questions.
Pourriez-vous essayer de faire un
expliquer code> sur la requête et coller ici parmi la liste des index? Pourrait aider à voir ce que MySQL essaie de faire.
Attendez, d'où vient un autre? Cela n'a jamais été mentionné et je suis confus sur la raison pour laquelle l'analyseur de requête penserait qu'il était pertinent car il n'est même pas utilisé dans le lieu où.
@Malonso, j'ai simplifié l'exemple et la table réelle a quelques colonnes de plus, ce que je montre ici. Je n'allais pas inclure l'index des autres_id à l'exception de l'analyseur de requête décidé de l'utiliser, aucune idée de la raison.
Quelles colonnes sont les plus sélectives?
Avez-vous essayé d'utiliser une table Temp? Je trouve souvent qu'une interrogation en plusieurs étapes (c.-à-d. Obtenir des données dans le tableau, manipuler des données) entraînera une durée de réponse beaucoup plus rapide.