2010-03-04 5 views
2

J'ai une grande table (~ lignes 1M maintenant, bientôt ~ 10M) qui a deux colonnes classement (en plus des données régulières):mysql: Optimisation de requête w/ordre mixte-ascendant PAR

  • avg_visited , un flotteur 0-1 représentant une popularité en% d'âge; plus élevé est mieux
  • alexa_rank, un nombre entier de 1-N donnant un classement a priori

Le classement a priori de source externe ne peut donc pas être modifié. Beaucoup de lignes n'ont pas encore de popularité (comme aucun utilisateur ne l'a encore touché), donc le classement a priori est l'ordre de repli. La popularité change cependant très fréquemment - à la fois pour mettre à jour les anciennes entrées et pour ajouter une popularité à celles qui auparavant ne disposaient que du classement a priori, si un utilisateur l'a réellement touché. J'ai souvent exécuté SELECT id, url, alexa_rank, avg_visited FROM sites ORDER BY avg_visited desc, alexa_rank asc LIMIT 49500, 500 (pour diverses valeurs de 49500).

Cependant, ORDER BY ne peut pas utiliser un index avec par mélange ascendant http://dev.mysql.com/doc/refman/5.0/en/order-by-optimization.html

Ceci est dans une base MySQL 5.1, InnoDB.

Comment est-ce que je peux mieux changer cette situation pour me donner une requête saine, entièrement indexée?

Répondre

1

Malheureusement, MySQL ne prend pas en charge les clauses DESC dans les index, pas plus qu'il ne prend en charge les index sur les expressions dérivées.

Vous pouvez stocker la popularité négative avec le positif et l'utiliser dans le ORDER BY:

CREATE INDEX ix_mytable_negpopularity_apriori ON (neg_popularity, a_priori); 

INSERT 
INTO mytable (popularity, neg_popularity) 
VALUES (@popularity, [email protected]); 

SELECT * 
FROM mytable 
ORDER BY 
     neg_popularity, a_priori 
+0

C'est aussi la première chose à laquelle j'ai pensé. Je me demande s'il y a une meilleure solution. – Sai

+0

@Sai: c'est peu probable (avec MySQL). Dans d'autres moteurs, vous pouvez créer un index sur '(popularité DESC, a_priori)', mais pas dans 'MySQL'. – Quassnoi

+0

Aussi, FWIW, je dois utiliser un index de couverture - c'est-à-dire '(neg_popularity, a_priori, common_data_1, common_data2)' - parce qu'un index simple ne fonctionne pas avec order by s'il y a d'autres champs dans select. : -/ – Sai

1

Juste un simple bidouille:

Depuis popularité est depuis un flotteur entre 0 à 1. Vous peut multiplier par -1 et le nombre sera compris entre -1 à 0.

de cette façon, vous pouvez inverser l'ordre de tri de la popularité à ORDER BY popularity ASC, a_priori ASC

Je ne suis pas sûr que l'overhead pèse le gain. Cela me rappelle le piratage des emails stockés en sens inverse.

+0

Ceci est identique à celui de Quassnoi, donc je lui donne le chèque d'être le premier (à moins que quelqu'un ne propose une meilleure solution). Quel piratage de stocker des e-mails sous forme inverse? Je ne le sais pas. – Sai