Open messianos opened 11 years ago
Si además que tenemos varios accesos a disco (y el procesamiento). Creo que tiene sentido, además la actualización del "accepted_solution_id" no creo que sea muy recurrente.
Típico trade-off entre espacio y tiempo de ejecución.
Ventajas: -Las búsquedas son más rápidas.
Desventaja: -Un "puntero" extra por cada solución.
Creo que vale la pena en este caso agregar ese campo.
De todas formas planteo una alternativa de diseño para que la pensemos:
En lugar de tener un campo accepted_solution_id en Problem y un campo id_of_problem_solved_by_this en Solution, se podría agregar una tabla que mantenga ambos pares (llámese por el momento solved_problem).
La búsqueda sería
SELECT count(*) FROM Solution JOIN solved_problem WHERE Solution.creator_user_name LIKE BINARY 'user_name'
La búsqueda de los IDs de los problemas resueltos por un cierto usuario se obtendría como:
SELECT Problem.id, Problem.description FROM Solution JOIN solved_problem JOIN Problem WHERE Solution.creator_user_name LIKE BINARY 'user_name'
Ventajas: -Evitás un campo extra en cada Solution y en cada Problem (que en general va a ser NULL). -La cantidad de pares en solved_problem va a ser más bien menor. Esto puede ser eficiente a la hora de hacer JOIN (?).
Desventajas: -Requiere un JOIN por cada búsqueda.
Aclaro que en la otra alternativa, para obtener los "links" a los problemas resueltos por un cierto usuario también necesitás hacer un JOIN (porque en general no te va a bastar con obtener el ID del problema resuelto, sino que se va a requerir también su descripción por una cuestión de elegancia). Este JOIN sería entre las tablas Problem y Solution directamente (haciendo coincidir Problem.accepted_solution_id con Solution.id). Puedo estar equivocado, pero ¿esto no es MUY ineficiente? ¿Hacer Solution JOIN solved_problem JOIN Problem es más eficiente? (habría que leer la documentación y ver si en este caso el JOIN se hace en el orden planteado, es decir, primero haciendo el JOIN de una tabla grande con una chica y después de la tabla resultante con la otra grande).
En fin, esto es hilar fino. Puede que no valga la pena.
UNA COSA MÁS IMPORTANTE: estaría bueno ir anotando en un archivo en el directorio doc/ los cambios propuestos, para hacerlos todos a la vez. Teniendo en cuenta que la base de datos está en el hosting, cambiarla va a ser más "difícil". Por el diseño que hicimos, el único cambio que hay que hacer es en DatabaseInterface. Por ahora podemos implementar la solución ineficiente con el diseño actual, y después cambiarlo.
Estaba tratando de contar la cantidad de accepted_solution de un user y me encontre con que hacer la consulta para eso es bastante rebuscada e ineficiente.
Tenemos:
Solution(id, ...., username) Problem(id, accepted_solution, ...) problem_solutions(problem_id, solution_id)
para obtener las soluciones aceptadas habria q hacer:
accepted_solution => filter Solutions by the user => join con problem_solutions => join con Problem => filter Problem.accepted_solution_id = Solution.id
no es mucho? lo vamos a usar en el ranking y en el perfil. Ni hablar de listar las accepted_solutions y ponerle el link al problema.
No seria mejor poner un "id_of_problem_solved_by_this" y actualizarlo cada vez que se actualiza "accepted_solution_id" de Problem? En ese caso el count seria:
SELECT count(*) FROM Solution WHERE creator_user_name = 'username' AND id_of_problem_solved_by_this NOT NULL
Mucho mas rapida...