Estrategias de fetch Sistemas de persistencia de objetos Fetch Forma de recuperar objetos de la BDD y meterlos en contexto de persistencia En memoria los objetos forman un grafo por sus asociaciones Recorrer el grafo (navegar las asociaciones) es la forma natural de los modelos Orientados a Objetos Pero ¿cuándo y cómo se cargan en memoria? nov-08 Alberto M.F.A. alb@uniovi.es 2 Estrategia de fetch ¿Cuándo se suben de la BDD? Los objetos asociados con un objeto dado Dos momentos: nov-08 LAZY: se cargan en el momento que se necesiten EAGER: se cargan al cargar el objeto que las asocia Alberto M.F.A. alb@uniovi.es 3 Estrategias de fetch ¿Cómo se cargan? (los asociados) Ya sea LAZY o EAGER, en el momento que se decide cargarlos ¿cómo? Varios tipos: nov-08 Batch prefetch Subselect Eager JOIN Eager Select Ajustes Hibernate Alberto M.F.A. alb@uniovi.es 4 Lazy load con proxies nov-08 Es un proxy No se ha hecho select a la BDD Alberto M.F.A. alb@uniovi.es ¡ No selects ! 5 Lazy load de asociaciones nov-08 Las asociaciones son proxies -ToOne: Se cargan al refenrenciarlos -ToMany: Al acceder a cualquier método de la colección Alberto M.F.A. alb@uniovi.es 6 Configuración lazy: posibilidades En JPA por defecto: LAZY: asociaciones –ToMany EAGER: asociaciones –ToOne Posibilidades: Desactivar lazy para la clase nov-08 Todas las cargas de esa clase serán siempre eager Ajuste demasiado grueso -ToOne lazy -ToMany eager Alberto M.F.A. alb@uniovi.es 7 Desactivar la carga lazy de una clase Ya no carga proxy Al cargar el Item se cargan todos los usuarios relacionados por cualquier asociación nov-08 Alberto M.F.A. alb@uniovi.es 8 Carga eager nov-08 Alberto M.F.A. alb@uniovi.es 9 ¿Cómo cargar las asociaciones? Poco eficiente, el problema de las n+1 consultas nov-08 Alberto M.F.A. alb@uniovi.es 10 Prefetch en lotes Ajuste: tamaño del lote Cuando se necesite hacer carga se suben en lotes de hasta el tamaño indicado Inconvenientes Puede realizar cargas que después no se van a usar El tamaño del lote requiere ajuste min(tamaño lote, los proxies User sin inicializar) nov-08 Alberto M.F.A. alb@uniovi.es 11 Prefetch en lotes nov-08 Alberto M.F.A. alb@uniovi.es 12 Prefetch con subselects Se realiza una segunda select que incluye a la primera como subselect No necesita ajustes Ideal si se va a recorrer toda la colección (o size(), contains()) nov-08 Alberto M.F.A. alb@uniovi.es 13 Prefetch con subselects nov-08 Alberto M.F.A. alb@uniovi.es 14 Eager JOIN Solo para estrategias EAGER Por defecto en colec. EAGER en JPA con Hibernate Atención a colecciones paralelas: ¡Producto cartesiano ! nov-08 Alberto M.F.A. alb@uniovi.es 15 Eager JOIN nov-08 Alberto M.F.A. alb@uniovi.es 16 Eager con SELECT Se lanza una segunda select en vez de JOIN para evitar producto cartesiano nov-08 Alberto M.F.A. alb@uniovi.es 17 Guía de optimización Activar el log SQL en persistence.xml Dejar todas las opciones por defecto. Ejecutar cada caso de uso observando el log para detectar cuales son los que generan un tráfico anómalo. nov-08 Alberto M.F.A. alb@uniovi.es 18 Guía de optimización (2) Si hay mucho tráfico: Ajustes en las queries. nov-08 Si el tráfico se genera en algunos casos de uso concretos se puede mejorar el rendimiento dinámico solo para ellos. Suele ser la mejor estrategia. Emplear left join fetch o join fetch en las queries que generan más tráfico Alberto M.F.A. alb@uniovi.es 19 Guía de optimización (3) Si sigue habiendo mucho tráfico: Ajustes en los ficheros de mapeo nov-08 Si son muchos los casos de uso afectados ajustar ficheros de mapeo (no es habitual). Para -to-one ponerFetchType.LAZY y batchsize=”<número>” Colecciones de pocos elementos lazy=”false” y fetch=”subselect” Alberto M.F.A. alb@uniovi.es 20 Guía de optimización (4) Ajustes en los ficheros de mapeo nov-08 En caso necesario (muy raro y en general desaconsejado) se puede poner fetch=”join” en colecciones xxxx–to-many. Ojo colecciones paralelas. Atención a los caminos fetch=”join” que se forman al mapear varias asociaciones así. Se pueden cargar grafos muy profundos lo que supone subir muchos objetos a memoria. Se puede usar la propiedad max_fetch_depth para establecer el camino máximo. Alberto M.F.A. alb@uniovi.es 21