Использование SQL для определения статистики количества слов в текстовом поле - PullRequest
19 голосов
/ 14 апреля 2009

Недавно я работал над некоторыми функциями поиска в базе данных и хотел получить некоторую информацию, например, среднее количество слов в документе (например, текстовое поле в базе данных). Единственное, что я нашел до сих пор (без обработки на языке выбора за пределами БД):

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

Кажется, это работает * но у вас есть другие предложения? В настоящее время я использую MySQL 4 (надеюсь перейти к версии 5 для этого приложения в ближайшее время), но мне также интересны общие решения.

Спасибо!

* Я могу себе представить, что это довольно грубый способ определить это, поскольку он не учитывает HTML в контенте и тому подобное. Это нормально для этого конкретного проекта, но опять же есть лучшие способы?

Обновление: Чтобы определить, что я имею в виду под «лучше»: либо более точным, более эффективным или более «правильным» (простым в обслуживании, хорошей практикой и т.д.) Для содержимого, которое у меня есть, приведенный выше запрос достаточно быстрый и точный для этого проекта, но в будущем мне может понадобиться нечто подобное (поэтому я и спросил).

Ответы [ 3 ]

40 голосов
/ 16 апреля 2009

Возможности обработки текста в MySQL недостаточно хороши для того, что вы хотите. Сохраненная функция является опцией, но, вероятно, будет медленной. Лучше всего обрабатывать данные в MySQL, добавляя пользовательскую функцию . В любом случае, если вы собираетесь построить более новую версию MySQL, вы также можете добавить встроенную функцию .

«Правильный» способ - это обработка данных вне БД, поскольку БД предназначены для хранения, а не для обработки, и любая тяжелая обработка может создать слишком большую нагрузку на СУБД. Кроме того, вычисление количества слов вне MySQL облегчает изменение определения того, что считать словом. Как насчет хранения количества слов в БД и его обновления при изменении документа?

Пример сохраненной функции:

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 ;
2 голосов
/ 13 августа 2017

Это немного быстрее, но чуть менее точно. Я нашел это на 4% меньше на счетчике, что нормально для сценариев "оценки".

SELECT
    ROUND (   
        (
            CHAR_LENGTH(content) - CHAR_LENGTH(REPLACE (content, " ", "")) 
        ) 
        / CHAR_LENGTH(" ")        
    ) AS count    
FROM documents
0 голосов
/ 01 июня 2018

Вы можете использовать word_count() UDF из https://github.com/spachev/mysql_udf_bundle.. Я перенес логику из принятого ответа с той разницей, что мой код поддерживает только кодировку latin1. Логика должна быть переработана для поддержки других кодировок. Кроме того, обе реализации всегда рассматривают не алфавитно-цифровой символ как разделитель, что может быть не всегда желательно - например, «книга учителя» считается тремя словами в обеих реализациях.

Версия UDF, конечно, значительно быстрее. Для быстрого теста я попробовал оба набора данных из Project Guttenberg, состоящих из 9751 записей общим объемом около 3 ГБ. UDF сделал все это за 18 секунд, в то время как сохраненная функция заняла 63 секунды, чтобы обработать только 30 записей (что UDF делает за 0,05 секунды). Таким образом, в этом случае UDF примерно в 1000 раз быстрее.

UDF превзойдет любой другой метод по скорости, который не включает изменение исходного кода MySQL. Это потому, что он имеет доступ к строковым байтам в памяти и может работать непосредственно с байтами без необходимости их перемещения. Он также компилируется в машинный код и запускается непосредственно на процессоре.

...