Ajuda com Cache

Olá a todos,

Estou com um problema que gostaria de amenizar.

Eu tenho um <select> com 5000 pacientes, que consome 180MB do servidor quando é carregado.

Queria uma solução assim, com exemplos:

  1. Fazer um cache dessa consulta, pra não ter que carregar sempre, mais quero que o cache não fica se atualizando por hora ou minutos, so quando sair do sistema OU…

  2. Como são pacientes, o sistema tem cadastro, gostaria que toda vez que atualiza-se ou cria-se o registro, ai sim renovar o cache dos registro.

E possivel fazer isso? Tive pouca experiência com cache, por isso estou com pouca noção de como fazer.

Cache com tempo "0" não expira, então acho que vc pode usar isso e por no onAfterSave do seu AR pra refazer o cache.

Tem o lançe de dependência que, pelo que eu entendi do CDbCacheDependency, expiraria o cache se uma determinada condição do SQL não fosse satisfeita. Não usei ele, mas, até onde eu sei, ele só serve pra expirar o cache tb. Não vai refazer ele pra vc.

Daniel,

Foi mais ou menos isso que pensei, expirar o cache onAfterSave().

Nen que a proximo carregamento demora, mais só pra criar novamente o cache já ta otimo.

Não querendo abusar muito, tem algum wiki que mostrar como criar cache de uma consulta?

Outra duvida, tem como eu colocar em cache 1 consulta? ou vai o sistema todo?

Valeu!

Gostaria de algumas sugestões pra cachiar essa consulta.


$paciente = Paciente::model()->findAll(array('order' => 'nome ASC', 'condition' => 'bloqueado = 0'));

Memoria Usada: 78,5MB

Adicionei o beginCache:


if ($this->beginCache($id, array('dependency' => array(

                                    'class' => 'system.caching.dependencies.CDbCacheDependency',

                                    'sql' => 'SELECT MAX(dataatualizacao) FROM paciente')))) {


                        $paciente = Paciente::model()->findAll(array('order' => 'nome ASC', 'condition' => 'bloqueado = 0'));


                        $this->endCache();

                    }



Memoria Usada: 48MB

Se ficasse nos 48MB tudo bem, mais na próxima atualização de página, volta aos 78,5MB.

Não tem como deixar fixo, e so atualizar quando receber delete, insert, update?

Já busquei no forum, e foi o máximo que conseguir, e no google no Blog Del Antonio(http://www.ramirezcobos.com/2011/02/15/yii-news-query-caching/) fala de uma função que só vai está disponivel na 1.1.7.

Mais usando o beginCache e o CDbCacheDependency, alguem tem um exemplo?

Valeu!

wiki nao tem … mas vou fazer um exemplo aqui. Hoje ainda disponibilizo.

Valeu Daniel,

Sobre o CDbConnection::cache(), já está disponivel no download:

Nightly Snapshot - yii-1.1-dev.tar.gz ([color="#FF0000"]not stable[/color]) - Built on Feb 20, 2011

http://yii.googlecode.com/svn/trunk/

Hoje chegando em casa, verifico se está estavel, e funcionando essa função.

Então vou esperar vc testar, até pq to enrolado hoje :)

Bom, vamos ao resultado do teste.

Localmente (php 5.3.x)

Antes:

Memoria Usada: 148MB

Depois:

Memoria Usada: 40MB

Usando a nova função CDbConnection::cache().

Exemplo:


$dependency = new CDbCacheDependency('SELECT MAX(dataatualizacao) FROM paciente');

$paciente = Paciente::model()->cache(0, $dependency)->findAll(array('order' => 'nome ASC', 'condition' => 'bloqueado = 0'));

Observação:

Esse foi a unica função que conseguir deixar estável, a outra beginCache(), ela fica variando não sei o por que, depois com calma vou testar novamente.

Servidor Web (Produção:php 5.2.15)

Antes:

Memoria Usada: 148,75MB

Depois:

Memoria Usada: 11MB

Usando a nova função CDbConnection::beginCache().

Exemplo 1:




                    if ($this->beginCache($id, array('dependency' => array(

                                    'class' => 'system.caching.dependencies.CDbCacheDependency',

                                    'sql' => 'SELECT MAX(dataatualizacao) FROM paciente')))) {


                    $paciente = Paciente::model()->findAll(array('order' => 'nome ASC', 'condition' => 'bloqueado = 0'));

                        

                    $paciente = CHtml::listData($paciente, 'codpaciente', 'codigonome');

                    echo CHtml::dropDownList('codpaciente', $_GET["codpaciente"], $paciente, array(

                        'prompt' => 'Selecione',

                        'class' => 'select w400px',

                    ));

                        $this->endCache();

                    }






Exemplo 2:

AtendimentoController.php




public function getTbCatalogDependency() {

        $dbDepend = new CDbCacheDependency("SELECT UPDATE_TIME FROM information_schema.tables WHERE TABLE_SCHEMA = :schema AND TABLE_NAME = :table");


        $dbName = explode(';', Yii::app()->db->connectionString); //mysql:host=$dbhost;dbname=$dbname

        $dbName = explode('=', $dbName[1]);

        $dbDepend->params = array(':schema' => $dbName[1], ':table' => 'paciente');


        return $dbDepend;

    }



view/atendimento/_form.php




                    if ($this->beginCache($id, array('dependency' => $this->getTbCatalogDependency()))) {


                    $paciente = Paciente::model()->findAll(array('order' => 'nome ASC', 'condition' => 'bloqueado = 0'));

                        

                    $paciente = CHtml::listData($paciente, 'codpaciente', 'codigonome');

                    echo CHtml::dropDownList('codpaciente', $_GET["codpaciente"], $paciente, array(

                        'prompt' => 'Selecione',

                        'class' => 'select w400px',

                    ));

                        $this->endCache();

                    }






Observação:

Fique surpreso pelos 11MB do resultado, percebi que o CDbConnection::cache() só deve funcionar no php 5.3, testei com cache(1000) e outras variações e não cachio o resultado.

Outro detalhe, para que funcione o cache do banco de dados, tem que incluir no arquivo de configuração o cache CDbCache.




'components' => array(

        ...

        'cache'=>array(

      		'class'=>'system.caching.CDbCache',

    	),



Outra observação que tive aqui.

Quando usei o CDbConnection::cache(), eu só fiz na consulta, eu to achando que por não está usando o CDbConnection::beginCache() que envolveu o CHtml::listData() e o CHtml::dropDownList(), por isso ele não ta cacheando tudo.

Depois em casa verifico essa possibilidade de ser isso.