6
votes

Marquage de la requête avec group_concat

Utilisation du schéma de base de données pour le marquage de cette question est accepté Réponse est-il possible d'avoir une requête à l'aide de group_concat qui fonctionne avec une grande quantité de données? J'ai besoin d'obtenir des articles avec leurs balises pour tous les articles étiquetés avec tag x. L'utilisation d'une requête avec group_concat ayant ~ 5 millions d'étiquettes est très lente à> 15 secondes. Sans group_concat (éléments sans balises ), il est ~ 0.05 secondes.

comme une question secondaire, comment résout ce problème?


3 commentaires

Pouvez-vous donner des enregistrements d'exemples?


Il semble donc résoudre ce problème en limitant les questions à la plupart des 5 étiquettes. Et qu'est-ce qui vous fait penser qu'il utilise group_concat () du tout lors de la gestion des balises?


@Barmar: la limite de balise sur SO N'EST PAS pour des raisons de performance, mais plutôt pour garder les questions ciblées ; Comme pour SYSTMA , les balises sont associées à des messages de la mode normalisée (la table posttags ) et aussi une mode dénormalisée (le champ Posts.Tags.Tags ) - Ce dernier permet de récupérer des balises d'un post avec le poste lui-même, tandis que le premier facilite la recherche de postes avec une balise particulière combinaisons.


4 Réponses :


5
votes

Ceci est probablement un cas d'une stratégie d'indexation médiocre. Adapter le schéma montré dans La réponse acceptée de la question à laquelle vous avez lié: xxx

note que:

  • Le type de données MySQL est un alias pour Bigint non signé non null auto_incrètent unique et, comme tel, est indexé;

  • Définition des contraintes de clé étrangère dans items_Tags crée des index sur les colonnes de clé étrangère.


1 commentaires

Hmm Je suis assez sûr que j'ai les mêmes indices, vérifiera plus tard ce soir.



3
votes

Je proposerais d'avoir un hybride entre Données normalisées et Dénormalisés Data.
Ainsi, à l'aide de la structure normalisée fournie par Eggyal je ferais la structure dénormalisée suivante: xxx

dans la colonne Tags Vous auriez toutes les balises ( tag_title ) pour le item_id correspondant .
Maintenant, vous avez 2 façons d'y parvenir:

  • Créez un cron qui fonctionne périodiquement, ce qui construira cette table items_tags_dénormalisé à l'aide de Groupe_ConCat ou quelque chose qui vous convient (avantage: ne met pas de charge supplémentaire lorsque vous insérez. ou supprimer dans items_tags Table; Inconvénient: La table dénormalisée ne sera pas toujours à jour (en fonction de la fréquence d'exécution de la courante)

  • créer déclenche pour Articles_Tags TABL SUR INSERTER ET SUPPRIMER Pour que vous continuez à mettre à jour le tableau items_tags_dénormalisé Table (avantage: la table dénormalisée sera toujours à jour; inconvénient: charge supplémentaire lorsque vous insérez ou supprimez Dans items_Tags table)

    Choisissez quelle que soit la solution adaptée à vos besoins en considérant les avantages et les inconvénients.

    donc à la fin, vous aurez la table items_tags_dénormalisée de laquelle vous allez Seulement lire sans faire des opérations supplémentaires .


2 commentaires

Pourquoi ne pas ajouter le champ disormalisé (code> sur le champ éléments Table (ce qui est ainsi que ça)?


Il est crucial d'avoir des modèles distincts: une normalisée et une dénormalisation, votre solution est correcte mais de la conception POV, je suggérerais de le garder séparé pour diverses raisons: vous devez reconstruire la table, vous devez ajouter plus de colonnes, etc. Plus si vous Ajouter une colonne de balises dénormalisées dans les éléments Les performances de la table chuteront: taille plus grande = requêtes plus lentes



1
votes

Pourquoi utiliseriez-vous GROUP_CONCAT pour cela? Pour une balise X donnée, vous avez dit que la sélection de la liste des éléments est rapide. Pour une liste donnée d'éléments, tous les tags devraient également être rapides. Et n'y a-t-il pas normalement une sorte de restriction, je veux dire des sites Web normaux ne montrent pas 100 000 entrées sur une page.

Je suggérerais: P>

drop temporary table if exists lookup_item;

create temporary table lookup_item (item_id serial, primary key(item_id));

insert into lookup_item select i.id as item_id 
from items i 
where exists (select * from items_tags where item_id = i.id and tag_id = <tag_id>)
and <other conditions or limits>;

select * from lookup_item
inner join items_tags it on it.item_id = i.id
inner join tags t on t.id = it.tag_id
order by i.<priority>, t.<priority>


0 commentaires

1
votes

Si je comprends correctement, group_concat n'est pas la seule chose que vous supprimez qui rend la requête plus rapide sans étiquettes. À l'intérieur du group_concat Vous sélectionnez tags.tag_title et forçant la table des étiquettes à accéder.

Vous pouvez essayer d'exécuter group_concat avec items_tags.tag_id pour tester ma théorie.


0 commentaires