7
votes

Commander par Rand () Alternative

Dupliqué possible:
MySQL: Alternatives à la commande par Rand ()

J'ai actuellement une requête qui se termine commander par rand (heure (maintenant (())) limite 40 pour obtenir 40 résultats aléatoires. La liste des résultats change à chaque heure.

Cela tue le cache de requête, qui est une performance endommagée.

Pouvez-vous suggérer une solution alternative d'obtenir un ensemble de résultats aléatoire (ish) qui change de temps à autre? Il ne doit pas nécessairement être chaque heure et il n'est pas nécessaire d'être totalement aléatoire.

Je préférerais un résultat aléatoire, plutôt que de trier sur un champ arbitraire dans la table, mais je ferai cela comme un dernier recours ...

(Il s'agit d'une liste de nouveaux produits que je veux mélanger un peu de temps en temps).


2 commentaires

Pourriez-vous fournir un aperçu de ce que vous codez cela? Je suggérerais de faire cela dans le code par opposition à SQL.


Pourriez-vous simplement le mettre en cache au niveau de l'application?


9 Réponses :


5
votes

Son va tuer le cache parce que vous attendez un résultat différent à chaque fois. Il n'y a aucun moyen de pouvoir mettre en cache un ensemble de valeurs aléatoires. Si vous souhaitez mettre en cache un groupe de résultats, cache un ensemble de valeurs aléatoires importants, puis dans les sous-sections du temps que vous allez utiliser ces valeurs faire une prise aléatoire dans l'ensemble plus petit [en dehors de SQL].


2 commentaires

Eh bien, je veux seulement qu'il changea toutes les heures environ, donc pendant l'heure, il sera corrigé. C'est ce que ma requête actuelle produit, avec l'inconvénient de l'utilisation de Rand () qui empêche les résultats d'être mis en cache.


Bon point - il n'est pas nécessaire de dépendre de cache de MySQL ; par exemple. Memcached ou une autre cache d'application-Tier irait bien.



0
votes

Un moyen d'y parvenir est de mélanger les objets que vous mappez les données. Si vous ne mappiez pas les données sur des objets, vous pouvez mélanger la matrice de résultat de la base de données. Je ne sais pas si cela fonctionnera mieux ou non, mais vous obtiendrez au moins les avantages du cache de requête comme vous le mentionnez.

Vous pouvez également générer une séquence aléatoire de 1 à N, et indexer la matrice de résultat (ou la matrice d'objet) avec celles.


0 commentaires

1
votes

Vous pouvez avoir une colonne avec des valeurs aléatoires que vous mettez à jour toutes les heures.


0 commentaires

6
votes

Si vous avez une colonne d'identité, il est préférable de faire un: xxx pré>

La logique de sélection du numéro d'identification aléatoire peut être déplacée vers le niveau d'application. P>

SELECT * FROM table ORDER BY RAND LIMIT 40


1 commentaires

La table pourrait avoir des identifiants manquants quelque part au milieu, de sorte que la sélection correcte serait à la fin: Sélectionnez * à partir de l'ID> = @row limite 1;



0
votes

Calculez l'heure actuelle dans votre code PHP et transmettez-le à votre requête. Cela entraînera une valeur statique qui peut être mise en cache.

Notez que vous pourriez également avoir un bogue caché. Puisque vous ne prenez que l'heure, vous n'avez que 24 valeurs différentes, qui vont répéter tous les jours. Ce qui signifie que ce qui se présente à 13 heures aujourd'hui sera aussi le même que ce qui montre demain à 6. Vous voudrez peut-être changer cela.


1 commentaires

L'heure est simplement utilisée comme une graine pour le générateur de nombres aléatoires. Oui, je sais que j'ai les mêmes résultats à 14h chaque jour, mais c'est bien (à moins que la liste des produits ne change de quelque manière que ce soit))



0
votes

Ne vous battez pas avec le cache-- Exposez-le!

Écrivez votre requête comme vous êtes (ou même plus simple). Ensuite, dans votre code, cache les résultats, définissant une expiration de cache pendant 1 heure. Si vous utilisez une couche de cache, comme Memcached, vous êtes défini. Sinon, vous pouvez construire une assez simple: xxx


0 commentaires

3
votes

Je pense que la meilleure façon est de télécharger les identificateurs de produit vers votre couche intermédiaire, choisissez des valeurs aléatoires de 40 lorsque vous avez besoin (une fois par heure ou pour chaque demande) et utilisez-les dans la requête: produit_id dans (@ ID_1, @ id_2, ..., @ id_40) .


1 commentaires

+1 C'est souvent une bonne solution, à moins que @RIKH fonctionne Amazon ou eBay (I.e., des millions de produits). Avoir l'IDS en mémoire pourrait également être utile pour d'autres optimisations.



0
votes

Si vous n'avez besoin que d'un nouvel ensemble de données aléatoires une fois par heure, n'appuyez pas sur la base de données - enregistrez les résultats à la couche de mise en cache de votre application (ou, si elle n'en a pas, désactivez simplement une fichier de quelque sorte). La cache de requête est pratique, mais si vous n'avez jamais besoin d'exécuter une requête, encore mieux ...


0 commentaires

1
votes

Il s'agira d'une requête significativement méchante s'il doit trier un ensemble de données volumineux dans un ordre aléatoire (ce qui nécessite vraiment une sorte), puis supprimez tous les 40 premiers enregistrements.

Une meilleure solution serait de choisir 40 enregistrements aléatoires. Il y a beaucoup de façons de faire cela et cela dépend généralement d'avoir des clés qui sont réparties de manière uniforme.

Une autre option consiste à choisir les 40 enregistrements aléatoires dans un travail de lot qui est exécuté une fois par heure (ou autre), puis rappelez-vous lesquels ils sont.


0 commentaires