IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

SQL Oracle Discussion :

Optimisation requête SELECT - trouver des mots clefs dans un texte


Sujet :

SQL Oracle

  1. #1
    Membre régulier
    Inscrit en
    Janvier 2005
    Messages
    104
    Détails du profil
    Informations forums :
    Inscription : Janvier 2005
    Messages : 104
    Points : 123
    Points
    123
    Par défaut Optimisation requête SELECT - trouver des mots clefs dans un texte
    Salut ici,

    J'ai une table de 1 million de lignes (appelons-la "MaTable") qui contient un champs de type VARCHAR de longueur 280 ("MonChamps"). Ce champs contient une liste de mots clefs et a environ 900K valeurs distinctes. La table a aussi un index simple basé sur ce champs uniquement.

    Ce que j'aimerais faire, c'est pour un texte donné (de la taille d'une courte phrase "MaPhrase") retourner toutes les lignes de MaTable où une valeur de MonChamps est trouvée dans MaPhrase.

    Alors comme je suis un gros noob je fais comme ça :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    SELECT *
      FROM MaTable
     WHERE INSTR('MaPhrase', MonChamps) > 0;
    Ça marche - mais c'est pas très rapide.

    Après un coup d'œil sur ce sympathique tutoriel http://jpg.developpez.com/oracle/tuning/ , j'ai creusé un peu et remarqué que mon index n'est pas utilisé.
    À priori la fonction INSTR est le problème, et j'imagine que c'est pareil si j'utilise LIKE. Comme je suis sur Orcale 10G je n'ai pas accès non plus à l'index de type "text" (et de toute façon je ne sais pas si ça aiderait, vu que je ne cherche pas un texte à l'intérieur des valeurs de mon champs, mais l'inverse).

    Voilà, ça a l'air tout simple mais je cale.
    Quelqu'un a-t-il une idée ?

  2. #2
    Membre du Club
    Profil pro
    Inscrit en
    Novembre 2008
    Messages
    46
    Détails du profil
    Informations personnelles :
    Localisation : Royaume-Uni

    Informations forums :
    Inscription : Novembre 2008
    Messages : 46
    Points : 60
    Points
    60
    Par défaut
    Bonsoir,

    J'ai ecris un petit script qui au moins ferait usage de votre index :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    WITH wrk_matable AS (
    SELECT 'cle'       AS monchamps FROM dual 
    UNION ALL
    SELECT 'suis'      AS monchamps FROM dual
    UNION ALL
    SELECT 'invalide'  AS monchamps FROM dual
     )
    SELECT monchamps 
    FROM wrk_matable 
    WHERE monchamps IN ( 
                        SELECT SUBSTR ( ','||REPLACE(trim(' je suis la cle '), ' ', ',')||','
                        , INSTR ( ','||REPLACE(trim(' je suis la cle '), ' ', ',')||',', ',', 1, LEVEL ) + 1 
    		    , instr (','||REPLACE(trim(' je suis la cle '), ' ', ',')||',', ',', 1, level+1) 
    			- instr (','||REPLACE(trim(' je suis la cle '), ' ', ',')||',', ',', 1, level) -1 )            
    FROM dual 
    CONNECT BY LEVEL <= length(TRIM ('  je suis la cle     ')) - LENGTH(REPLACE(TRIM('  je suis la cle     '), ' ', ''))+1)
    Dites moi ce que vous en dites et si cela correspond a votre probleme ?
    Le script ne gere pas les phrases avec des caracteres speciaux tel que ";() etc. Il devrait gerer les virgules par contre.

  3. #3
    Expert éminent
    Avatar de pachot
    Homme Profil pro
    Developer Advocate YugabyteDB
    Inscrit en
    Novembre 2007
    Messages
    1 821
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 53
    Localisation : Suisse

    Informations professionnelles :
    Activité : Developer Advocate YugabyteDB
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Novembre 2007
    Messages : 1 821
    Points : 6 443
    Points
    6 443
    Billets dans le blog
    1
    Par défaut
    Bonjour,

    La meilleure solution serait de normaliser un peu le modèle: une atble avec une ligne pour chaque mot clé et pour chaque enregistrement de MaTable.

    Sinon, il y a Oracle Text

    Et si le nombre de mots clés par enregistrement est connu, il est possible d'avoir un index pour le 1er mot clé, un autre index pour le 2eme, etc en en indexant les fonctions INSTR qui vont bien, et de faire la requête avec des OR en utilisant les mêmes fonctions.

    Cordialement,
    Franck.
    Franck Pachot - Developer Advocate Yugabyte 🚀 Base de Données distribuée, open source, compatible PostgreSQL
    🗣 twitter: @FranckPachot - 📝 blog: blog.pachot.net - 🎧 podcast en français : https://anchor.fm/franckpachot

  4. #4
    Membre régulier
    Inscrit en
    Janvier 2005
    Messages
    104
    Détails du profil
    Informations forums :
    Inscription : Janvier 2005
    Messages : 104
    Points : 123
    Points
    123
    Par défaut
    Bonjour,

    Merci à vous deux pour votre aide, ça m'a donné des pistes pour améliorer mon appli.

    @Franck : En me relisant maintenant je crois que j'étais pas super clair - le champs contient des expressions que j'aimerais chercher telles quelles (en entier) dans un texte. Par exemple on peut imaginer une table qui contient une liste de noms (prénom plus nom de famille) et d'adresses, et j'aimerais pouvoir retrouver les adresses de tous les noms qui apparaissent dans un texte. C'est donc assez difficile de normaliser proprement, il peut y avoir des homonymes. Mais sur le long terme la meilleure solution serait peut-etre effectivement de préparer le terrain avec une table organisée en index et Oracle text.

    @Jorafali : ce code a l'air de bien fonctionner. Si j'ai bien compris, l'idée est de décomposer le texte en mots distincts, pour ensuite utiliser IN au lieu de LIKE, et donc faire marcher l'index. Avec une légère adaptation (pour retrouver aussi les combinaisons de 2 mots), ma requête tourne maintenant 5 fois plus vite, ce qui la rend tout à fait utilisable en production. Peut-être qu'avec des textes trop longs ça posera problème, mais pour 99% des cas c'est super.

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. Recupérer des mots clé dans un texte
    Par sabari dans le forum API standards et tierces
    Réponses: 2
    Dernier message: 02/12/2014, 10h27
  2. Insérer des mots clefs
    Par mikesquake dans le forum WordPress
    Réponses: 2
    Dernier message: 11/07/2010, 16h22
  3. [COM] Trouver des mots dans des PDF et autres documents ?
    Par zyongh dans le forum Bibliothèques et frameworks
    Réponses: 2
    Dernier message: 02/11/2006, 14h23
  4. détection mot clef dans un texte
    Par Royd938 dans le forum Algorithmes et structures de données
    Réponses: 2
    Dernier message: 19/04/2006, 18h12

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo