From d952f8088142acdb81a0a977a3bdffdb793a47e6 Mon Sep 17 00:00:00 2001 From: Cerdic <cedric@yterium.com> Date: Fri, 1 Feb 2008 22:38:33 +0000 Subject: [PATCH] le petit cache de la recherche prend du galon et integre la base sql : - creation d'une table spip_recherches qui stockent les resultats par id/points pour chaque recherche - les requetes decriees par #1231 et consort disparaissent au profit d'une simple jointure La portabilite sql est a verifier pour cause : - d'une fonction HEX() reliquat des vieilles version mysql - dune jointure implicite ecrite en clause SELECT/WHERE dans le critere recherche --- ecrire/base/auxiliaires.php | 12 +++++++ ecrire/inc/prepare_recherche.php | 60 +++++++++++++------------------- ecrire/inc_version.php | 3 +- ecrire/maj/svn10000.php | 9 +++++ ecrire/public/criteres.php | 4 ++- 5 files changed, 51 insertions(+), 37 deletions(-) diff --git a/ecrire/base/auxiliaires.php b/ecrire/base/auxiliaires.php index 54bf82d970..cc819f8cbb 100644 --- a/ecrire/base/auxiliaires.php +++ b/ecrire/base/auxiliaires.php @@ -42,6 +42,15 @@ $spip_visites_articles = array( $spip_visites_articles_key = array( "PRIMARY KEY" => "date, id_article"); +$spip_recherches = array( + "recherche" => "BIGINT UNSIGNED NOT NULL", + "id" => "INT UNSIGNED NOT NULL", + "points" => "INT UNSIGNED DEFAULT '0' NOT NULL", + "maj" => "TIMESTAMP" ); + +$spip_recherches_key = array( + "PRIMARY KEY" => "recherche,id"); + $spip_referers = array( "referer_md5" => "bigint UNSIGNED NOT NULL", "date" => "DATE NOT NULL", @@ -272,6 +281,9 @@ $tables_auxiliaires['spip_mots_documents'] = array( $tables_auxiliaires['spip_meta'] = array( 'field' => &$spip_meta, 'key' => &$spip_meta_key); +$tables_auxiliaires['spip_recherches'] = array( + 'field' => &$spip_recherches, + 'key' => &$spip_recherches_key); $tables_auxiliaires['spip_versions'] = array( 'field' => &$spip_versions, 'key' => &$spip_versions_key); diff --git a/ecrire/inc/prepare_recherche.php b/ecrire/inc/prepare_recherche.php index 35665c35c3..913fc1e4fb 100644 --- a/ecrire/inc/prepare_recherche.php +++ b/ecrire/inc/prepare_recherche.php @@ -14,13 +14,13 @@ if (!defined("_ECRIRE_INC_VERSION")) return; include_spip('inc/rechercher'); +@define('_DELAI_CACHE_RECHERCHES',600); // Preparer les listes id_article IN (...) pour les parties WHERE // et points = des requetes du moteur de recherche // http://doc.spip.org/@inc_prepare_recherche_dist function inc_prepare_recherche_dist($recherche, $table='articles', $cond=false, $serveur='') { static $cache = array(); - static $fcache = array(); // si recherche n'est pas dans le contexte, on va prendre en globals // ca permet de faire des inclure simple. @@ -31,20 +31,22 @@ function inc_prepare_recherche_dist($recherche, $table='articles', $cond=false, if ($cond AND !strlen($recherche)) return array("''" /* as points */, /* where */ '1'); + + $rechercher = false; // Premier passage : chercher eventuel un cache des donnees sur le disque - if (!$cache[$recherche]['hash']) { - $dircache = sous_repertoire(_DIR_CACHE,'rech'); - $fcache[$recherche] = - $dircache . substr(md5($recherche),0,10).'.txt'; - if (lire_fichier($fcache[$recherche], $contenu)) - $cache[$recherche] = @unserialize($contenu); + if (!isset($cache[$recherche][$table])){ + $hash = md5($recherche . $table); + $res = sql_select('NOW()-maj AS fraicheur','spip_recherches',"recherche=0x$hash OR HEX(recherche)='$hash'",'','fraicheur DESC','0,1','',$serveur); + if ((!$row = sql_fetch($res)) + OR ($row['fraicheur']>_DELAI_CACHE_RECHERCHES)){ + $rechercher = true; + } + $cache[$recherche][$table] = array("points","(recherche=0x$hash OR HEX(recherche)='$hash')"); } - // si on n'a pas encore traite les donnees dans une boucle precedente - if (!$cache[$recherche][$table]) { - - $tables = liste_des_champs(); + if ($rechercher) { + //$tables = liste_des_champs(); $x = preg_replace(',s$,', '', $table); // eurk if ($x == 'syndic') $x = 'site'; $points = recherche_en_base($recherche, @@ -67,31 +69,19 @@ function inc_prepare_recherche_dist($recherche, $table='articles', $cond=false, $points = $p2; } - # calculer le {id_article IN()} et le {... as points} - if (!count($points)) { - $cache[$recherche][$table] = array("''", '0'); - } else { - $listes_ids = array(); - $primary = id_table_objet($table); - foreach ($points as $id => $p) - $listes_ids[$p['score']] .= ','.$id; - $select = ''; - foreach ($listes_ids as $p => $liste_ids) - $select .= "+ (case when (". - sql_in("$table.$primary", substr($liste_ids, 1),'',$serveur) - .") then $p else 0 end) "; - - $select = $select ? substr($select,1) : '0'; - $cache[$recherche][$table] = array($select, - '('.sql_in("$table.$primary", - array_keys($points),'',$serveur).')' - ); + // supprimer les anciens resultats de cette recherche et les resultats trop vieux avec une marge + // hash=0x$hash OR HEX(hash)='$hash' permet d'avoir une requete qui marche qu'on soit en mysql <4.1 ou >4.1 + // il y a des versions ou install de mysql ou il faut l'un ou l'autre selon le hash ... ! + sql_delete('spip_recherches','(maj<NOW()-'.(_DELAI_CACHE_RECHERCHES+100).") OR (recherche=0x$hash OR HEX(recherche)='$hash')",$serveur); + + // inserer les resultats dans la table de cache des recherches + if (count($points)){ + $values = ""; + foreach ($points as $id => $p){ + $values.= ",(0x$hash,".intval($id).",".intval($p['score']).")"; + } + sql_insert('spip_recherches',"(recherche,id,points)",substr($values,1),array(),$serveur); } - - // ecrire le cache de la recherche sur le disque - ecrire_fichier($fcache[$recherche], serialize($cache[$recherche])); - // purger le petit cache - nettoyer_petit_cache('rech', 300); } return $cache[$recherche][$table]; diff --git a/ecrire/inc_version.php b/ecrire/inc_version.php index 7be9d096f5..75793e92f8 100644 --- a/ecrire/inc_version.php +++ b/ecrire/inc_version.php @@ -292,7 +292,8 @@ $liste_des_forums = array( // (= numero SVN de leur derniere modif cassant la compatibilite) $spip_version_code = 11169; // version de la base SQL (= numero SVN de sa derniere modif) -$spip_version = 11171; +$spip_version = 11172; + // version de l'interface a la base $spip_sql_version = 1; diff --git a/ecrire/maj/svn10000.php b/ecrire/maj/svn10000.php index fbae401682..2c774ef775 100644 --- a/ecrire/maj/svn10000.php +++ b/ecrire/maj/svn10000.php @@ -23,4 +23,13 @@ $GLOBALS['maj'][10990] = array(array('upgrade_types_documents')); // Aller plus vite pour les vieilles versions en redeclarant une seule les doc unset($GLOBALS['maj'][10990]); $GLOBALS['maj'][11042] = array(array('upgrade_types_documents')); + +function maj_11172() { + global $tables_auxiliaires; + include_spip('base/auxiliaires'); + $v = $tables_auxiliaires[$k='spip_recherches']; + sql_create($k, $v['field'], $v['key'], false, false); +} +$GLOBALS['maj'][11172] = array(array('maj_11172')); + ?> diff --git a/ecrire/public/criteres.php b/ecrire/public/criteres.php index 093f844d1b..a5f5aef2bf 100644 --- a/ecrire/public/criteres.php +++ b/ecrire/public/criteres.php @@ -181,7 +181,9 @@ function critere_recherche_dist($idb, &$boucles, $crit) { $t = $boucle->id_table . '.' . $boucle->primary; if (!in_array($t, $boucles[$idb]->select)) $boucle->select[]= $t; # pour postgres, neuneu ici - $boucle->select[]= '$rech_select as points'; + $boucle->select[]= 'recherches.points as points'; + $boucle->from[]= 'spip_recherches as `recherches`'; + $boucle->where[]= "'recherches.id=".$boucle->id_table.".".$boucle->primary."'"; // et la recherche trouve $boucle->where[]= '$rech_where'; -- GitLab