Sphinx en PHP: Aumenta las búsquedas de tu site (Parte 1)

Actualmente nuestras páginas web contienen gran cantidad de información. Tratar correctamente esta información se convierte en un problema mediante las tecnologías de base de datos habituales.

La mayoría de webs implementan un buscador genérico que se traduce en una consulta de texto libre mediante el motor de base de datos. Si bien los gestores tipo MySQL o SQLServer son muy buenos buscando y ordenando en campos numéricos su rendimiento se degrada tratando con campos de texto.

En nuestro ejemplo de hoy trataremos con una tabla de dos millones de registros que contienen los datos de profesionales médicos. Entre otros guardamos el nombre, apellidos, centro académico, especialidad, etc. Nuestra base de datos se gestiona mediante el motor de MySQL.

Podemos ver a continuación un pequeño extracto del tipo de datos con los que trataremos.

Imaginemos que nuestra web es un directorio médico de recursos humanos en el que mostramos información de posibles candidatos. Las búsquedas pueden hacerse por palabras simples o bien con condicionantes.

Como primera búsqueda nos interesaría conocer cuantos se han educado en un centro universitario (UNIVERSITY en inglés)

Para ello nuestra web le solicitaria al MySQL los datos mediante la consulta:

mysql> select count(*) t from medical where Med_sch REGEXP 'UNIVERSITY';
+--------+
| t      |
+--------+
| 877437 |
+--------+
1 row in set (4.62 sec)

Realizar esta consulta directamente en el campo de texto tarda mas de 4 segundos en completarse.

Imaginemos que no solo queremos saber los que han cursado estudios en una universidad, queremos que el sistema nos diga también los profesionales que se han educado en un colegio mayor (COLLEGE).

En nuestro sistema sabemos que para indicar que queremos especificar la condición  «O» utilizamos el caracter «|» (sin las comillas).

De esta manera nuestra petición se convierte en esta consulta:

mysql> select count(*) t from medical where Med_sch REGEXP 'UNIVERSITY|COLLEGE';
+---------+
| t       |
+---------+
| 1087615 |
+---------+
1 row in set (7.04 sec)

Como vemos, la complejidad de la pregunta ha aumentado y con ello el tiempo que ha tardado el motor de MySQL en obtener la respuesta.

Queremos ser mas específicos todavía y le volvemos a preguntar a nuestro buscador por profesionales que se hayan educado en Universidades o Colegios Mayores que se llamen Houston. Queremos que nos de resultados del estilo «UNIVERSITY OF HOUSTON» o «SOURTHERN COLLEGE OF OPTOMETRY OF HOUSTON».

Para especificar esta condición le diremos al buscador que nos busque UNIVERSIDAD ó COLLEGE y que a continuación aparezca la palabra HOUSTON.

Así, la consulta a la base de datos se convertiria en:

mysql> select count(*) t from medical where Med_sch REGEXP '(UNIVERSITY|COLLEGE).+HOUSTON';
+-------+
| t     |
+-------+
| 14124 |
+-------+
1 row in set (16.37 sec)

Observamos que el tiempo de respuesta a esta petición es muy elevado. En una web normal deberíamos añadirle el tiempo de procesado y generación del html más su presentación en el navegador.

Vamos a comparar las mismas peticiones utilizando el motor de Sphinx. Profesionales que cursaron sus estudios en una universidad.

> search "UNIVERSITY"
index 'ndx_medical_school_names': query 'UNIVERSITY ': returned 1000 matches of 877437 total in 0.061 sec

Bastante rápido, pero probemos con la segunda consulta en la que pedíamos los datos de profesionales en universidades y colegios mayores.

> search "UNIVERSITY|COLLEGE"
index 'ndx_medical_school_names': query 'UNIVERSITY|COLLEGE ': returned 1000 matches of 1087615 total in 0.155 sec

Vemos que también ha incrementado su tiempo de respuesta, pero sigue siendo realmente rápido.

Pongamos el motor de Sphinx a prueba con la tercera consulta. Recordemos que pedíamos los profesionales de universidades o colegios mayores pero que ademas apareciera la palabra Houston a continuación.

> search "(UNIVERSITY|COLLEGE).+HOUSTON"
index 'ndx_medical_school_names': query '(UNIVERSITY|COLLEGE).+HOUSTON ': returned 1000 matches of 14124 total in 0.064 sec

Como vemos el tiempo de respuesta es extremadamente bajo.

Haciendo números podremos ver de manera más clara la mejora de velocidad.

MySQL Sphinx Incremento
Consulta 1 4.62s 0.061s 75.7x
Consulta 2 7.04s 0.155s  45.4x
Consulta 3 16.37s 0.064s 255.8x

Comparando los resultados nos damos cuenta de que implementar una solución basada en Sphinx es altamente recomendable en páginas web que realizan consultas intensivas de texto en la base de datos.

En un próximo artículo profundizaremos en la manera de incorporar Sphinx en un proyecto realizado en PHP.