SQL千萬級資料設計和優化

2022-02-07 07:40:35 字數 3094 閱讀 5335

1. 資料太多。放在乙個表肯定不行。

比如月週期表。乙個月1000萬,一年就1.2億,如此累計下去肯定不行的。所以都是基於乙個週期資料乙個表。甚至乙個週期資料就要分幾個分表。主要是考慮實際的資料量而定。當你建立乙個新錶時,可能這個表需要有索引,但是都要先取消索引,或者先建立表,匯入資料後,再建立索引。

必要時處理完,統計完後,就備份到磁帶或者其他介質。然後清掉。

從問題域來看,乙個週期內的資料關聯性最大。比如統計乙個客戶某個帳期的話單總額,同比上月增幅,還有就是零話費客戶等。如此種種,參照的資料不外乎本週期,或者兩個週期,甚至更多就是乙個季度,或者半年的樣子(類似三個月連續零話費,或者三個月連續欠費未交之類的,儲存量之類的報表可能會要一年的資料)。而且這樣的情況在資料探勘或者高階管理報表中比較常見,一般營業部門使用的介面中,是不可能含有這樣的統計的。

所以資料按表分開,甚至於可以按資料庫分開,更便於管理。

大家要打消一種固有的思路,這些資料,跟環衛工人處理垃圾一樣,是幾乎有點帶人工處置的多步驟方式,也就是不會作為常規資料(如客戶基本資料等)長期存在和頻繁使用的。所以我們可以改變思路,就是想盡辦法,在需要的時候,做最佳處理,而在不需要時,清理掉它。也就是說,比如分表,你可以分100個表,1000個表都可以。只要方便統計和得到所需資料即可。 例如**meng.115sou.com就是分表處理的。

view只是說你能在寫select語句時簡單一點,對速度沒有任何提高。

主要是,你的分表的方式能建立減少訪問所有資料,就能提高速度。比如你做某個統計,那些資料恰好在某個分表內。舉例說,你有10個分部,而你統計id=1這個分部時,你恰好把資料放在第乙個分表裡,你就可以在儲存器內通過判斷,只訪問第乙個分表,從而提高統計速度。如果你的統計需要統計全部分表內的資料,那處理速度還是一樣慢。

2. 假設每個表的資料在數十萬條,那統計起來是沒有任何瓶頸的。常規的資料庫都應該沒任何問題。

3. 預處理的必要性。

有人問:我統計一千萬條資料彙總,要多久多久,能否提高。。。試想你把中國人所有的存款加總,需要多長時間吧?看看這個問題的規模,其實再複雜的資料庫dbms,我們說他都逃不過:找出符合條件的資料,一條一條的加總這個計算過程。暫且不提where條件了。預處理的必要性在於,如此規模的資料處理,本身就是乙個非常耗時的過程,我們有必要提前,處理其結果到乙個表內,或者多個表裡面。使用者查詢時,再顯示出來。比如說1000萬資料分10個分部,要看每個分部的應收增長,那我們可以預先統計資料到分部費用表中,則使用者端報表顯示時,就非常快。如果任何資料彙總都要從原始資料去統計,那是不現實的。所以我們可以設定原始資料表,中間結果表,結果表,彙總表,月結表,期間表之類的東西。逐步統計歸屬。

另外要提的是,這樣的動作肯定非常耗時,而且!這樣的資料如果由伺服器的儲存過程定期定時執行的話,處理的規模就只有一次,任何客戶端,都只從結果表裡產生報表。如果不用此方法,任何客戶端報表都從原始資料產生,理論上是可以,但是這樣的千萬條資料彙總的處理會做n次。而且時間上也是不容許的。

還有,這樣的統計過程最好是分開db進行存放,而公用的資料比如客戶基本資料,最好拷貝乙份到這個新db中來處理。這樣可以不干擾到正常的使用。

可以在晚上,或者另開db或者在另外的server上跑這個過程。處理完後,寫乙個標誌告訴主db,則客戶端可以統計這些報表了。

4. 對單行資料做計算字段。舉個例子,比如一條記錄的產生時間是2009-01-01

12:00:00.001,如果你的統計剛好需要對某個時段進行統計,那最好增加字段,比如hour欄位,下乙個批處理命令下去,取得小時數,然後再統計。 doc.115sou.com

5. select語句中忌諱對column做函式。因為函式將導致查詢條件不走索引,而改走遍歷所有資料。這樣你就是查一條資料,也會遍歷所有資料,那豈不是可憐。

6. 條件盡量都是數字,也就是都用id,比如分部,鎮區,業務種類,接入型別,客戶位址,等等,都需要用到fk方式的編碼,主表裡只用數字id,請記住是數字型id。整數型數字是計算最快的資料型別。如果金額極大,可以用decimal(小數=0)。varchar型別是效率很低的,不過好像有sql的md5演算法,我想可以嘗試這個方法(我還沒試過)。

7. 索引,這個是海量資料查詢首要解決的問題。

沒有索引,就是遍歷。索引沒有覆蓋到,也會走遍歷。

8. 複雜的統計,用儲存器做分步處理,然後得到結果,同比一條select語句實現要輕鬆和明白得多。

而且對錶的占用時間要短得多。當然,很複雜的統計可能要用到條件判斷,迴圈等,一條select語句是無法處理的。多層的where中的子句也是效率低,容易占用表的寫法。

原則上,這裡我所討論的問題都不是那種基於**內容管理的小case,主要對企業運用而言。比如舉例說查乙個「存量客戶增幅表」,問題都不是簡單到直接對比兩個月的話費總額這麼簡單,還得找出之前他的話費如何,比如超過多少錢的才列入統計物件。所以,我的理解:複雜的問題,必須儲存過程。真正做過幾個專案才會明白,寫sql語句會比程式設計**還要多。真正的程式,其實是sql。

最後說一句,如果經驗足夠豐富,寫出的統計過程,其執行時間在數分鐘甚至幾個小時都是正常的。所以初學者應該明白,資料量是與處理時間成正比的。如果平時處理幾條資料感覺很快,資料量猛然增加幾個數量級,不要認為時間上還能優化到幾秒鐘。

erp裡的mrp展開計算,通常能到幾個小時的。這都是正常的。(主要是物料多,bom多,計算步驟太多造成)

9. 補充一點。如果資料量超過我們標題的千萬級,甚至幾十億數量級。那也不存在問題,還是分而治之的思路,就是把資料在多台伺服器上並行執行。就好像為災區捐款一樣,靠乙個人的力量是不行的。人多力量大。類似資料分揀之類的,只需要原始資料和基本資料,還有一些計費策略之類的。完全可以分布在多台server上同時處理,也是必要的。主要根據你的資料量和單台處理的速度以及你要求的總的處理時間而決定的。有人說select語句難道也需要分布?只能說,如果確實有必要,也能做到。比如你要返回所有話單異常的資料,那也可以從每台執行檢索,然後匯合到一起,我想是可以的。

總而言之:

一。合理設計表結構,使得統計彙總最高效(包括fk設計和用數字id,不用varchar,索引設計,計算字段);

二。合理分表,使得單錶資料規模適當;

三。用儲存器分多個步驟處理。

四。資料預先處理。

五。分布在多台server上同時處理。

也就是分而治之與預處理。

千萬級資料優化記錄

每個動作都會生產一條動態資料,如今已經生成了一千多萬條資料,而且正以每天好幾萬的速度迅速增長,頻繁的讀寫導致 rds 資料庫例項壓力非常大,該庫還有核心業務的資料,為了避免對核心資料的影響,決定將其分出來。結合其業務特點,決定使用 mongdb,那麼第乙個問題就是如何同步這些資料了。不能停止服務,還...

oracle千萬級資料查詢優化

需求 組合查詢,按條件統計某幾個欄位取前100條記錄 問題 沒建索引導致查詢結果耗時5秒多,不能忍受。解決方法 建索引,在哪個欄位建?在這裡先提下oracle的sql語句的執行。oracle在執行sql語句之前會用優化器optimizer對sql語句進行解析,解析出最優的執行計畫再執行,這樣所花費的...

千萬級 百萬級資料刪除優化

在mysql上面刪除大量資料 千萬級 由於不是清空資料,故不能使用truncate 語句 有個truncate可參考 mysql delete語句與truncate table語句 在正常delete下,刪除十分緩慢 由於索引的原因,每次刪除都要相應的更新索引,越往後索引碎片越多,即越往後越慢 完整...