Question

Je travaille sur une requête pour un site d'actualités, qui trouvera un contenu en vedette pour l'affichage sur la page d'accueil principale. Le contenu marqué de cette façon est étiqueté comme «Content de vedette», et commandé dans une table en vedette par «page d'accueil». J'ai actuellement la sortie souhaitée, mais la requête fonctionne en plus de 3 secondes, ce que je dois réduire. Comment optimiser une requête comme celle qui suit?

Edit: matérialisé la vue à chaque minute comme suggéré, jusqu'à 0,4 secondes:

SELECT f.position, s.item_id, s.item_type, s.title, s.caption, s.date
FROM live.search_all s 
INNER JOIN live.tags t 
ON s.item_id = t.item_id AND s.item_type = t.item_type AND t.tag = 'FeaturedContent' 
LEFT OUTER JOIN live.featured f 
ON s.item_id = f.item_id AND s.item_type = f.item_type AND f.feature_type = 'homepage'
ORDER BY position IS NULL, position ASC, date

Cela renvoie toutes les fonctionnalités de page d'accueil dans l'ordre, suivie d'un autre contenu en vedette commandé par date.
L'explication ressemble à ceci:

|-id---|-select_type-|-table-|-type---|-possible_keys---------|-key--------|-key_len-|-ref---------------------------------------|-rows--|-Extra-------------------------------------------------------------|
|-1----|-SIMPLE------|-t2----|-ref----|-PRIMARY,tag_index-----|-tag_index--|-303-----|-const-------------------------------------|-2-----|-Using where; Using index; Using temporary; Using filesort;--------|
|-1----|-SIMPLE------|-t-----|-ref----|-PRIMARY---------------|-PRIMARY----|-4-------|-newswires.t2.id---------------------------|-1974--|-Using index-------------------------------------------------------|
|-1----|-SIMPLE------|-s-----|-eq_ref-|-PRIMARY, search_index-|-PRIMARY----|-124-----|-newswires.t.item_id,newswires.t.item_type-|-1-----|-------------------------------------------------------------------|
|-1----|-SIMPLE------|-f-----|-index--|-NULL------------------|-PRIMARY----|-190-----|-NULL--------------------------------------|-13----|-Using index-------------------------------------------------------|

Et le profil est le suivant:

|-Status---------------|-Time-----|
|-starting-------------|-0.000091-|
|-Opening tables-------|-0.000756-|
|-System lock----------|-0.000005-|
|-Table lock-----------|-0.000008-|
|-init-----------------|-0.000004-|
|-checking permissions-|-0.000001-|
|-checking permissions-|-0.000001-|
|-checking permissions-|-0.000043-|
|-optimizing-----------|-0.000019-|
|-statistics-----------|-0.000127-|
|-preparing------------|-0.000023-|
|-Creating tmp table---|-0.001802-|
|-executing------------|-0.000001-|
|-Copying to tmp table-|-0.311445-|
|-Sorting result-------|-0.014819-|
|-Sending data---------|-0.000227-|
|-end------------------|-0.000002-|
|-removing tmp table---|-0.002010-|
|-end------------------|-0.000005-|
|-query end------------|-0.000001-|
|-freeing items--------|-0.000296-|
|-logging slow query---|-0.000001-|
|-cleaning up----------|-0.000007-|

Je suis nouveau dans la lecture de la sortie Explication, donc je ne sais pas si j'ai une meilleure commande disponible, ou quelque chose de assez simple qui pourrait être fait pour les accélérer.

Le tableau Search_ALL est le tableau de vue matérialisé qui est périodiquement mis à jour, tandis que les balises et les tables en vedette sont des vues. Ces vues ne sont pas facultatives et ne peuvent pas être travaillées.

La vue de balises combine des balises et une table relationnelle pour récupérer une liste des balises selon item_type et item_id, mais les autres vues sont toutes des vues simples d'une table.

EDIT: Avec la vue matérialisée, le plus gros goulot d'étranglement semble être l'étape «Copying to Temp Table». Sans commander la sortie, il faut 0,0025 secondes (bien mieux!) Mais la sortie finale doit être commandée. Existe-t-il un moyen d'améliorer les performances de cette étape ou de le contourner?

Désolé si le formatage est difficile à lire, je ne suis pas nouveau et je ne sais pas comment il est régulièrement fait.
Merci pour ton aide! Si quelque chose d'autre est nécessaire, faites-le moi savoir!

Modifier: tailles de table, pour référence:
Relations de tag: 197,411
Tags: 16 897
Histoires: 51 801
Images: 28 383
Vidéos: 2 408
En vedette: 13

Était-ce utile?

La solution

Je pense que l'optimisation de votre requête ne sera pas très utile. Les premières pensées sont que rejoindre une sous-requête, elle-même en syndicats, est à elle seule un double goulot d'étranglement pour les performances.

Si vous avez la possibilité de modifier votre structure de base de données, je vous suggère de fusionner les 3 tables stories, images et videos en un, s'ils le sont, comme ça ressemble, très similaire (leur ajoutant un type ENUM('story', 'image', 'video')) pour différencier les enregistrements; Cela supprimerait à la fois la sous-requête et l'Union.

Aussi, cela ressemble à vos vues sur stories et videos, n'utilisent pas un champ indexé pour filtrer le contenu. Interrogez-vous une colonne indexée?

C'est un problème assez délicat sans connaître votre structure de table complète et la répartition de vos données!

Une autre option, qui n'impliquerait pas d'apporter des modifications à votre base de données existante (surtout si elle est déjà en production), serait de "cache" ces informations dans un autre tableau, qui serait périodiquement actualisé par un travail cron.

La mise en cache peut être effectuée à différents niveaux, soit sur la requête complète, soit sur des sous-parties (vues indépendantes, soit les 3 syndicats fusionnés dans une seule table de cache, etc.)

La viabilité de cette option dépend s'il est acceptable d'afficher ou non des données légèrement obsolètes. Il peut être acceptable pour certaines parties de vos données, ce qui peut impliquer que vous mettrez en cache juste un sous-ensemble des tables / vues impliquées dans la requête.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top