Drupal API: drupal_render_cache_by_query [基於 DB Query,緩存你的查詢結果]

在網站中,經常有一些資料是相同的,並不必要每一次刷新都重建,若果這在一個大的 DB 資料庫,或一個複雜的 SQL 查詢中,很消耗資源。將查詢結果進行緩存是一個極好的解決方法。

Drupal 7 新增了 API drupal_render_cache_by_query() 來嘗試解決以上問題,主要用作緩存相同的 DB Query 的結果,為 DB Server 減輕查詢負擔。也就是說,當 DB Query 有改變,這會重新產生,否則這會直接由 DB 取得預早的緩存結果。

在 Drupal Core 中也只有在 Forum Block 中使用過一次。由於太新了,這唯一的一次實例也出錯了,以下是修正的版本示範:

function forum_block_view($delta = '') {
  $query = db_select('forum_index', 'f')
    ->fields('f')
    ->addTag('node_access');
  switch ($delta) {
    case 'active':
      $title = t('Active forum topics');
      $query
        ->orderBy('f.last_comment_timestamp', 'DESC')
        ->range(0, variable_get('forum_block_num_active', '5'));
      break;

    case 'new':
      $title = t('New forum topics');
      $query
        ->orderBy('f.created', 'DESC')
        ->range(0, variable_get('forum_block_num_new', '5'));
      break;
  }

  $block['subject'] = $title;
  // Cache based on the altered query. Enables us to cache with node access enabled.
  $block['content'] = drupal_render_cache_by_query($query, 'forum_block_view', CACHE_TEMPORARY, DRUPAL_CACHE_PER_ROLE);
  $block['content']['#access'] = user_access('access content');
  return $block;
}

上面,我們很清楚可見:

  • $query - db_select() Object (沒有執行 $query->execute())
  • forum_block_view - 這是一個 callback,將會呼叫 forum_block_view_pre_render 進行後續處理,並將處理好的數據作為緩存資料
  • CACHE_TEMPORARY - 緩存的時間性設定,可參考 cache_set() $expire
  • DRUPAL_CACHE_PER_ROLE - 這項是緩存的方式,比如:
    DRUPAL_CACHE_PER_ROLE (以角色區分)
    DRUPAL_CACHE_PER_PAGE (以每一頁面區分)。
    也可以兩者同時區分:"DRUPAL_CACHE_PER_PAGE | DRUPAL_CACHE_PER_ROLE" (既以頁面又以角色區分)。
    還有一個是 DRUPAL_CACHE_PER_USER。選擇那一個要按實際需求,過份濫用也有可能會造成 DB 壓力。

多善用 :)

4 個回應主題: Drupal API: drupal_render_cache_by_query [基於 DB Query,緩存你的查詢結果]

#1

Kay 研究得很細喔。

不知道在 Taiwan,有沒有那麼大型的網站,可以用到這個函數。

#2

嗯... 你說的也是,不知多少網站與模組會用到,很多都基本用舊有的 CACHE 就可以。

就以上 FORUM 例子,其實在 D7 中的 FORUM BLOCK 也幾乎不太必要這東西了 (D7 基於 forum_index 查詢,根據我之前測試,即使沒有這東西,過百萬主題也不會造成效能問題)。

#3

不错,drupal7真的改进了不少,可是有时候小型网站用d7,反而感觉更慢了?

#4

我沒有實質測試過,按看過的結果,簡單頁面,是 D6 快一點,但當讀取 10個 NODES 或 數十 COMMENTS 時,D7 有優化 (node_load_multiple),另外,如果 BLOCK 很多,我估計在 D7 是有優勢

此刻為止,Drupal 7 Dev 版本會比 7.0 stable 要快一點 (建議大家用 Dev version,很多修正)

寫下您的回覆

電子郵件不會公開