做了一年的大一年度項目了,對於關系型數據庫結構還是有些了解了,有的時候還是覺得這種二維表不是很順手。在看過一篇文章之後,對NoSQL有了初步的了解,(https://keen.io/blog/53958349217/analytics-for-hackers-how-to-think-about-event-data)。這篇文章寫的很好,確實寫出來了在實際情況下NoSQL的“用武之地”,而且用了MineCraft作分析,但是也許不夠全面。比如文章中只是提到了,entity數據用關系型怎麼存,event數據用NoSQL怎麼存,我想借我這篇文章,來分析一下event類型的數據原始的關系型數據庫是怎樣存數據的,然後再對這兩種儲存方式做一種對比,算是對原文都一種補充吧。
對於這種死亡事件,有這樣的兩條數據,一個是關於creeper的爆炸,一種是掉進巖漿。如果必須用關系型二維表數據庫,我會這樣存儲。(如果您還不知道是什麼樣的數據,可以先看之後的NoSQL儲存方法,那樣看起來更清楚。)
這種情況的數據可以說是數據庫設計中比較復雜的一種情況了,因為它包含兩種情況(當然不止這兩種情況,那麼就會產生更多的結構),不同情況的數據表結構是不同的,這非常麻煩。我們一般的解決方案是設計四個表格,利用關系型數據庫的關系性。設計如下四張表格。(在這裡我就簡寫了)
第一張表
id #首先用於關聯,主表需要有個id,這個倒不是什麼區別,因為NoSQL一般也會有個_id的預設 timestamp #所有共同部分就可以存在一張表中。 cause player_UID player_experience player_age #對於player_inveneory_id 因為這是一個可以任意長度的數組,又只能保存在另一個表中了
第二張表(用於保存creeper死亡方式的死亡事件的)
id #這是這張表的id以後可以跟別的表格關聯 mid #用於關聯主表 enemy_type enemy_power enemy_distance enemy_age
第三張表(用於保存lava死亡方式的死亡事件的)
id #這是這張表的id以後可以跟別的表格關聯 mid #用於關聯主表 place_x place_y place_z
第四張表(用於保存player_inveneory)
id #這是這張表的id以後可以跟別的表格關聯 mid #用於關聯主表 inveneory
至此關系性數據庫就將這種有不同結構的事件存放方式規定好了,接下來存放如下(我就不畫表格了)
1. id timestamp cause player_UID player_experience player_age 1 "2013-05-23T1:50:00-0600" "creeper" "99234890823" 8873729 228 2 "2013-05-24T23:25:00-0600" "lava" "99234890823" 88737 22 2. id mid enemy_type enemy_power enemy_distance enemy_age 1 1 "creeper" .887 3.34 .6677 3. id mid place_x place_y place_z 1 2 45.366 -13.333 -39.288 4. id mid inveneory 1 1 "diamend sword" 2 1 "torches" 3 2 "stone"
至此,我們就用關系性數據庫將這兩個事件數據存下了。(好麻煩是吧!)
我們再看NoSQL的儲存方法,因為每條數據並不受字段(列名)限制,完全可以直接保存,不用分表。(比如JSON格式)
#第一條數據 { "timestamp": "2013-05-23T1:50:00-0600", "cause":"creeper", "enemy":{ "type":"creeper" "power": .887 "distance_from_player":3.34 "age":.6677 }, "player": { "UID":"99234890823", "experience": 8873729, "age": 228, "inveneory":["diamend sword","torches"] } } #第二條數據 { "timestamp": "2013-05-24T23:25:00-0600", "cause":"lava", "place":{ x:45.366 y:-13.333 z:-39.288 } "player": { "UID":"99234890823", "experience": 88737, "age": 22, "inveneory":["stone"] } }
下面我們分析NoSQL對這種數據存放方式的好處
1.首先是把分散的表結構整合了,讓應該在一起的數據在一起了。
這就像C語言中開多個數組儲存還是用一個結構體數組的區別,將一些有關系的數據放在一起是人類一種自然的想法,當然會讓人更加舒服,而且可以提高關聯性和升級擴展的簡易程度。
2.存放變得方便
讓我們來考慮有數據來了我們怎麼儲存。
對於二維表數據庫:
1.分析數據是那種類型的
2.存放主表數據,並獲得返回id
3.分支,加上主表id在不同情況下向lava或creeper表中存放數據
4.開循環,向inveneory表中插入多條記錄
這還只是一個簡述,還要考慮到對多個表格操作時的數據回滾問題,實際寫起來30行左右,那麼出錯的可能就大大提高了。
對於NoSQL類型
一句話:
insert(data);#偽碼
其實想想便知道,取數據時原來的關系性數據庫也會同樣麻煩。
3.NoSQL更利於動態生成存放方式,靈活性高了很多,至少我們可以在存放數據的時候再設計數據庫了(雖然可能預先設計會好一些)
當然,如果存儲的不是事件性或者類似此類數據那麼就另當別論了,二維表還是有很多它本身的優勢的。以上是我的一些個人的分析,當然還有很多普遍認同的觀點,以下是一些普遍認同的關於兩種數據庫模式的優缺點分析,我也基本同意。
關系性優勢:
1.事務處理---保持數據的一致性;
2.由於以標准化為前提,數據更新的開銷很小(相同的字段基本上只有一處);
3.可以進行Join等復雜查詢。
關系型缺點:
1. 擴展困難:由於存在類似Join這樣多表查詢機制,使得數據庫在擴展方面很艱難;
2. 讀寫慢:這種情況主要發生在數據量達到一定規模時由於關系型數據庫的系統邏輯非常復雜,使得其非常容易發生死鎖等的並發問題,所以導致其讀寫速度下滑非常嚴重;
3. 成本高:企業級數據庫的License價格很驚人,並且隨著系統的規模,而不斷上升;
4. 有限的支撐容量:現有關系型解決方案還無法支撐Google這樣海量的數據存儲;
NoSQL優勢,主要體現在下面幾點:
1. 簡單的擴展:典型例子是Cassandra,由於其架構是類似於經典的P2P,所以能通過輕松地添加新的節點來擴展這個集群;
2. 快速的讀寫:主要例子有Redis,由於其邏輯簡單,而且純內存操作,使得其性能非常出色,單節點每秒可以處理超過10萬次讀寫操作;
3. 低廉的成本:這是大多數分布式數據庫共有的特點,因為主要都是開源軟件,沒有昂貴的License成本;
NoSQL數據庫還存在著很多的不足,常見主要有下面這幾個:
1. 不提供對SQL的支持:如果不支持SQL這樣的工業標准,將會對用戶產生一定的學習和應用遷移成本;
2. 支持的特性不夠豐富:現有產品所提供的功能都比較有限,大多數NoSQL數據庫都不支持事務,也不像MS SQL Server和Oracle那樣能提供各種附加功能,比如BI和報表等;
3. 現有產品的不夠成熟:大多數產品都還處於初創期,和關系型數據庫幾十年的完善不可同日而語;