Melhorias de performance atacando apenas os mapeamentos do hibernate

Updated . Posted . Visible to the public.

Um dos grandes problemas de desempenho que uma aplicação pode enfrentar é o de acesso ao banco, pois como bem sabemos o acesso ao disco é muito mais lento que o acesso à memória.
Um ponto que pode ser atacado para prover mais performance à aplicação são os mapeamentos do hibernate. Quando se acessa um objeto que tem coleções de objetos tipo List's, Map's o hibernate vai buscar do banco todos os itens desta coleção o que pode ser muito lento dependendo da quantidade de registros que esta coleção contém e também da complexidade destes registros, pois pode haver uma 'reação em cadeia'.

    class Biblioteca {
        String nome
        List livros
    }

    class Livro {
        String titulo
        Autor autor
        List paginas
    }

    class Autor {
        String nome
    }

    class Pagina {
        int numero
    }

Biblioteca.hbm.xml










Livro.hbm.xml











Pagina.hbm.xml






Ex.: Meu objeto Biblioteca têm uma lista de Livros que por sua vez tem uma lista de Paginas, quando eu acessar o objeto Biblioteca a lista de Livros também virá e a de Paginas também.
Supondo que a lista de Livros do objeto Biblioteca tenha 100 elementos e a quantidade de páginas do Livro é também de 100 elementos (note que são listas de poucos elementos). Ao fazer o acesso à Biblioteca o hibernate trará todos os outros objetos o que daria um total de 10000 elementos, ou seja, o acesso a um simples objeto traria outros 10000 que talvez nem sejam necessários para mim em determinado momento, por exemplo se eu quiser saber apenas o nome da biblioteca, neste caso qual seria a utilidade de trazer todos estes elementos da minha base de dados?

Abaixo vou apresentar uma forma mais eficiente de escrever os mapeamentos com o objetivo de melhorar a performance da aplicação, fazendo com que ela faça a busca na base de dados apenas dos registros que precisarão ser acessados por você no momento. Claro que esta abordagem não vai resolver todos os problemas, pois como diz um amigo meu... É uma faca de dois legumes. Na primeira abordagem você terá todos os registros na memória com apenas um acesso ao disco, ao passo que na próxima será feito um acesso para cada registro.

Mas eu acredito que a forma que eu vou apresentar a seguir é mais eficiente porque apesar de se fazer mais acessos ao banco para obter um determinado registro há o ganho que se têm quando os objetos dos relacionamentos não são necessários para fazer a computação que se deseja no momento, e isso é bem comum.

Biblioteca.hbm.xml










Livro.hbm.xml

    <?xml version="1.0"?>
    <!DOCTYPE hibernate-mapping PUBLIC
    		"-//Hibernate/Hibernate Mapping DTD 3.0//EN"
    		"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
    <hibernate-mapping>
    	<class name="Livro" table="table_livro">
    		<property name="titulo" column="livro_titulo"/>
    		<many-to-one name="autor" column="livro_autor" fetch="select"/> 
//relacionamentos many-to-one não podem ser lazy="true". 
A forma de fazer com que eles sejam acessados apenas se necessário é colocando fetch="select"
    		<bag name="paginas" table="table_paginas" lazy="true" fetch="select">
    			<key column="pagina_livro"/>
    			<one-to-many class="Pagina"/>
    		</bag>
    	</class>
    </hibernate-mapping>

Pagina.hbm.xml






Com uma simples alteração no mapeamento dos objetos faria com que apenas os objetos necessários fossem buscados do banco de dados, no mesmo exemplo acima, ao acessar o objeto Biblioteca apenas ele seria retornado, os outros objetos seriam retornados caso fossem acessados, assim o acesso ao banco será feito para buscar apenas o que for necessário para a computação do momento (apenas os objetos que eu preciso serão trazidos).

Claro que a solução para os problemas de performance devido acesso ao banco não será sair mudando todos os mapeamentos para lazy, tem que fazer isso com moderação, pois se a coleção for constantemente acessada é mais vantajoso que a coleção seja trazida junto com o objeto, além do que propriedades lazy costumam causar bugs com os proxys do hibernate.

João Paulo
Last edit
Posted by João Paulo to ZeroGlosa (2013-01-11 13:58)