Question

J'ai récemment travaillé sur une fonctionnalité de recherche de base de données et je voulais obtenir des informations comme les mots en moyenne par document (champ de texte, par exemple dans la base de données). La seule chose que j'ai trouvé jusqu'à présent (sans traitement dans la langue choisie en dehors du DB) est:

SELECT AVG(LENGTH(content) - LENGTH(REPLACE(content, ' ', '')) + 1)
FROM documents

Cela semble fonctionner * mais avez-vous d'autres suggestions? Je suis actuellement en utilisant MySQL 4 (l'espoir de passer à la version 5 pour cette application bientôt), mais suis aussi intéressé par des solutions générales.

Merci!

* Je peux imaginer que c'est une façon assez rude pour déterminer ce qu'il ne tient pas compte de HTML dans le contenu et analogues ainsi. C'est OK pour ce projet particulier, mais encore sont-il de meilleures façons?

Mise à jour: Pour définir ce que je veux dire par « mieux »: soit plus précis, effectue de façon plus efficace, ou plus « correcte » (facile à entretenir, bonnes pratiques, etc.). Pour le contenu dont je dispose, la requête ci-dessus est assez rapide et précis pour ce projet, mais je peut avoir besoin quelque chose de similaire à l'avenir (donc je demande).

Était-ce utile?

La solution

Les capacités de traitement de texte de MySQL ne sont pas assez bon pour ce que vous voulez. Une fonction stockée est une option, mais sera probablement lente. Votre meilleur pari pour traiter les données dans MySQL est d'ajouter un utilisateur défini fonction . Si vous allez construire une nouvelle version de MySQL de toute façon, vous pouvez également ajouter un fonction native .

La « bonne » façon est de traiter les données en dehors de la base de données depuis DB sont pour le stockage, le traitement non, et tout traitement lourd pourrait mettre trop d'une charge sur le SGBD. En outre, le calcul du nombre de mots en dehors de MySQL, il est plus facile de changer la définition de ce qui compte comme un mot. Que diriez-vous stocker le nombre de mots dans la base de données et la mise à jour quand un document est modifié?

Exemple fonction stockée:

DELIMITER $$
CREATE FUNCTION wordcount(str LONGTEXT)
       RETURNS INT
       DETERMINISTIC
       SQL SECURITY INVOKER
       NO SQL
  BEGIN
    DECLARE wordCnt, idx, maxIdx INT DEFAULT 0;
    DECLARE currChar, prevChar BOOL DEFAULT 0;
    SET maxIdx=char_length(str);
    SET idx = 1;
    WHILE idx <= maxIdx DO
        SET currChar=SUBSTRING(str, idx, 1) RLIKE '[[:alnum:]]';
        IF NOT prevChar AND currChar THEN
            SET wordCnt=wordCnt+1;
        END IF;
        SET prevChar=currChar;
        SET idx=idx+1;
    END WHILE;
    RETURN wordCnt;
  END
$$
DELIMITER ;

Autres conseils

Ceci est un peu plus rapide, mais juste un peu moins précis. Je l'ai trouvé 4% de lumière sur le compte, ce qui est correct pour les scénarios « Estimate ».

SELECT
    ROUND (   
        (
            CHAR_LENGTH(content) - CHAR_LENGTH(REPLACE (content, " ", "")) 
        ) 
        / CHAR_LENGTH(" ")        
    ) AS count    
FROM documents

Vous pouvez utiliser l'UDF word_count() de https://github.com/spachev/mysql_udf_bundle . Je Ported la logique de la réponse acceptée avec une différence que mon code ne supporte que charset latin1. La logique devrait être retravaillé pour soutenir d'autres jeux de caractères. En outre, les deux implémentations considèrent toujours un caractère non alphanumérique être un séparateur, qui ne peut toujours souhaitable -. Par exemple, est considéré comme « le livre de l'enseignant » à trois mots par les deux implémentations

La version UDF est, bien sûr, beaucoup plus rapide. Pour un test rapide, j'ai essayé à la fois sur un ensemble de données de Guttenberg projet composé de 9751 dossiers totalisant environ 3 Go. L'UDF a fait tous en 18 secondes, alors que la fonction stockée a pris 63 secondes pour traiter seulement 30 dossiers (dont UDF fait en 0,05 secondes). Ainsi, l'UDF est environ 1000 fois plus rapide dans ce cas.

UDF va battre toute autre méthode de la vitesse qui ne nécessite pas de modifier le code source MySQL. En effet, il a accès aux octets de chaîne en mémoire et peut fonctionner directement sur les octets sans les avoir à déplacer autour. Il est également compilé en code machine et fonctionne directement sur la CPU.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top