Pregunta

Hace poco he estado trabajando en algunas funciones de búsqueda de base de datos y quería obtener alguna información como las palabras promedio por documento (campo de texto, por ejemplo, en la base de datos). La única cosa que he encontrado hasta el momento (sin procesamiento en el idioma de su elección fuera de la DB) es:

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

Esto parece funcionar * pero no tiene otras sugerencias? Actualmente estoy usando MySQL 4 (espero que para mover a la versión 5 para esta aplicación en breve), pero también estoy interesado en soluciones generales.

Gracias!

* Me puedo imaginar que esta es una manera bastante duro para determinar esto, ya que no tiene en cuenta el contenido HTML en y similares también. Eso está bien para este proyecto en particular, pero de nuevo ¿Hay mejores maneras?

Actualización: Para definir lo que quiero decir con "mejor": ya sea más preciso, lleva a cabo de manera más eficiente, o es más (de fácil mantenimiento, buenas prácticas, etc.) "correcta". Para el contenido que tengo disponible, la consulta anterior es lo suficientemente rápido y es exacta para este proyecto, pero puede necesitar algo similar en el futuro (por lo que se solicita).

¿Fue útil?

Solución

Las capacidades de manejo de texto de MySQL no son lo suficientemente buenos para lo que quieres. Una función almacenada es una opción, pero probablemente será lenta. Su mejor opción para procesar los datos dentro de MySQL es añadir un usuario definido función. Si va a construir una nueva versión de MySQL de todos modos, también se puede añadir un función nativa .

La forma "correcta" es procesar los datos fuera de la base de datos desde el DB son para el almacenamiento, procesamiento no, y cualquier procesamiento pesada podría poner demasiado de una carga en el DBMS. Además, calculando el número de palabras fuera de MySQL hace que sea más fácil cambiar la definición de lo que se considera una palabra. ¿Qué hay de almacenar el número de palabras en la base de datos y su actualización cuando se cambia un documento?

Ejemplo función almacenada:

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 ;

Otros consejos

Esto es un poco más rápido, aunque sólo un poco menos precisa. He encontrado que 4% de luz en el recuento, lo cual está bien para escenarios "estimar".

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

Puede utilizar la UDF word_count() de https://github.com/spachev/mysql_udf_bundle . Porté la lógica de la respuesta aceptada con una diferencia que mi código sólo es compatible con juego de caracteres latin1. tendría que ser revisado a fin de apoyar a otros juegos de caracteres de la lógica. Además, ambas implementaciones siempre consideran un carácter no alfanumérico ser un delimitador, que puede que no siempre es deseable. - por ejemplo, "El libro de profesor" es considerada como tres palabras por ambas implementaciones

La versión UDF es, por supuesto, mucho más rápido. Para una prueba rápida He intentado tanto en un conjunto de datos de proyecto Guttenberg que consiste en 9751 registros de un total de aproximadamente 3 GB. La UDF hizo todo de ellos en 18 segundos, mientras que la función almacenada tomó 63 segundos para procesar sólo 30 registros (que UDF hace en 0,05 segundos). Por lo que la UDF es aproximadamente 1000 veces más rápido en este caso.

UDF le ganará a cualquier otro método de la velocidad que no implica modificar el código fuente de MySQL. Esto es debido a que tiene acceso a los bytes de cadena en la memoria y puede operar directamente en bytes sin que tengan que ser movido alrededor. También se compila en código máquina y se ejecuta directamente en la CPU.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top