2012-11-04 10 views
5

Weź ten kawałek kodu jako przykład:Yii - Czy buforowanie zależności bazy danych działa w wielu operacjach?

public function actionPostOneWay($postId) 
{ 
    $dependency = new CDbCacheDependency('SELECT publish_date FROM posts WHERE id = :post_id;'); 
    $dependency->params = array('post_id'=>$postId); 
    $post = Post::model()->cache(59, $dependency)->findByPk($postId); 

    // process post one way 
} 

public function actionPostAnotherWay($postId) 
{ 
    $dependency = new CDbCacheDependency('SELECT publish_date FROM posts WHERE id = :post_id;'); 
    $dependency->params = array('post_id'=>$postId); 
    $post = Post::model()->cache(59, $dependency)->findByPk($postId); 

    // process post another way 
} 

Więc dostępu /postOneWay i /postAnotherWay używać tego samego obiektu pamięci podręcznej, lub będą tworzyć obiekty cache własnych?

Odpowiedz

5

Próbowałem buforować to samo zapytanie w dwóch różnych akcjach i tak, użyty zostanie ten sam buforowany obiekt. Widać, że włączanie CProfileLogRoute w pliku konfiguracyjnym aplikacji.

Patrząc na kod źródłowy klasy CActiveRecord stwierdziłem, że metoda public function findByPk($pk,$condition='',$params=array()) (i inne metody zapytań) używają protected function query($criteria,$all=false). Ten z kolei bazuje na klasie private function queryInternal($method,$mode,$params=array()) z klasy CDbCommand, gdzie Yii dokonuje buforowania z zapytaniami do bazy danych.

Jak widać klucz cache używany do przechowywania i odtwarzania wyników zapytań jest zdefiniowany następująco:

$cacheKey='yii:dbquery'.$this->_connection->connectionString.':'.$this->_connection->username; 
$cacheKey.=':'.$this->getText().':'.serialize(array_merge($this->_paramLog,$params)); 
if(($result=$cache->get($cacheKey))!==false) 
{ 
    Yii::trace('Query result found in cache','system.db.CDbCommand'); 
    return $result; 
} 

Ten klucz nie bierze instancję zależności cache pod uwagę. CDbCacheDependency służy tylko do określenia, czy coś zostało zmienione w bazie danych, a nowe zapytanie zostanie wykonane, aby zaktualizować pamięć podręczną. Powiedzieć więcej - jeśli podasz różne zapytania SQL do tworzenia CDbCacheDependency w dwóch działaniach tylko jeden z nich (wykonany pierwszy) będzie sensu podczas buforowania czasu ze względu na wystąpienie CDbCacheDependency są buforowane w odcinkach wraz z wyniku kwerendy:

if(isset($cache,$cacheKey)) 
    $cache->set($cacheKey, $result, $this->_connection->queryCachingDuration, $this->_connection->queryCachingDependency); 

buforowanie wystąpienie oceniano zależność może być postrzegane w public function set($id,$value,$expire=0,$dependency=null) metody CCache klasy:

if ($dependency !== null && $this->serializer !== false) 
    $dependency->evaluateDependency(); 

if ($this->serializer === null) 
    $value = serialize(array($value,$dependency)); 
elseif ($this->serializer !== false) 
    $value = call_user_func($this->serializer[0], array($value,$dependency)); 
+0

Wow! Nie spodziewałem się takiego poziomu szczegółowości. Dzięki! Większość ma sens. Jestem zdezorientowany w tej linii: "jeśli określisz różne SQL, aby utworzyć CDbCacheDependency w dwóch akcjach, tylko jeden z nich (wykonany jako pierwszy) będzie miał sens w czasie buforowania z powodu wystąpienia CDbCacheDependency jest buforowany serializowany wraz z wynikiem zapytania". Czy chcesz powiedzieć, że instancja zależności jest buforowana i ponownie używana? – HyderA

+0

Tak, miałem na myśli to dokładnie. Instancja Dependency będzie buforowana z wartością, a następnym razem, gdy wartość pamięci podręcznej ma być pobrana w 'if (($ result = $ cache-> get ($ cacheKey))! == false)' condition to wystąpienie będzie używane do określić, czy w zapytaniu bazy danych wykonawczym wystąpiły pewne zmiany i porównać wynik z wcześniej ocenianym (gdy ustawiono wartość pamięci podręcznej). Możesz przetestować go samodzielnie dodając 'CProfileLogRoute' do' log' komponentu konfiguracji aplikacji i ustawiając flagę 'enableProfile' dla' db' komponentu na 'true'. – Ezze

Powiązane problemy