Loading...

SQL (Structured Query Language 結構化查詢語言) 是一種專門用來管理與查詢關聯式資料庫(Relational database)的程式語言。NoSQL資料庫的意思是 "Not Only SQL",也就是不限定為「關聯式資料庫」的資料庫管理系統的統稱。

今天,大部分的人提到「資料庫」的時候,通常指的其實是資料庫管理系統(database management system,簡稱 DBMS):一套讓我們能方便使用資料庫的軟體,作為使用者(或是使用資料庫的應用程式)與資料庫之間溝通的平台。在這篇文章,會入門介紹「關聯式資料庫」與「NoSQL(非關聯式)資料庫」這兩種常見的資料庫管理系統。

相關課程:SQL 入門課程:14 天從語法到真實企業案例

想了解更多 Data & AI 產業與必備技能?Data & AI 免費公開課在這裡!

透過專案實作,學會後端必懂的資料庫設計

關聯式資料庫(Relational Database Menagement System, RDBMS)

1970 年代初,在 IBM 研究實驗室工作的埃德加·科德 (Edgar F. Codd) 出版了一份名為「A Relational Model of Data for Large Shared Data Banks」的研究,定義了「關聯式資料 (Relational Database)」的概念,以及將資料組成表格的應用原則。這份研究,就是關聯式資料庫發展的起點。

關聯式資料庫有三個特質:

1)資料是以一個或是多個資料表 (table) 的方式存放

在關聯式資料庫裡,每一筆資料都是在 table 中的一個 record,然後再把不同的 table 集合起來,就成為一個關聯式資料庫。

所以使用關聯式資料庫的網站,背後都有多個 table,負責紀錄不同的資料。例如在一個電商網站中,應該會有賣家、商品、分類、使用者和交易紀錄等資料表,然後它們各自也有不同的關聯。

2)資料之間有明確的關聯

關聯式資料庫一般都用來儲存結構化的資料,而資料之間大多會有清楚的關聯。以電影清單專案為例,我們只有一種資料需要處理,就是「電影 (movie)」 的內容。在建立 To-do List 的認證系統的時候,我們則有 todo 跟 user 這兩種資料,並需要建立它們直接的關聯。而在關聯式資料庫裡,這兩種資料會以兩個資料表來存放,而在兩個資料表之間,我們也會設定「使用者擁有 todo」這個關聯:

3)關聯式資料庫以 SQL 語言操作

SQL (Structured Query Language 結構化查詢語言) 是一種專門用來管理與查詢關聯式資料庫的程式語言。透過 SQL,我們能在關聯式資料庫裡新增、查詢、更新和刪除資料,同時也能建立和修改資料庫模式。它的語法簡單直接,一切都是以資料為主角去思考。讓我們一起來看一個簡單的 SQL 的範例:

SELECT * FROM [TABLE_NAME] WHERE [COND];

這句話的意思,就是「從 [TABLE_NAME] 的資料表中取出滿足 [COND] 條件的資料。

在過去的幾十年裡,關聯式資料庫的發展並不是一帆風順,有很多批評者,但由於關聯式資料庫使用簡單,穩定度高,而 SQL 功能強大,並且也積累了很多企業開放支援 SQL 的軟體與大量的成功案例,所以目前關聯式資料庫仍是最多軟體開發者使用的資料庫系統。

關聯式資料庫的特色

  1. 資料存放在一個或多個資料表當中。資料都是透過資料表中行列的二元關係呈現。
  2. 資料表需預先設定架構 (schema)
  3. 資料表之間的關係也需要預先定義好,使資料之間有明確的關聯
  4. 可以透過 SQL 語言進行資料操作

另外,一個好的關聯式資料庫設計,也需要能夠確保每一個 transaction 能夠滿足 ACID 原則。ACID 分別代表

  • Atomicity (原子性) : 資料操作不能只有部分完成。一次的 transaction 只能有兩種結果:成功或失敗
  • Consistency (一致性):transaction 完成前後,資料都必須永遠符合 schema 的規範,保持資料與資料庫的一致性
  • Isolation (隔離性):資料庫允許多個 transactions 同時對其資料進行操作,但也同時確保這些 transaction 的交叉執行,不會導致數據的不一致
  • Durability (耐久性):transaction 完成後,對資料的操作就是永久的,即便系統故障也不會丟失

關聯式資料庫的侷限性

隨著網路應用程式的普及,使得資料庫的使用、分享、與資料量飛快地增加,讓原本的資料庫設計遇到的挑戰。人們除了需要更快的速度來處理大量資料之外,也需要能夠及時地提供服務以滿足大量使用者的需求。

此時人們開始轉向非關聯式資料庫設計來尋找解決方法,NoSQL 也就開始站上了舞台。NoSQL 的意思不是「不要用 SQL 」或是「資料不需要關聯」,NoSQL 它真正的意思是 Not Only SQL,也就是「不是用 SQL 操作資料的資料庫設計」,因此實際上資料之間還是可以建立關聯的喔。

另外,NoSQL 也不是橫空出世,雖然這個詞看起來很新,但早在電腦科學發展初期,就有許多不同於 Relational model 的資料庫設計。

NoSQL 非關聯式資料庫

前面說到,關聯式資料庫是最多開發者使用的資料庫系統,那麼還有什麼其他的資料庫系統呢?讓我們來聊聊 NoSQL 資料庫。

隨著電腦、行動裝置、與互聯網的普及,網路應用程式的流量大幅地增長,同時 互聯網也進入「使用者生產內容 (user generated content)」為主流的時代。對於 Youtube、Facebook 這些社交網站來說,每分每秒需要處理的資料量是過去一般網站的非常多倍。

而從使用者的角度來看,他們在這些平台上對於資料的需求也跟過去不太一樣。資料庫的主要功能,從過去的「能夠無錯誤地同步處理結構清楚的資料」,到現在慢慢有新需求誕生:「處理高速且大量產生的資料,但不需要即時同步,也不需絕對地零錯誤。」為了呼應這個需求,NoSQL 資料庫就隨之興起了。

Not Only SQL (NoSQL)

NoSQL 的意思是 "Not Only SQL",也就是不限定為「關聯式資料庫」的資料庫管理系統的統稱,在操作上,NoSQL 並不支持 SQL 語法 與 SQL 的邏輯。所以,NoSQL 資料庫通常不使用關聯模型,也並不需要固定的結構 (也就是 schema-free)。但有需要時, NoSQL 也可以使用關聯模型與 schema。

NoSQL 將聚集後的資料,作為儲存的最小單位,透過縝密豐富的資料結構,有利於將資料分散到多個節點;比起資料的關聯,NoSQL 更關注資料所代表的人(例如使用者)與物(例如一篇分享在社交平台上的文章)的「狀態」變動,例如文章被分享、按讚等。

文件資料庫 (document database)

文件資料庫是NoSQL資料庫的一種,顧名思義,是把資料存放成「文件 (documents)」,這些文件會組成為「集合 (collection)」並放在一起,圖示如下:。

在文件資料庫裡,文件會存成 JSON 格式,而資料物件會由「屬性-值」 (attribute-vaule pair) 或陣列組成。例如下圖:

此外,NoSQL 還有一個特點是,不講求資料同步,只求最後結果一致。怎麼說呢?

我們先來看一個例子。如果我們今天要匯出一筆款項給商家,那麼當款項從我們的帳戶匯出後,系統一定要同步「帳戶已經扣除這筆款項」這個訊息,不然款項可能會被重複扣除,或者其他系統會誤以為我們帳戶的結餘跟匯款前一樣。這是適合使用 SQL 的情境。

至於適合 NoSQL、所謂不講求資料同步,只求結果一致的情境是什麼呢?

例如我們要來處理一篇在 Facebook 上的 po 文有多少人按讚時,其實這個訊息的準確性就不是非常重要。當一篇文章獲得第 100 個按讚時,某些使用者可能會馬上看到新的數字,但部分使用者可能要隔數十秒後才看到按讚數從 99 轉到 100。這種延誤,並不會造成什麼嚴重的問題。而對 Facebook 來說,更重要的是能在一定的成本之下,去處理大量的數據。順便告訴你,有報導說:Facebook 每一分鐘會收到超過四百萬個讚

由於 NoSQL 的種類很多,而技術的成熟度與使用場景不一,所以目前業界還是以 SQL 資料庫佔大多數。在 Stackoverflow 2018 年的調查結果,關聯式資料庫系統還是最多開發者使用的資料庫管理系統,佔前五名中的首四名!

延伸閱讀:SQL (關聯式) 與NoSQL (非關聯式) 資料庫的比較

應用程式與資料庫

當你要在你的應用程式裡整合資料庫管理系統時,需要瞭解以下三件事:

  • 應用程式如何與資料庫溝通
  • 選擇用什麼資料庫
  • 如何在應用程式裡定義資料結構

與資料庫溝通:ODM 與 ORM

若需要使用資料庫的功能,比如查詢、新增、修改或刪除資料等,就必須使用資料庫管理系統 (DBMS) 提供的原生查詢語言,其中最著名的是SQL (structured query language),也就是是專門用來操作關聯式資料庫的語言。

但在實務上,當我們用 Express.js 開發應用程式時,會希望能直接用 JavaScript 操作資料庫,而不需要另外撰寫 SQL。換成不同的程式語言,也會有一樣的需求,因此有人開發了一種叫「物件映射 (object mapping)」 的技術,主要是用程式語言裡的「物件」來包裝資料庫的 SQL,讓開發者可以直接使用物件導向的方式操作資料庫。

學會用 Express.js 製作完整的 Web App 產品

依不同的資料庫類型,會分別使用不同的映射技術:

  • 文件資料庫:ODM (Object Document Mapper)
  • 關聯式資料庫:ORM (Object Relational Mapping)

兩種技術的用途與概念非常類似,只是對應的類型不同。ODM 是針對文件資料庫 (document database) 的技術,而 ORM 則是針對關聯式資料庫 (relational database)。不過簡單來說,ODM 與 ORM 都是讓開發者可以使用物件導向語法來操作資料庫,同時也增加程式碼的易讀性與維護性。

舉個例子,如果我們要在 Todo 資料庫尋找一筆名為「買蘋果」,但還沒被完成的待辦事項 (todo),透過 ORM 的語法:

Todo.find ({ name: '買蘋果', done: { false }})

若使用 SQL 的指令的話,會是:

SELECT * FROM Todos WHERE name='買蘋果' AND done=FALSE;

可以看到,使用物件導向語法時,程式碼會更簡潔,而且可以更好地銜接程式碼中同樣以物件導向語法建立的部分。

需要注意的是,任何技術都有優、缺點,ORM 與 ODM 也不例外。有部分開發者甚至大力反對使用 ORM 與 ODM,認為直接用資料庫管理系統的原生語言(如 SQL),才能確保操作時的效率與準確。

有很多不同的資料庫如 MongoDBMySQLPostgreSQL 等等。當你為自己的應用程式選擇一個資料庫時,也需要選擇對應的 ORM/ODM 系統。

MySQL or MongoDB?

說了這麼多,回過頭來到自己的專案上,該選擇 MySQL 還是 MongoDB 呢? 阿不對,剛剛都繞了這麼一大圈了,這裡應該是問,

「該選擇 RDBMS  還是 NoSQL 呢? 」

這裡有幾個考量點提供給大家參考:

可以考慮使用 NoSQL (譬如 MongoDB),如果

  1. 想快速啟動小專案測試 idea
  2. 資料格式不確定 (unstable schema),而未來很有可能調整
  3. 資料之間沒有複雜的關聯、或未來讀取資料時不需要使用 JOIN 的功能
  4. 著重在快速讀取資料與可用性,而非 ACID

可以考慮使用 RDBMS  (譬如 MySQL),如果

  1. 已經有明確的資料格式,未來不會大幅的變動
  2. 資料之間的關聯很重要
  3. 想要更有效率的讀取資料,未來會大量使用到 JOIN 的功能
  4. 更著重在資料操作的準確性與一致性 (ACID)

上述的情境主要是在個人專案上,如果實際在業界開發,還需要考量到

  1. 商業邏輯的設計
  2. 目前使用的系統(如何加入,需不需要做調整或轉移)
  3. 部署方式
  4. 成本計算
  5. 維護與營運考量
  6. 未來的擴充性

有這麼多需要考量的點,這也難怪當問你朋友「應該用 MySQL 還是用 MongoDB 好」的時候時,他只能回答「看情況囉」

SQL 入門課程:14 天從語法到真實企業案例

看了這麼大篇的文章,已經對資料庫有初步了解了嗎?來做個小測驗複習測試一下。

3分鐘小測驗,找到你學習後端開發的入口

更多技術學習資源
前端 JavaScript | HTML /CSS| Bootstrap | RWD | DOM | API | AJAX | Postman | jQuery
後端 HTTP / HTTPS | Node.js | MongoDB | Git | SQL / NoSQL | Docker | React
其他 VSCode | Web App | Leetcode