以前看過一篇關於程序上的小技巧的文章,作者給出了正確的(或者至少可以稱得上標準的)的解決方法,結尾他對這種技巧並不滿意,認爲是迫不得已才用的,等以後計算機發展了,可以使用“真實”的結果。我的想法和他截然相反,在我看來計算能力永遠也追不上實際需求,我們會在越來越多的地方使用各種“有損優化”。這個詞是我現想起來的,其實很多技巧都像 JPEG 標準一樣,無傷大雅的丟棄了那些難以察覺的細節。

任何列表類的東西(比方說站內消息、評論、論壇話題),最需要加緩存的地方有兩個,首要的是列表的第一頁,其次就是整個分類的計數(count(*) 之類,同時別跟我較真 InnoDB 下應該怎麼寫,下同)。順便再說句,我對評論緩存了第一頁後命中率高達 97%+,這是必須優化的地方。

計數的基本作用僅僅是計算頁碼,但畢竟每頁都需要顯示。每次計數有變化就應該在 memcache (increment 方法)裏和 mysql 字段(UPDATE += 1)裏都存,當然,這都不可靠,還要在後臺跑個計劃任務來修正(畢竟某些耗資源的功能確實需要,例如刪除某 spammer 在各論壇版塊留下的很多垃圾貼,這時計數沒必要立刻修正)。

但讓我奇怪的是很少有網站做排序上的優化:例如每頁 10 條評論(假設是評論,而論壇的排序跟它相反),有 300 條,分成 30 頁,那麼在列第 20 頁的時候不應該是 ORDER BY id DESC LIMIT 200, 10 而是 ORDER BY id ASC LIMIT 90, 10 。

這個方式的好處不僅僅是在排很深的頁時的消耗減半,計數和排序的兩種優化配合,能適應更多複雜的情況:

首先,計數被緩存,釋放了壓力,但不再精確,這會導致頁數不準,實際有 30 頁的時候,可能被記成了 32 頁或者 28 頁,顯示效果可能就是最後多出兩頁空白頁,或者少了兩頁(如果是論壇回貼,少兩頁最新的回覆可是大問題)。而反向 ORDER BY 會把這種錯誤從尾部挪到的中間的頁碼,可能是一個 15、16 兩頁有大半是相同的,也可能是第 15、16 頁之間有很多內容消失。他們的區別在於,最老和最新的內容很容易被點到,卻很少有人會直接看中間的頁碼,而這種優化恰恰是針對大量頁數據的時候,類似熱門視頻的評論、某超女的貼吧等情況。如果量很小,偏差可能只有一兩條,而很難達到錯幾頁的量級。把錯誤挪到更不容易被看到的地方比琢磨更精確的計數要節省的多。

反向排序優化是我在做論壇的時候被迫使用的,因爲總有 SB 去搞“真心話大冒險”“成語接龍”這種 SB 高樓貼,動不動就幾萬層高樓就堆出來了,那些 SB 還總以爲這種空洞無聊的蓋樓可以聚集人氣而屢試不爽,我對此優化後根本不擔心他們蓋多少層了。

頁碼錯誤的問題也經常能看到,貼吧現在可能改了,起碼以前經常能看到末尾幾頁空白。抓一個現行,是豆瓣。

http://www.douban.com/subject/3072124/comments?sort=vote&start=3860

http://www.douban.com/subject/1309161/comments?sort=vote&start=200

我估計豆瓣很快會修正這個問題,再貼個正常頁面的截圖,內容是在頁碼之前的(其實我是想問句,那位叫“影志”的老兄是豆瓣內部員工麼?太彪悍鳥)

這個截圖還能說明個問題,在這個界面裏,最後一頁可以直接點過去的(大部分網站都是如此),而用戶這麼容易就會看到錯誤的空白,很不應該。

雖然最近說的都是優化。但並不是所有問題都應該被提前考慮好,我主張出了問題再去修正(只要不是跟金融有關的程序)。牢記過度優化乃萬惡之源。

覺得文章有用?立即:和朋友一起 共學習 共進步!

建議繼續學習:

  1. 如何使用1M的內存排序100萬個8位數    (閱讀:10121)
  2. 快速排序(Quicksort)的Javascript實現    (閱讀:9438)
  3. 騰訊-1億個數據取前1萬大的整數-題解答    (閱讀:8514)
  4. 深入淺出插入類排序算法(直接插入, 折半插入, 希爾排序)    (閱讀:5592)
  5. 深入淺出交換類排序算法(冒泡排序,快速排序)    (閱讀:5481)
  6. Mysql中的排序優化    (閱讀:3733)
  7. Java程序員必知的8大排序算法    (閱讀:3738)
  8. Vim(gVim)對排序的妙用    (閱讀:3654)
  9. 快速排序詳細分析    (閱讀:3516)
  10. 深入淺出選擇類排序算法(簡單選擇排序,堆排序)    (閱讀:3291)

QQ技術交流羣:445447336,歡迎加入!

掃一掃訂閱我的微信號:IT技術博客大學習

相關文章