2011-04-25 3 views
1

Je dois obtenir toutes les entrées dans la base de données qui ont un publish_date entre deux dates. Toutes les dates sont stockées en tant que nombres entiers car les dates sont au format UNIX TIMESTAMP ... La requête suivante fonctionne parfaitement mais elle prend "trop ​​de temps". Il retourne toutes les entrées faites entre 10 et 20 dazs il y a.Optimisation de la requête SQL

SELECT * FROM tbl_post WHERE published < (UNIX_TIMESTAMP(NOW())-864000) 
AND published> (UNIX_TIMESTAMP(NOW())-1728000) 

Existe-t-il un moyen d'optimiser cette requête? Si je ne me trompe pas, il appelle les commandes NOW() et UNIX_TIMESTAMP sur evey. Je pensais que sauvegarder le résultat de ces 2 fonctions répétitives dans mysql @var rendait la comparaison beaucoup plus rapide, mais ce n'était pas le cas. 2ème code que je cours était:

SET @TenDaysAgo = UNIX_TIMESTAMP(NOW())-864000; 
SET @TwentyDaysAgo = UNIX_TIMESTAMP(NOW())-1728000; 
SELECT * FROM tbl_post WHERE fecha_publicado < @TenDaysAgo 
AND fecha_publicado > @TwentyDaysAgo; 

Une autre chose est source de confusion que PHP ne peut pas exécuter la requête mysql_query Bove de throught(); ?!

S'il vous plaît, si vous avez des commentaires sur ce problème, il sera plus que bienvenu :)

Luka

+0

Notez que 'NOW()' est une expression constante qui représente le début de l'exécution de l'instruction. Il n'y a donc aucune raison pour que MySQL ne puisse pas convertir 'UNIX_TIMESTAMP (NOW()) - 864000' en une expression constante. (Je ne sais pas si c'est le cas ... juste qu'il pourrait facilement.) – Matthew

Répondre

2

fonction mysql_query de PHP (en supposant que ce que vous utilisez) ne peut accepter une requête par chaîne , donc il ne peut pas exécuter les trois requêtes que vous avez dans votre deuxième requête.

Je suggère de déplacer ce genre de choses dans un stored procedure et de l'appeler à partir de PHP à la place. En ce qui concerne l'optimisation, la définition de ces variables est à peu près aussi optimisée que celle que vous obtiendrez pour votre requête. Vous devez effectuer la comparaison pour chaque ligne et définir une variable fournit le temps d'accès le plus rapide aux limites inférieure et supérieure.

Une amélioration de l'indexation de la table, plutôt que la requête elle-même, serait de regrouper l'index autour de fecha_publicado pour permettre à MySQL de gérer intelligemment la requête pour cette plage de valeurs. Vous pouvez le faire facilement en définissant fecha_publicado comme PRIMARY KEY de la table.

0

La façon d'optimiser serait de partitionner la table tbl_post sur la clé publiée selon les gammes de date (semble hebdomadaire approprié à votre demande). C'est une fonctionnalité disponible pour MySQL, PostgreSQL, Oracle, Greenplum, etc.

Cela permettra à l'optimiseur de requête de restreindre la requête à un ensemble de données beaucoup plus étroit.

+0

Partitionnement est une fonctionnalité nécessaire seulement quand il ya des loooooots de données. et MySQL a aussi un partitionnement. – johannes

+0

Si une telle requête prend trop de temps, et qu'il a déjà un index sur le champ * published *, alors il y a probablement assez de données dans cette table. Et j'ai fourni un lien vers la documentation de partitionnement de MySQL :) –

1

Les choses évidentes à vérifier sont les suivantes: existe-t-il un index sur la date de publication et est-il utilisé?

3

Assurez-vous d'avoir un index sur publié. Et assurez-vous qu'il est utilisé.

EXPLAIN SELECT * FROM tbl_post WHERE published < (UNIX_TIMESTAMP(NOW())-864000) AND published> (UNIX_TIMESTAMP(NOW())-1728000) 

devrait être un bon début pour voir ce qui se passe sur la requête. Pour ajouter un index:

ALTER TABLE tbl_post ADD INDEX (published) 
+0

J'ai défini mon fecha_publicado (ou publié) comme clé d'index mais les performances ne se sont pas vraiment améliorées? J'ai vérifié avec EXPLAIN et il dit que cet attribut est une clé d'index. étrange ... – luigi7up

+0

pouvez-vous poster la sortie EXPLAIN? – johannes

0

Je suis d'accord avec BraedenP qu'une procédure stockée serait appropriée ici. Si vous ne pouvez pas en utiliser un ou si vous ne le souhaitez pas, vous pouvez toujours générer les dates du côté PHP, mais elles peuvent ne pas correspondre exactement à la base de données, sauf si vous les avez synchronisées.

Vous pouvez également le faire plus rapidement que 3 requêtes distinctes probable.Interrogez les données de début, interrogez la date de fin, puis utilisez ces valeurs comme entrée dans votre requête cible.