4 votes

Flux d'activités avec PHP MySQL

Je suis en train de créer une sorte de "flux d'activité" en utilisant PHP et MySQL.

J'ai une table pour le flux qui stocke simplement le type d'activité et l'horodatage. J'ai ensuite besoin de consulter les données réelles de l'activité qui peuvent être trouvées dans différentes tables (en fonction du type d'activité). Le flux doit être capable de gérer des centaines d'utilisateurs et j'ai donc besoin qu'il soit performant. Les options que j'ai obtenues :

  • Récupérez la table des flux - faites une boucle en PHP avec une sorte de commutateur, puis appelez SQL pour les données d'activité appropriées (pour chaque activité). (Lent)
  • Faites une grande phrase SQL avec quelques jointures prenant toutes les données d'activité en une seule requête. Toujours en faisant la jointure en PHP mais sans avoir à appeler SQL à nouveau. (Est-ce lent pour les grandes tables ?)
  • Utilisation d'une sorte de vues avec MySQL - Je n'ai jamais fait cela auparavant.
  • Utilisation de plusieurs appels SQL pour obtenir toutes les données d'activité, les stocker dans des tableaux PHP et, à partir de là, effectuer la commutation.

Ai-je d'autres options ? Quelle serait la meilleure approche en termes de performances ?

4voto

Naltharial Points 1512

Vous pouvez effectuer une analyse des données JOIN avec une seule requête. Pour l'essentiel, vous devez JOIN chaque sous-table nécessaire et ensuite sélectionner, par alias, le contenu de la table dont vous avez besoin. En supposant que 1 est activité_boisson, 2 est activité_mange et 3 est activité_sport et que toutes les sous-tables ont la colonne content que vous souhaitez récupérer :

SELECT a.`timestamp`,
    CASE a.`activity_type`
        WHEN 1 THEN ad.`content`
        WHEN 2 THEN ae.`content`
        WHEN 3 THEN asp.`content`
    END AS content
FROM activities AS a
LEFT JOIN activity_drink AS ad ON (ad.`activity_id` = a.`activity_id`)
LEFT JOIN activity_eat AS ae ON (ae.`activity_id` = a.`activity_id`)
LEFT JOIN activity_sports AS asp ON (asp.`activity_id` = a.`activity_id`)

Cela aurait pour effet de dénormaliser vos tableaux au moment de la sélection. Vous pourriez également le convertir en un VIEW pour faciliter l'accès. Cela ne devrait pas être trop coûteux, en supposant que vous avez correctement configuré les clés étrangères, les identifiants et/ou les noms de domaine. UNIQUE (MySQL remarquera qu'il n'y a pas de lignes correspondantes dans la table et "l'ignorera" - en sélectionnant une ligne NULL). Je ne l'ai pas testé correctement, car je n'ai pas de données et j'ai dû supposer, mais le snippet devrait fonctionner en principe.

Je tiens toutefois à préciser que je me méfie personnellement de l'utilisation de jointures basées sur des données. La bonne façon de procéder à la normalisation dans ce cas serait de trouver le plus grand ensemble commun d'attributs et de les placer dans un fichier de type activities table. Si cela s'avère nécessaire, vous pouvez ajouter des informations supplémentaires aux tableaux adjacents. En règle générale, cependant, si plusieurs tableaux utilisent les mêmes données, vous devriez probablement les placer dans la colonne principale, à moins qu'il ne soit absolument nécessaire de ne pas le faire.

1voto

Luke Points 89

La solution que j'ai mise en œuvre comporte 7 types de contenu différents, tous stockés dans des tables distinctes, mais j'ai 1 table d'activité/alimentation .

Ma solution - Utilisation de mySQL5.7 Je tire parti du champ JSON . J'ai un travail qui sélectionne les différents types de contenu et insère une ligne dans le tableau d'activité et en utilisant la fonction mysql JSON_OBJECT() il stocke ces données sous forme de json dans la colonne de données, puis mon application manipule ce json et l'affiche comme il se doit. Les données JSON ne contiennent que les données pertinentes dont elle a besoin pour ce type de contenu, donc pas de valeurs nulles.

  • id | contentType | data(JSON) | created | status

Cela signifie donc que je n'ai pas de jointures internes, pas de table non extensible avec des tas de champs nuls.

J'ai pu facilement ajouter d'autres types de contenu sans rien changer.

0voto

Packet Tracer Points 2129

Si le flux d'activité n'est pas trop long (quelques enregistrements, pas des milliers), j'opterais pour une seule requête, si les tables sont indexées correctement, la requête devrait être suffisamment rapide. Si vous pouvez créer des unions avec vos tables, je pense que cette requête ne devrait pas être si coûteuse.

SELECT * FROM (
  SELECT * FROM stream 
    INNER JOIN type1 ON stream.id = type1.stream_id
  LIMIT 50

  UNION

  SELECT * FROM stream 
    INNER JOIN type1 ON stream.id = type1.stream_id
  LIMIT 50

  UNION

  ...
)
ORDER BY stream.timestamp_field
LIMIT 50

Comme autre solution, si vous n'avez pas beaucoup de tables de type, vous pourriez faire une requête pour chaque type de table, et ensuite fusionner les résultats. Mais vous devrez ordonner les résultats fusionnés avec PHP.

$sql1 = "SELECT * FROM stream INNER JOIN type1 ON stream.id = type1.stream_id";
$sql2 = "SELECT * FROM stream INNER JOIN type2 ON stream.id = type2.stream_id";
...

Quelle est la taille des résultats que vous voulez obtenir ? comment voulez-vous ordonner les résultats ? peut-être que les performances ne sont pas un problème en limitant les résultats de votre requête.

0voto

Mafuba Points 374

Cette réponse est tardive, mais si le flux d'activités fait partie d'une application plus vaste, il peut être judicieux d'utiliser un service externe comme Collabinate ( http://www.collabinate.com ).

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X