最近在撰寫發票對獎系統,有一個深刻的體會。
電腦的運算速度還是很快,幾秒之間迴圈就可以跑到數萬次,甚至更多,但寫入資料庫的動作就沒有辦法這麼快,在預設的PHP執行期時間內(30秒)有時候只能寫入1萬多筆,有時候能寫到2萬多筆。這和資料庫的資料儲存在硬碟有關,畢竟硬碟的存取速度較記憶體慢上許多。
關於這點,也許我該試試資料庫延遲寫入的功能,看看能不能在30秒內寫入更多筆的記錄。
另外,在設計的過程因為需要大量的發票號碼來測試,所以利用亂數來產生發票號碼以便寫入資料庫,結果亂數產生的結果經過運算後呈現接近平均的效果,例如亂運產生0~9的數字,大量的執行後並累計各數字出現的次數,各數字間的比例會接近1:1,這個特性可以用來做某些事,也可能不適合做某些事。
測試的時候,資料庫裡所有的發票筆數約14萬筆,模擬今年1月至8月所存進去的發票號碼,平均每兩個月3萬多筆記錄。對獎的時候是以雙月為單位,大約3秒可以完成對獎及發送給中獎者通知的動作,所以對獎的速度是很快。
所以和傳統對獎的流程相比,用電腦來比對的流程是將時間花在前置登錄的動作上。如果設置一個人的專職工作就是在keyin發票,每張發票鍵入的時間10秒,以每天工作8小時來算,一天可以鍵入2880張發票,一個月可以鍵入86400張發票,兩個月有172800張發票,上述這樣的時間配置還包括將發票做字尾分類,以方便中獎時尋找發票。到對獎的時候,電腦在10秒中可以比對出中獎的號碼,此時先過濾掉未中獎的字尾,再從剩餘的發票中挑出有中獎的號碼。
所以字尾分類的工作變得很重要,一般是以最後一個數字分類,為了要加快搜尋的動作,可以加上最後第二個數字來做分類,如果不方便把第二個數字拆成十個數字,可以分成奇偶數,這樣總共就有10*2個類別,目前中獎發票號碼共有六組,加碼會多一組,所以字尾最多只有七組,但實際不會這麼多,如果不要考慮特獎必須全中的狀況,頂多只有4組,所以20分類組合,最少可以過濾掉12個分類,172800*(12/20)=103680(張),只剩下69120張發票,而實際情況肯定更少。
至於這樣到底有沒有比較省事?因為最後要挑出中獎的發票還是要從那茫茫大海裡去挑出來,和傳統比對方式並沒有差別。不過,至少在找出來前已經得知此次發票的中獎狀況,在找發票的時候可能心情也不一樣,但前提也必須保證登錄的發票號碼都沒有錯誤,否則萬一電腦比對出200萬,但找不出來,那麻煩更大,必須全部找過一次。
對獎之後,若有中獎的發票,應從中獎的發票裡彙整字尾,如此可再縮減搜尋的範圍,至少不會多於全部中獎的組數,而且極可能少於中獎的組數。