怎樣玩轉千萬級別的數據

大數據處理是一個頭疼的問題,特別當達不到專業DBA的技術水準時,對一些數據庫方面的問題感到無賴。因此仍是有必要了解一些數據庫方面的技巧,固然,每一個人都有本身的數據庫方面的技巧,只是八仙過海,所用的武功不一樣而已。我把我最經常使用的幾種方式總結來與你們分享,你們還有更多的數據庫設計和優化的技巧,儘可能的追加到評論中,有時一篇完整的博客評論比主題更爲精彩。sql

方法1:採用表分區技術。

第一次據說表分區,是之前的一個oracle培訓。oracle既然有表分區,就想到mssql是否有表的分區,當時我回家就google了一把,資料仍是有的,在這我兒只是再做一次推廣,讓更多的人瞭解和運用這些技術。數據庫

表分區,就是將一個數據量比較大的表,用某種方法把數據從物理上分紅若干個小表來存儲,從邏輯來看仍是一個大表。首先來個結構圖:oracle

gdft45bfghty.png

上圖雖然不能很清晰的表達表分區的執行過程,可是能夠看出表分區要用到那些對象,好比數據文件,文件組,分區方案,分區函數等。數據庫設計

咱們以一個用戶表(TestUser)爲例,假設這個表準備用來存儲中國部分公民的數據,每條數據記錄着每一個人所屬的省份(Area),以及每一個人的姓名(UserName),以下圖所示。當數據量達到1千萬的時候,查詢就比較慢了,這時候的數據優化就迫在眉睫。ide

qqjie_tu_20130911080338.jpg

在優化以前,根據數據的結構,讀寫操做等,確定會提出若干個解決方案。在這兒就以分區表的方案來優化數據庫的查詢,這兒以區域來分別存儲數據,好比廣東的公民存放在AreaFile01.MDF文件中,湖南的公民存放在AreaFile02.MDF的文件中,四川的公民存放在AreaFile03.MDF的文件中,以此類推其它省份,爲了實現這個功能咱們就得作分區方案。在作分區方案時,首先要搞清楚分區方案要涉及到的四個對象:文件組,文件,分區函數,分區方案。函數

a:文件組,用來組織數據文件(.MDF)的一個虛擬名稱,一個文件組能夠添加多個數據文件(.MDF)。打開SQL管理器,找到具體的數據庫,而後右鍵【屬性】,進入到【文件組】選項卡,添加Area01,Area02,Area03,Area04四個文件組。如圖:性能

6j34jfvry6576utyhsdf.png

b:而後選擇中【文件】選項卡,添加AreaFile01,AreaFile02,AreaFile03,AreaFile04,AreaFile05,AreaFile06六個數據文件(.MDF),而後指定每一個文件屬於那個文件組(一個文件組能夠存儲多個數據文件),以及這個文件的物理路徑。在這兒你們已經看明白了,這些數據文件,就是物理上來分割一個數據表的數據的。也就是說一個表的數據有可能存儲在AreaFile01中,也有可能存儲在AreaFile02中,只要用某種方法來指定他們的存儲規則就好了。大數據

grt456ytdfgfgs.png

c:分區函數,就是指定數據的存儲規則。就是告訴SQL,把新增的數據如何分區。建立一個分區函數,能夠用下邊的SQL語句來實現。優化

?google

1
2
CREATE PARTITION FUNCTION partitionFunArea (nvarchar(50))
AS RANGE Left  FOR VALUES ( '廣東' , '湖南' , '四川' )

d:辛苦的建立了文件,又爲其指定文件組,還建一個分區函數,目的只有一個,就是爲了建立一個分區方案。分區方案能夠用如下代碼來建立。

?

1
2
3
4
5
6
7
CREATE PARTITION SCHEME partitionSchemeArea
AS PARTITION partitionFunArea
TO (
     Area01,
     Area02,
     Area03,
     Area04)

通過緊張的四步操做,一個分區方案就呈如今咱們的眼前了。接下來的事,就是咱們要怎樣來消費這個分區方案。

首先咱們建立一人普通的表,而後給這個表指定一個分區方案。以下代碼。

?

1
2
3
4
5
CREATE TABLE TestUser(
     [Id] [ int ] IDENTITY(1,1) NOT NULL ,
     [Area] nvarchar(50),
     [UserName] nvarchar(50)
) ON partitionSchemeArea([Area])

爲了能看到效果,再插入一些數據。

?

1
2
3
4
5
6
7
8
9
10
11
INSERT TestUser ([Area],[UserName]) Values ( '四川' , '肖一' );
INSERT TestUser ([Area],[UserName]) Values ( '四川' , '肖二' );
INSERT TestUser ([Area],[UserName]) Values ( '四川' , '肖三' );
INSERT TestUser ([Area],[UserName]) Values ( '四川' , '肖四' );
 
INSERT TestUser ([Area],[UserName]) Values ( '廣東' , '張一' );
INSERT TestUser ([Area],[UserName]) Values ( '廣東' , '張二' );
INSERT TestUser ([Area],[UserName]) Values ( '廣東' , '張三' );
 
INSERT TestUser ([Area],[UserName]) Values ( '湖南' , '楊一' );
INSERT TestUser ([Area],[UserName]) Values ( '湖南' , '楊二' );

查詢全部的數據,能夠用select * from TestUser; 按分區查詢:就用以下方法:

?

1
2
3
4
5
6
select $PARTITION.partitionFunArea([Area]) as 分區編號, count (id) as 記錄數
from TestUser group by $PARTITION.partitionFunArea([Area])
select * from TestUser where $PARTITION.partitionFunArea([Area])=1
select * from TestUser where $PARTITION.partitionFunArea([Area])=2
select * from TestUser where $PARTITION.partitionFunArea([Area])=3
select * from TestUser where $PARTITION.partitionFunArea([Area])=4

效果圖:

fsdf44444tfgvxdvxc.png

大家看我一個簡單的表的分區是否是就已經完成了。呵呵,固然在實際應用中,僅僅掌握這點是不夠的,好比在原分區方案上添加一個分區,刪除一個分區。

方法2:用xml類型代替主從表設計,從而達到提升查詢性能。

優化和提升數據庫的性能,是從一個良好的數據庫設計開始的。以一個會議預訂系統爲例,一個預訂會議系統包括了會議時間,會議地點,主持人,參與人,知會人,記錄者等相關信息。在的TDD,DDD模型主導的時代,在這兒爲了更好的想表達我要闡述的問題,仍是以表驅動模型來進行開發。

用戶需求:

  a:一個會議可能有多個主持人,雖然這種狀況比較少,可是也有可能有。

  b:一個會議有多個參與人,這個不難理解。

  c:一個會議有可能要讓某人知曉,這人能夠參與或不參與會議,通常爲高層。

  d:一個會議有可能有零個或者多個記錄者。

  e:一個會議須要遠程視頻,投影儀,電腦,麥克風等會議設備中的某些設備。

  f:會議預訂成功,或者會議時間,會議地點等重要信息修改後,郵件通知與會人員。

常規數據庫設計:

  a:建一個Meeting的主表,用於存放會議名稱,會議地點,會議時間等的相關信息。

  b:再建一個MeetingUser的表存儲主持人,參與人,知會人,記錄者。

  c:一樣,會議所須要的設備用MeetingDevice表來存儲相關的信息。如圖:

t54445666778.png

這樣的表結構,是比較常規的設計方法,可是在實際應用中,你會發現一些待改進的問題。好比:

  a:在提取一個會議的相關信息時,會鏈接多個表進行查詢。這種查詢在很大的程序上影響了數據庫性能。

  b:在作修改操做時也夠嗆的,先修改主表的相關信息,再把主表關聯的子表信息所有刪除從新插入一次,這樣的操做是否夠吐血了。固然有人精益求精,會比較修改前和修改後的數據,再用增長,刪除,修改的手段達到子表數據的更新。這樣的操做在有些ORM操做中已經實現了,但當本身code代碼來實現的時候,特別是在屢次code的時候,感受老是那麼煩心。

吐槽了這麼多,是否有更好的解決方案呢?固然,在SQL裏,咱們能夠XML數據類型來消除主從表的設計。如圖:

h566ugfb.png

上面的表結構設計,是否是有一個小清新的感受呢?很明顯,能夠把第一種表的設計缺陷給消除了。一個會議的相關信息都存儲在了一個表的一條記錄中,這樣的數據看起來是否是更直觀呢?

  a:獲取一個預訂會議的詳細信息,我不須要進行多個表的鏈接查詢,我要作的是隻需用C#的Linq.Xml來解析查詢出來的XML字符串便可。

  b:修改操做時,我只須要從新組合XML數據,一個Update就更新了與會議相關的信息,操做是否是簡單多了。

表面上看這種設計已經完美了,可是用戶的需求是無止境的,有一天,你收到了一個需求,查詢某個用戶參與過的全部會議(就是隻要主持人,參與人,或者記錄者中包括了這個用戶,就把這些記錄都給查詢出來),Oh!My God  這種表結構設計應該怎麼解決這個問題呢?其實能夠用XQuery解決這個問題,還沒接觸過XQuery的那得趕快充一下電了。XQuery中最經常使用的有exist(),value()這些函數,這兒就不詳細的介紹了,網上搜索一下有不少相關資料,若是有必要,我會把之前項目中用的XQuery技巧與

相關文章
相關標籤/搜索