2010-08-20 11 views
2

im en cours d'exécution requête ci-dessous pour rapportez de 3 tables MySQL et il fonctionne très bien, mais il augmente l'utilisation de la mémoire et parfois il faut 10 secondes pour commencer à charger la pageinstruction de jointure interne mysql et surutilisation de la mémoire!

INNER JOIN table_tags AS ntg ON (ns.tags = '' OR CONCAT(' ',COALESCE(ns.tags,' '),' ') LIKE CONCAT('% ',ntg.tid,' %')) 
    INNER JOIN table_topics AS nto ON (ns.associated = '' OR CONCAT(' ',COALESCE(ns.associated,'-'),' ') LIKE CONCAT('%',nto.topicid,'%')) 

problème est dans INNER JOIN statemnet et si i supprimer

ns.tags = '' OR

et

ns.associated = « » OU

le problème de l'utilisation excessive de la mémoire sera fixe, mais des histoires montrent cative avec champ vide tag

est-il une autre façon d'écrire la déclaration ci-dessous pour inclure tous des histoires même celles sans étiquettes!

INNER JOIN table_tags AS ntg ON (ns.tags = '' OR CONCAT(' ',COALESCE(ns.tags,' '),' ') LIKE CONCAT('% ',ntg.tid,' %')) 

mon id tags sont stockés dans table_ns comme (14 17 2) seprated avec l'espace

Répondre

1

Votre état ns.tags = '' OR ... signifie que si ns.tags = '' est vrai ce disque de table_stories sera jointe à tous les enregistrements table_tags. Idem avec ns.associated = '' OR ... Cela peut facilement "créer" des ensembles de résultats énormes et ce n'est probablement pas ce que vous voulez.
Si vous ne voulez vraiment pas/ne peut pas changer/normaliser la structure de la table (comme vous l'avez dit dans un commentaire à ma réponse précédente) ma meilleure estimation est d'utiliser deux LEFT JOINs comme:

SELECT 
    ns.*, 
    ntg.tid, 
    nto.topicid, 
    group_concat(DISTINCT ntg.tag) as mytags, 
    group_concat(DISTINCT ntg.slug) as tagslug, 
    group_concat(DISTINCT nto.topicname) as mytopics, 
    group_concat(DISTINCT nto.slug) as topicslug, 
    ns.counter AS counter_num 
FROM 
    table_stories AS ns 
LEFT JOIN 
    table_tags AS ntg 
ON 
    CONCAT(' ', ns.tags,' ') LIKE CONCAT('% ',ntg.tid,' %') 
LEFT JOIN 
    table_topics AS nto 
ON 
    CONCAT(' ', ns.associated, ' ') LIKE CONCAT('%',nto.topicid,'%') 
WHERE 
    time <= '4711' 
GROUP BY 
    ns.sid 
ORDER BY 
    ns.sid DESC,ns.hotnews DESC 

Mais MySQL ne peut pas utiliser d'index pour cela, donc la requête aboutira à des analyses de table complètes. Il aura également besoin de tables et filesort temporaires, c'est-à-dire que la requête est relativement lente.
Sans changer la structure de la table mais le format des données 1 2 3-1,2,3 vous pouvez au moins se débarrasser de Concat() et LIKE en utilisant le FIND_IN_SET(str, strlist) un peu plus rapide.


Juste pour être complet et si vous changez d'avis: http://en.wikipedia.org/wiki/Database_normalization