Использование SQL для определения статистики количества слов в текстовом поле

StackOverflow https://stackoverflow.com/questions/748276

Вопрос

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

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

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

Спасибо!

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

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

Это было полезно?

Решение

Возможности 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 ;

Другие советы

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

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

Вы можете использовать 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.Это связано с тем, что он имеет доступ к строковым байтам в памяти и может работать непосредственно с байтами без необходимости их перемещения.Он также компилируется в машинный код и запускается непосредственно на центральном процессоре.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top