Necesito filtrar una lista por si la persona tiene una cita. Esto se ejecuta en 0,09 segundos.
select personid from persons p where EXISTS (SELECT 1 FROM appointments a WHERE a.personid = p.personid);Como uso esto en más de una consulta y en realidad contiene otra condición, me pareció conveniente poner el filtro en una función, así que tengo
CREATE FUNCTION `has_appt`(pid INT) RETURNS tinyint(1) BEGIN RETURN EXISTS (SELECT 1 FROM appointments WHERE personid = pid); ENDEntonces puedo usar
select personid from persons where has_appt(personid)Sin embargo, suceden dos cosas inesperadas. En primer lugar, la declaración que utiliza la función has_appt() ahora tarda 2,5 segundos en ejecutarse. Sé que hay una sobrecarga en una llamada de función, pero esto parece extremo. En segundo lugar, si ejecuto la declaración repetidamente, tarda unos 5 segundos más cada vez, por lo que para la cuarta vez, tarda más de 20 segundos. Esto sucede independientemente de cuánto tiempo espere entre intentos, pero almacenar la función nuevamente restablece el tiempo a 2,5 segundos. ¿Qué puede explicar la lentitud progresiva? ¿Qué estado puede verse afectado simplemente ejecutándolo varias veces?
Sé que la solución es olvidar la función e incorporarla en mis consultas, pero quiero comprender el principio para evitar volver a cometer el mismo error. Gracias de antemano por su ayuda.
Estoy usando MySQL 8 y Workbench.
Su consulta original puede ser reemplazada y acelerada por,
SELECT personid FROM appointments;Pero la consulta parece tonta: ¿por qué querrías una lista de todas las identificaciones de personas con citas, pero sin información sobre ellas? ¿Quizás simplificaste demasiado la consulta?
Si una persona pudiera tener múltiples citas, entonces esto sería necesario y podría no ser tan rápido:
SELECT DISTINCT personid FROM appointments; En cuanto a por qué la función es tan lenta... La optimización no ve lo que hay dentro de la función. Así que select personid from persons where has_appt(personid) recorre toda la tabla de persons , llamando a la función repetidamente.