2011-04-30 79 views
3

我爲一個項目使用Doctrine 2,它會有很高的流量,並且我關心性能。我應該使用SQL限制還是不是性能原因?

有時我需要爲「分頁」目的加載很多實體。

示例:加載30,000篇發表的文章,我需要對這些結果進行分頁。

我想知道從數據庫加載如此多的行有多差,我可以使用LIMIT OFFSET sql語句,但是使用Doctrine 2 &分頁,實現Paginator適配器的開銷會更大(複雜存儲庫等),我可以使用一個簡單的Iterator適配器。

我想用一個好的緩存系統,它不應該是一個問題,但我不太確定。

順便說一下,你有關於緩存的任何提示?

回答

5

問題是,無論您使用哪種分頁解決方案,當您僅在頁面上顯示10個數據時,它實際上是否會加載30,000條記錄,還是僅載入需要的10條記錄?

如果它載入所有記錄只是爲了顯示10,那麼它是瘋了,你會有性能問題。任何實際值得使用的分頁解決方案都只會加載必要的記錄。另外,緩存並不是爲了解決這些類型的問題(即隱藏低效的算法)。編寫高效的代碼,速度很快,並且緩存將使您的響應速度更快。

最後,在一個典型的應用程序中,爲快速緩存分配的空間非常寶貴,所以不要用一堆你不需要的東西填滿它。保持緊密,以便您的緩存可以幫助儘可能快地製作儘可能多的應用程序。

+3

+1因爲您應該總是試圖從數據庫中獲取所需的信息。如果顯示10條記錄,則應提取10條記錄並使用count()來確定總計。或者如果第11條記錄存在,則獲取11條只記錄下一個按鈕的記錄。那麼你不需要數數。 – Arjan 2011-04-30 22:26:17

2

我以前沒有用過Doctrine,但是幾乎所有我看過的分頁方法絕對是不要加載完整的數據表來做分頁。以最基本的方式,您執行兩個查詢:一個計算記錄數(SELECT COUNT(*) ...),另一個查詢您需要的實際行數(SELECT * ... LIMIT ...)。 MySQL通過SQL_CALC_FOUND_ROWSFOUND_ROWS提供了很好的簡化。

但是,我曾經在一個項目上工作過一次,其中我需要的數據視圖涉及幾個具有數千萬記錄的表的一些相當複雜的聯接。執行COUNT(*)每次擊中8秒。我最終做的分頁是採取一個稍微更現實的方法:人們不用真的使用分頁。我的意思是,99%的時間不會超過第一頁,對吧?第10頁的人數很少,所以我改變了我的查詢來選擇第一個pageSize * 10 + 1記錄(在我的情況下爲201)。如果找到的記錄數是201,那麼我只需打印"You are on page 1 of 'lots'"

2

第2條原則使得它比其他情況更加痛苦。這是您爲ORM抽象支付的價格。

從數據庫中加載成千上萬行是不好。將它們全部水合(將它們變成實體)是可怕的壞

幸運的是,在DoctrineExtensions package有一些幫助。 Paginator擴展有助於抓取您需要的記錄片段,並僅保存那些實體。它這樣做是在三個查詢(一般情況下),這是你能爲希望最好的:

  1. 計數的匹配記錄
  2. 總數獲取的id S爲當前頁面的實體
  3. 獲取這些實體。

我已經在很多場合使用了擴展功能,並取得了很好的成功,對於我來說,對於成千上萬條記錄來說,它的表現非常好。目前尚不清楚它對於大型數據集或高流量場景的擴展程度如何,但這至少是一個開始。

+0

我沒有這個適配器,但是我知道DoctrineExtensions,但是,我使用了一個ServiceLayer,它使得這個適配器很難用於這個項目,但是很好的瞭解它 – JohnT 2011-05-02 21:02:03