2010-02-05 9 views
0

J'ai besoin d'aide pour indexer MySQL. J'ai une table MySQL avec des lignes suivantes:Table d'indexation avec doublons MySQL/SQL Server avec des millions d'enregistrements

ID Feature_ID Order_ID Viewed_Date Numéro magasin deal_id IsTrial
L'ID est généré automatiquement. Store_ID va de 1 à 8. Feature_ID à partir de 1 - disons 100. Date de consultation Date et heure auxquelles les données sont insérées. IsTrial est 0 ou 1.
Vous pouvez ignorer Order_ID et Deal_ID à partir de cette discussion. Il y a des millions de données dans la table et nous avons un backend de reporting qui doit afficher le nombre de vues dans une période donnée ou globalement où trial est 0 pour un identifiant de magasin particulier et pour une fonctionnalité particulière.

La requête prend la forme de:

select count(viewed_date) 
from theTable 
where viewed_date between '2009-12-01' and '2010-12-31' 
and store_id = '2' 
and feature_id = '12' 
and Istrial = 0 

Dans SQL Server, vous pouvez avoir un index filtré à utiliser pour Istrial. Y a-t-il quelque chose de similaire dans MySQL? En outre, Store_ID et Feature_ID contiennent beaucoup de données en double. J'ai créé un index en utilisant Store_ID et Feature_ID. Bien que cela semble avoir diminué la période de recherche, j'ai besoin d'une meilleure amélioration que cela. En ce moment j'ai plus de 4 millions de lignes. Pour rechercher une requête particulière comme celle ci-dessus, il regarde 3,5 millions de lignes afin de me donner le nombre de 500k lignes.

PS. J'ai oublié d'ajouter le filtre view_date dans la requête. Maintenant j'ai fait ça.

+0

Combien de temps faut-il pour compléter la sélection donnée? S'il vous plaît également envisager de choisir les bits « code » et en cliquant sur le bouton 0101010 dans la page d'édition pour mettre en évidence le code (comme les structures de la requête ou de table) –

+0

Merci pour la suggestion de code. Je reviendrai à vous avec plus de détails. – Tesnep

Répondre

0

La meilleure manière que je trouvais dans la lutte contre ce problème est d'ignorer la recommandation de DTA et de le faire moi-même de la manière suivante:

  • Utilisez Profiler pour trouver les requêtes les plus coûteuses en termes d'utilisation du processeur (blocage probablement requêtes) et appliquer des index aux tables basées sur ces requêtes. Si le plan d'exécution de la requête peut être modifié pour réduire les temps de lecture, d'écriture et d'exécution globale, commencez par le faire. Si ce n'est pas le cas, auquel cas la requête est ce qu'elle est, appliquez la combinaison d'index cluster/non-cluster au mieux. Cela dépend de la nature des indices de table existants, le total des octets de colonnes participant à l'index, etc.
  • requêtes Run dans les SSMS pour trouver les requêtes les plus fréquentes d'exécution et font la même chose que ci-dessus.
  • Créer un calendrier de défragmentation pour soit Réorganiser ou Reconstruire les index selon la façon dont ils sont beaucoup plus fragmentés.

Je suis assez sûr que d'autres peuvent suggérer de bonnes idées. Faire ceux-ci m'a donné de bons résultats. J'espère que quelqu'un peut utiliser cette aide. Je pense que DTA ne rend pas vraiment les choses plus rapides en termes d'indexation parce que vous avez vraiment besoin de passer en revue tous les index qu'il va créer. C'est plus vrai pour une base de données qui est souvent touchée.

0

Si vous avez besoin d'optimiser cette requête spécifiquement dans MySQL, pourquoi ne pas ajouter istrial à la fin de l'index existant sur Store_ID et Feature_ID. Cela va complètement indexer la clause WHERE et sera capable d'attraper COUNT à partir du résumé de cardinalité de l'index si la table est MyISAM. Toutes vos requêtes existantes qui exploitent l'index actuel seront également inchangées.

modifier: aussi, je ne sais pas pourquoi vous faites COUNT(viewed_date) au lieu de COUNT(*)? Est-ce que viewed_date est toujours NULL? Si ce n'est pas le cas, vous pouvez simplement utiliser le COUNT(*) qui éliminera le besoin d'aller au fichier .MYD si vous le prenez en conjonction avec mon autre suggestion.

+0

Ce serait une sorte de mauvaise pratique. Bonne idée, néanmoins. – Tesnep

+0

pourquoi est-ce une mauvaise pratique? –

+0

P.S. Voir ma modification. –

0

Eh bien, vous pouvez développer votre index pour inclure Store_ID, Feature_ID et IsTrial. Vous n'obtiendrez pas mieux que cela, dans le sens de la performance.

0

Ma première idée serait un index sur (feature_id, store_id, istrial), car feature_id semble être la colonne avec l'entropie de Shannon la plus élevée. Mais sans connaître les statistiques sur feature_id je ne suis pas sûr. Peut-être que vous devriez mieux créer deux index, (store_id, feature_id, istrial) étant l'autre et laisser l'optimiseur le trier. L'utilisation des trois colonnes présente également l'avantage que la base de données peut répondre à votre requête uniquement à partir de l'index, ce qui devrait également améliorer les performances. Mais si aucune de vos colonnes n'est suffisamment sélective pour améliorer suffisamment les performances de l'index, vous devrez peut-être recourir à la dénormalisation en utilisant les déclencheurs INSERT/UPDATE pour remplir une seconde table (feature_id, store_id, istrial, view_count). Cela ralentirait les insertions et les mises à jour, bien sûr ...

+0

l'index ne répondrait pas à la requête si les données que vous sélectionnez ne se trouvent pas dans l'index. Oui, les lignes à retourner seront complètement spécifiées par l'index, mais il faudra quand même aller dans le fichier .MYD pour obtenir les données réelles, et EXPLAIN ne dira pas "Using Index". –

+0

Vous avez raison, j'ai négligé que count (seen_date) doit rechercher notNULLness et neds pour frapper le disque dur pour cela. – wallenborn

0

Vous pourriez vouloir diviser cette table horizontalement. Vous pouvez exécuter un job nocturne qui place chaque store_id dans une table distincte. Ou jetez un oeil à feature_id, ouais, c'est beaucoup de tables mais si vous n'avez pas besoin de données en temps réel. C'est la route que je prendrais.

+0

Je pensais plutôt à la création d'un tableau de rapports séparé pour les données historiques en ajoutant également la colonne des totaux. Le problème est que je ne peux le faire que pour des périodes spécifiques de Views_Date, comme Dec 09 à Jan 2010. Si la période de temps change pour les requêtes, alors il faudra encore regarder dans cette table. Et oui, les clients ont besoin de données en temps réel. – Tesnep

Questions connexes