Jump to content
billcom

Requête multiple qui ralentit page web

Rate this topic

Recommended Posts

Bonjour à tous,



J'ai, sur un site d'offre d'emploi, une liste de domaines et plusieurs offres.



Chaque offre à un domaine correspondant.



Structure des tables :


  • table domaine
    • id_domaine
    • nom_domaine
    • ...

  • table offre
    • id_offre
    • id_domaine
    • date
    • ...

Sur une page du site, j'aimerai lister tous les domaines ainsi que les trois dernières offres du domaine en question.



Pour avoir ce résultat, je fais actuellement :


  • Une requête qui récupère les domaines;
  • Puis quand j'affiche les domaines avec un foreach(), je fais une requête qui récupère les 3 dernières offres correspondant au domaine courant.

Le problème, c'est que faire une requête dans une boucle n'a jamais été top et effectivement la page est longue à charger.



J'ai alors mis en cache la requête (remember / j'utilise le framework Laravel) afin que la page soit plus rapide. Cependant au premier chargement la page met très longtemps a apparaître.



J'aimerai optimiser ce premier chargement.



J'ai essayé de faire une requête avec une sous-requête mais sans succès et je ne sais même pas si c'est possible.



Si vous êtes un champion de SQL ou que vous voyer la faille dans mon raisonnement, j'attend votre aide thumbup.gif



Merci d'avance.


Share this post


Link to post
Share on other sites

Bonjour,



C'est possible avec une sous-requête :



SELECT domaine.Nom, offre.*
FROM domaine inner join (
SELECT Nom, id_offre
FROM Offre
order by date desc
LIMIT 0 , 3
) AS offre ON domaine.id_domaine = offre.id_domaine
WHERE 1
order by domaine.nom

A tester mais cela devrait marcher.




Portekoi


Share this post


Link to post
Share on other sites

Bonjour, j'étais en déplacement pro depuis mercredi.



Merci pour vos réponses je vais tester ça aujourd'hui thumbup.gif


Share this post


Link to post
Share on other sites

Alors, as tu pu tester?

Je viens de tester la requête, cela liste 3 résultats uniquement et non les 3 dernières offre de chaque domaine.

Merci encore

Share this post


Link to post
Share on other sites

Fonctionnelle :



set @num := 0, @domaine_id := '';

select * from(
select domaine.nom as domaine_nom, offre.id, offre.nom as offre_nom, offre.domaine_id,
@num := if(@domaine_id = domaine_id, @num + 1, 1) as nb,
@domaine_id := domaine_id as var
from offre inner join domaine on offre.domaine_id = domaine.id
group by domaine.nom, offre.id, offre.nom, domaine_id
having nb <= 2
) as tt
order by domaine_nom, offre_nom desc;

Share this post


Link to post
Share on other sites

Pour avoir les deux premières offres pour chaque domaine (attention aux ressources / à tester)



select m.id, m.nom as offre_nom, m.domaine_id
from offre as m
where m.id = (
select max(id) from offre where domaine_id = m.domaine_id)
or m.id = (
select max(id) from offre where domaine_id = m.domaine_id and id not in (select max(id) from offre where domaine_id = m.domaine_id))


Share this post


Link to post
Share on other sites

Si tu me dis que ça ne marche pas, je mange mon clavier :)


Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

  • Similar Content

    • By billcom
      Bonjour,

      Je me retrouve encore dans l'impasse aujourd'hui avec une requête imbriqué.



      Ma base est structuré de cette façon :

      Tables :


      messagerie



      messagerie_message_type



      messagerie_utilisateur_type


      Structure table messagerie :


      id (int)



      parent_id (int)



      sujet (varchar)



      contenu (text)



      lu (bool)



      message_type (int)



      expediteur_id (int)



      expediteur_type (int)



      destinataire_id (int)



      destinataire_type (int)



      date (timestamp)


      exemple :

      [

      'id' => 1,

      'parent_id' => 0,

      'sujet' => sujet test,

      'contenu' => blablabla,

      'lu' => 0,

      'message_type => 2,

      'expediteur_id' => 9,

      'expediteur_type => 1,

      'destinataire_id' => 5,

      'destinataire_type' => 2,

      'date' => 2015-07-29

      ]



      Structure table messagerie_message_type :


      id (int)



      type (varchar)


      exemple : [ 1 => question, 2 => message, 3 => demande d'infos ]



      Structure table messagerie_utilisateur_type :


      id (int)



      type (varchar)


      exemple : [ 1 => utilisateur, 2 => entreprise, 3 => ... ]



      Relations entre les tables :


      messagerie.message_type = messagerie_message_type.id



      messagerie.expediteur_type = messagerie_utilisateur_type.id



      messagerie.destinataire_type = messagerie_utilisateur_type.id




      Je cherche à lister tous les messages qui concerne un utilisateur (expéditeur et destinataire donc).



      Ma requête :

      SELECT * FROM messagerie

      WHERE (expediteur_id = x AND expediteur_type = 1)

      OR (destinataire_id = x AND destinataire_type = 1)



      Je récupère de cette façon les id des expéditeurs et destinataires.

      J'aimerai appliquer un SELECT et faire une jointure différente selon chaque ligne retourné par la requête.



      Je ne sais pas si cela est possible.

      Je m'explique :

      Je souhaite dans la requête ci-dessus pouvoir récupérer le nom_entreprise ou le nom et prenom selon si l’expéditeur est un utilisateur ou une entreprise.



      Je ne peux pas faire une jointure normale car un utilisateur peut être à la fois un expéditeur sur un message et un destinataire sur un autre.



      Je peux faire une boucle sur les résultats de la requête ci-dessus pour arriver à mes fins mais je sais que faire une requête en bouclant sur une autre ce n'est pas le mieux.



      Si il y a des pros du SQL dans la salle merci de m'aider.



      A bientôt

    • By MissOlana
      Rebonjour à tous chers internautes,
      me revoila pour un probleme que je n'arrive pas à résoudre: (hey oui je suis une buse des fois (rire))
      Bon voici le script et mon probleme:

      J'utilise un select multiple pour proposer un choix de recherche: (Homme, femme, couple)

      <select multiple="multiple" name="recherche[]" multiple size="3"> <option data-img-src="icone-homme.png" value="1"></option> <option data-img-src="icone-femme.png" value="2"></option> <option data-img-src="icone-couple.png" value="3"></option></select> Je récupere les données de mon choix multiple
      <?phpif(isset($_POST['recherche'])){if(($_POST['recherche']) && !empty($_POST['recherche'])){$Col1_Array = $_POST['recherche'];//print_r($Col1_Array);foreach($Col1_Array as $selectValue){//affichage des valeurs sélectionnéesecho $selectValue."";}}}?> Le résultat s'affiche comme suit:
      si le membre clique sur homme et femme cela m'affiche: 1 et 2
      si le membre clique sur homme, femme couple : 1 et 2 et 3
      jusque là tout va bien !

      Mon souci et l'ajout dans ma base de données MSQL, je n'y arrive pas
      Voici ma base:

      Voici la solution expéré:
      La table "comptes"
      +---------------+------------+----------+---------+| nom | Choix1 | Choix2 | Choix3 |+---------------+------------+----------+---------+| MissOlana | 1 | 2 | 3 | (si j'ai choisi homme, femme couple)+---------------+------------+----------+---------+| Paul | 1 | | | (si il a choisi homme)+---------------+------------+----------+---------+| Pierre | | 2 | 3 | (si il a choisi femme et couple)+---------------+------------+----------+---------+
      En attente de vos lumiéres , merci encore les amis, je remercie aussi duplex13, Dadou, hsdino pour mes anciens soucis
    • By elfaus
      Salut à tous,



      j'essaye d'optimiser un script php afin de n'avoir à réaliser qu'une seule requête et récupérer toutes les informations nécessaires. J'ai découvert il y a peu group_concat mais je ne suis parvenu à le faire fonctionner que sur un seul champ.



      Soit les deux tables sources suivantes :



      Heroes


      +----+-----------+------------+
      | id| name_fr | name_us |
      +----+-----------+------------+
      | 1 | ababab | ababab |
      | 3 | efefef | efefef |
      +----+-----------+------------+
      Schools


      +----+-----------+-----------+
      | id | name_fr | name_us |
      +----+-----------+-----------+
      | 3 | ababab | ababab |
      | 5 | cdcdcd | cdcdcd |
      | 9 | efefef | efefef |
      +----+-----------+-----------+

      Soit la table relationnelle suivante :
      Heroes_Schools


      +----+----+
      | hid|sid |
      +----+----+
      | 1 | 3 |
      | 1 | 5 |
      | 3 | 9 |
      +----+----+



      L'idée, est de faire en sorte de récupérer un résultat similaire à celui-ci


      +----+-----------+-----------+--------------------------------------------------+
      | id| name_fr | name_us | schools |
      +----+-----------+-----------+--------------------------------------------------+
      | 1 | ababab | ababab | 3, ababab, ababab; 5, cdcdcd, cdcdcd |
      | 3 | efefef | efefef | 9, efefef, efefef |
      +----+-----------+-----------+--------------------------------------------------+
      Afin de pouvoir par la suite faire un traitement de tableau en php et passer le contenu de schools en paramètre d'une autre class que celle réalisant la requête et stockant les information id, name_fr et name_us



      Pour l'instant j'ai ça :


      SELECT mch.id, mch.name_fr, mch.name_us, GROUP_CONCAT(mcs.id) AS schools_id, GROUP_CONCAT(mcs.name_fr) AS schools_name_fr, GROUP_CONCAT(mcs.name_us) AS schools_name_us

      FROM mom_cards_heroes AS mch
      LEFT JOIN mom_cards_heroes_schools AS mchs ON mch.id = mchs.heroesid
      LEFT JOIN mom_cards_schools AS mcs ON mchs.schoolid = mcs.id
      WHERE mch.`publish` = 1
      GROUP BY mch.id
      ORDER BY mch.factionid, mch.name_fr ASC

      Mais pas suffisant x)
    • By Torlax
      Bonjour à tous !



      Etant totalement désespéré, je m'adresse à vous en dernier recours



      Je vous retrace l'historique de mon problème :



      Je m'occupe actuellement d'un site avec un nombre de connexion plutot énorme (150 000 à 300 000 visiteurs par jours en moyenne). Le site en question est un bon gros Wordpress (9 plugins actif, plugins plutôt propre parmi les plus connu) avec une base sql pesant 380 Mo et environs 9000 articles, ainsi qu'un forum IPB don la base sql pèse 150 Mo... Auparavant, nous avions un gros HG XXL chez ovh pour gérer le tout. J'avais monté un ESX avec ma VM dessus qui comprenais Apache, php5, Mysql, bref... Après optimisation, on arrivais à grimper à environs 4000/4500 connexions simultanés (via Google Analytics) avec un Load Average assez élevé... J'ai donc fait le choix de partir sur deux serveur MG SSD plus petit (mono Xeon, 64 Go de ram sur les deux), le tout avec un Vrack (Baie Virtuelle), un bloc RIPE, et j'ai connecté mes deux serveur en "privé". Sur le premier (le frontal) J'y ai mis Apache + PHP et sur le seconds, mon Mysql. En gros j'ai réparti la charge sur deux serveur quoi... Après optimisation, j'obtiens à peu prêt la même tolérance à la charge qu'auparavant, mais avec des temps de réponses plutot rapide. Le souci, c'est que pendant les pic d'audience, ça se vautre méchamment...



      Constatations actuelles :



      - Mes logs apache ne me remonte aucunement la fameuse alerte comme quoi j'aurais atteins "Max_connection" (réglé sur 1024 actuellement).

      - Mes logs Mysql ne me remonte aucunement "Too many connections"

      - J'utilise bien un Opcode, ici APC (avec valeur 2Go de cache)

      - Coté Wordpress, W3 Total Cache paramétré

      - Cloudflare actif pour décharger apache de toute la partie "statique"



      En fait, quand ça pète, ça donne réellement l'impression que Apache suit correctement, Mysql sature, il tombe... les requête s'empilent et font ensuite pétés apache + php.



      J'en viens à ma demande... La partie ou je m'y connais le moins bien est Mysql (comme beaucoup...) Et je suspecte beaucoup d'avoir une base non optimisé (manque d'index, problème de jointures etc...) en plus de (peut être) quelques script foireux. Pour les scripts foireux, nous y travaillons : Nous allons faire développer notre propre thème, avec tout ce que nous avons besoin en plugin directement intégré pour décharger Wordpress.



      Là ou je bute, c'est l'optimisation de ma base Mysql... Les index, etc... Je ne sais pas dutout par ou commencer. J'ai également essayé de passé toutes mes table en Innodb pour éviter les lock au niveau des tables, ça s'écroule encore plus vite qu'en Myisam, en ayant pourtant pris soin de ne pas faire de réglages foireux (Pool_Buffer_Size à 50/80% de ma ram, etc...). J'ai également essayé "Apache + Varnish", "Nginx + Varnish", "Apache + Nginx en reverse proxy", malgré tout ça, rien à faire ça fini toujours par explosé quasiment dans les mêmes circonstances.



      Si une bonne âme se sent de me conseiller sur ce que je devrais faire, m'aiguiller ou carrément me proposer un audit, je suis preneur... Enfin, je vous met mes fichiers de config actuel ci-dessous :



      Merci à tous !





      My.ini :


      [mysqld]
      port = 3306
      socket = /var/run/mysqld/mysqld.sock
      bind-address = xxx.xxx.xxx.xxx

      skip-external-locking
      max_connections = 500
      key_buffer_size = 10G
      max_allowed_packet = 1M
      table_open_cache = 4
      sort_buffer_size = 64K
      read_buffer_size = 256K
      read_rnd_buffer_size = 256K
      net_buffer_length = 2K
      thread_stack = 128K
      table_cache = 2048
      query_cache_limit = 30M
      query_cache_size = 128M #(J'attends les 48h de Tuning-primer ici pour augmenter cette valeur)
      thread_cache_size = 20
      max_heap_table_size = 128M #(J'attends les 48h de Tuning-primer ici pour augmenter cette valeur)


      [mysqldump]
      quick
      max_allowed_packet = 16M

      [mysql]
      no-auto-rehash
      # Remove the next comment character if you are not familiar with SQL
      #safe-updates

      [myisamchk]
      key_buffer_size = 8M
      sort_buffer_size = 8M

      [mysqlhotcopy]
      interactive-timeout





      Apache.conf :




      Timeout 300
      KeepAlive On
      MaxKeepAliveRequests 200
      KeepAliveTimeout 2
      HostnameLookups Off

      <IfModule mpm_prefork_module>
      StartServers 64
      MinSpareServers 64
      MaxSpareServers 128
      ServerLimit 1500
      MaxClients 1500
      MaxRequestsPerChild 300
      </IfModule>




      Résultat TuningPrimer (ça ne fait pas 48h là, donc ne veut pas dire grand chose mais j'vous le met quand meme...) :




      MySQL Version 5.5.30-1~dotdeb.0 x86_64

      Uptime = 0 days 12 hrs 50 min 46 sec
      Avg. qps = 124
      Total Questions = 5735385
      Threads Connected = 3

      Warning: Server has not been running for at least 48hrs.
      It may not be safe to use these recommendations

      To find out more information on how each of these
      runtime variables effects performance visit:
      http://dev.mysql.com/doc/refman/5.5/en/server-system-variables.html
      Visit http://www.mysql.com/products/enterprise/advisors.html
      for info about MySQL's Enterprise Monitoring and Advisory Service

      SLOW QUERIES
      The slow query log is NOT enabled.
      Current long_query_time = 10.000000 sec.
      You have 0 out of 5735409 that take longer than 10.000000 sec. to complete
      Your long_query_time seems to be fine

      BINARY UPDATE LOG
      The binary update log is NOT enabled.
      You will not be able to do point in time recovery
      See http://dev.mysql.com/doc/refman/5.5/en/point-in-time-recovery.html

      WORKER THREADS
      Current thread_cache_size = 20
      Current threads_cached = 17
      Current threads_per_sec = 0
      Historic threads_per_sec = 0
      Your thread_cache_size is fine

      MAX CONNECTIONS
      Current max_connections = 500
      Current threads_connected = 4
      Historic max_used_connections = 39
      The number of used connections is 7% of the configured maximum.
      You are using less than 10% of your configured max_connections.
      Lowering max_connections could help to avoid an over-allocation of memory
      See "MEMORY USAGE" section to make sure you are not over-allocating

      INNODB STATUS
      Current InnoDB index space = 0 bytes
      Current InnoDB data space = 0 bytes
      Current InnoDB buffer pool free = 98 %
      Current innodb_buffer_pool_size = 128 M
      Depending on how much space your innodb indexes take up it may be safe
      to increase this value to up to 2 / 3 of total system memory

      MEMORY USAGE
      Max Memory Ever Allocated : 10.29 G
      Configured Max Per-thread Buffers : 406 M
      Configured Max Global Buffers : 10.26 G
      Configured Max Memory Limit : 10.66 G
      Physical Memory : 39.38 G
      Max memory limit seem to be within acceptable norms

      KEY BUFFER
      Current MyISAM index space = 88 M
      Current key_buffer_size = 10.00 G
      Key cache miss rate is 1 : 660
      Key buffer free ratio = 80 %
      Your key_buffer_size seems to be fine

      QUERY CACHE
      Query cache is enabled
      Current query_cache_size = 128 M
      Current query_cache_used = 43 M
      Current query_cache_limit = 30 M
      Current Query cache Memory fill ratio = 34.20 %
      Current query_cache_min_res_unit = 4 K
      MySQL won't cache query results that are larger than query_cache_limit in size

      SORT OPERATIONS
      Current sort_buffer_size = 64 K
      Current read_rnd_buffer_size = 256 K
      Sort buffer seems to be fine

      JOINS
      Current join_buffer_size = 132.00 K
      You have had 2 queries where a join could not use an index properly
      You should enable "log-queries-not-using-indexes"
      Then look for non indexed joins in the slow query log.
      If you are unable to optimize your queries you may want to increase your
      join_buffer_size to accommodate larger joins in one pass.

      Note! This script will still suggest raising the join_buffer_size when
      ANY joins not using indexes are found.

      OPEN FILES LIMIT
      Current open_files_limit = 65536 files
      The open_files_limit should typically be set to at least 2x-3x
      that of table_cache if you have heavy MyISAM usage.
      Your open_files_limit value seems to be fine

      TABLE CACHE
      Current table_open_cache = 2048 tables
      Current table_definition_cache = 400 tables
      You have a total of 253 tables
      You have 311 open tables.
      The table_cache value seems to be fine

      TEMP TABLES
      Current max_heap_table_size = 128 M
      Current tmp_table_size = 16 M
      Of 65393 temp tables, 38% were created on disk
      Perhaps you should increase your tmp_table_size and/or max_heap_table_size
      to reduce the number of disk-based temporary tables
      Note! BLOB and TEXT columns are not allow in memory tables.
      If you are using these columns raising these values might not impact your
      ratio of on disk temp tables.

      TABLE SCANS
      Current read_buffer_size = 256 K
      Current table scan ratio = 388 : 1
      read_buffer_size seems to be fine

      TABLE LOCKING
      Current Lock Wait ratio = 1 : 21
      You may benefit from selective use of InnoDB.
      If you have long running SELECT's against MyISAM tables and perform
      frequent updates consider setting 'low_priority_updates=1'
      If you have a high concurrency of inserts on Dynamic row-length tables
      consider setting 'concurrent_insert=ALWAYS'.

    • By vespa
      Bonjour,

      Je n'arrives pas à bâtir une requête.. J'ai une table "items" qui comportent plusieurs champs : name, description, date... Certaines lignes sont en doubles c'est à dire même "name", même "description" seul la date change

      Je dois supprimer tous les doublons en gardant le "name", "description" ayant la date la plus récente... J'ai passé mon dimanche sur ce SQL. Je précise que cette table est sur DB2 et que je n'ai aucun pouvoir dessus, je dois juste faire ce nettoyage. Merci d'avance pour votre aide.
×
×
  • Create New...