2014-02-19 148 views
3

說我在PHP中有這個數組。Riak:快速獲取多個項目

$ids = [ 
    246, 
    8362, 
    5241, 
    2586, 
    6548, 
    9372, 
    28504, 
    14, 
    5729 
]; 

這些數組元素對應於bucket'articles'中的項目,有時這個數組可能有1000個元素深度。

目前,我通過他們都通過1

$articles = []; 
foreach($ids as $id) 
{ 
    $articles[] = Riak::get("articles.$id"); 
} 

循環,拉出1中的數據這是比我更想花當IDS的名單會很長的時間。

有更快的方式從Riak存儲桶中提取項目列表嗎?我查了一下,map-reduce很有用,但顯然會導致比我順序GET請求更多的開銷。

我知道最有可能的答案是「這完全是你做到這一點的唯一方法。」但我希望有一個超級天才從左邊的領域中跳出來,讓我看到一些神奇的東西。

回答

2

不幸的是,從Riak高效地獲取大量記錄非常困難,因爲它們遍佈在集羣中並且必須單獨檢索。一些客戶端庫最近得到了客戶端multi-get的支持,它允許使用多個連接並行獲取對象,但我認爲這還沒有達到PHP客戶端。

使用mapreduce來做到這一點將減少對數據庫的調用次數,但不會導致法定讀數,因爲它只查詢覆蓋的一組分區。然而,Mapreduce是一種查詢數據的相當廣泛的方式,不能像直接訪問密鑰那樣擴展或執行。

如果這是一種常見操作,您需要執行此操作,這可能表示您的數據模型過於標準化,並且您可能需要取消規範化以便更好地支持您的應用程序及其訪問模式。

準確地說,如何最好地做到這一點需要關於您的數據以及您的訪問和查詢模式的知識。一種方法可能是將多篇文章與已知和可預測的關鍵字一起存儲在一個單獨的對象中,例如,一個固定範圍的文章ID。這將使得檢索文章更加高效,因爲需要讀取的對象數量少得多,但是在更新和插入時可能會使您的複雜性變得更加複雜。

另一種選擇是通過複製數據來解除歸一化。如果你只需要文章中的一些信息,就可以將這些數據存儲在專門用於有效服務這些查詢的單獨對象中。

Riak通常比使用更多的信息檢索更大的對象並在應用程序級別進行篩選要比試圖從數據庫中準確獲取所需的記錄更好。

+0

我結束了在考慮我們如何存儲數據很好看。對數據進行反規範化最終成爲更好的方法。有些數據可能並不像我們期望的那樣是最新的,但對於我們來說,儘可能快地檢索數據並不那麼重要。謝謝你的回答,這正是我需要的。 – castis

1

基於https://github.com/basho/riak-php-client PHP例子:

/** 
    * Retrieve JSON-encoded objects from Riak. 
    * @param array(int) $keys - List of the key. 
    * @return RiakObjects 
    */ 
    public function multiGet($keys) { 
     if (!$keys || !count($keys)) 
      return array(); 
     $query = null; 
     foreach ($keys as $key) { 
      if ($query) { 
       $query->add($this->getBucketName(), $key); 
      } else { 
       $query = $this->riak->add($this->getBucketName(), $key); 
      } 
     } 
     $results = $query->map(('function(riakObject){return [{"key":riakObject.key, "document":riakObject.values}];}'))->run(); 
     if (!$results || !count($results)) { 
      return array(); 
     } 

     $objects = array(); 
     foreach ($results as $data) { 
      if (isset($data->key) && isset($data->document[0]->data) && !empty($data->document[0]->data)) { 
       $object = json_decode($data->document[0]->data, true); 
       if ($object) { 
        $objects[$data->key] = $object; 
       } 
      } 
     } 
     return $objects; 
    } 
+0

+1用於使用我正在尋找的方法進行連接,但不幸的是,它仍然執行得太慢以至於我不喜歡。我最終以不同的格式存儲數據。我知道這是人們正在尋找的相當普遍的事情,我希望這對其他人有用。 – castis

+0

該方法使用mapreduce檢索多個對象。值得指出的是,這是一個相當昂貴的操作,其缺點是不會導致法定讀數(將其視爲讀取R = 1且notfound_ok = true)。 –