iT邦幫忙

2017 iT 邦幫忙鐵人賽
DAY 18
5
Modern Web

Half-Stack Developer 養成計畫系列 第 18

閃開!讓專業的來:SQL 與 NoSQL

閃開!讓專業的來:SQL 與 NoSQL

如果你是個有接觸過程式設計的人,可能會對於上一章所教的「把檔案當作資料庫來存取」的作法感到奇怪,因為你以往接觸的教學大概都是直接教你使用資料庫。其實會用檔案來教,也是我一時突發奇想出來的結果,而且我認為從檔案開始教是一個「非常非常好」的選擇。就像我這系列教學一直在強調的一樣,你要知道「脈絡」,你要知道「原因」,你要知道「你為什麼要用這個工具」。

我們用檔案來操作,其實已經可以完成幾乎八九成的功能了,可是你會發現碰到一些問題:

  1. 如果有兩個人同時寫入檔案,例如說 A 跟 B 同時開啟檔案,然後 A 先寫了,B 後寫,那 A 的內容就會被 B 蓋掉了。
  2. 檔案 IO 效率很差,速度比較慢,要頻繁地去操作檔案
  3. 就只是個檔案,你沒辦法對那些資料對更進一步的操作。(例如說像 Excel 那樣)

對於第一個問題,你可以看成是下列流程:

A 讀取全部 posts
B 讀取全部 posts
A 新增了一篇 postA,所以要寫入檔案的資料是 posts + postA
B 新增了一篇 postB,所以要寫入檔案的資料是 posts + postB
A 打開檔案,寫入 posts + postA
B 打開檔案,寫入 posts + postB
最後,檔案就會是 posts + postB,而 postA 不見了

這個其實跟我們寫檔的方式也有關係啦,我們新增一筆資料是先把資料全部讀出去,把新的放進去,然後全部寫回去。你可以改成直接在檔案結尾 append 一筆資料,就可以避免這個問題。可是你會發現仍然無法解決,因為刪除資料一樣會有同樣的問題,例如說兩個人同時刪除,最後只有其中一筆被刪掉。

為了要解決這些麻煩的問題,就有了專門給資料儲存使用的「資料庫」出現了,就是大家常聽到的 Database。

Database 的最底層當然還是用檔案來存取,因為你想永久的保存資料的話,除了檔案以外沒有其他方法。可是,差別在於它有做了很多的優化,讓速度快很多。至於資料庫系統是怎麼做的這個我就不知道了,有興趣的朋友們可以自己去研究一下。

總之呢,對於要儲存資料來說,資料庫是你的最佳選擇。

其實資料庫這個東西就跟 Excel 差不多啦,一個 Excel 檔案就是一個資料庫。然後 Excel 底下不是會有很多頁籤(Tab)嗎?例如說學生清單、家長清單、缺課紀錄之類的,每一個 Tab 在資料庫系統裡面就叫做 Table。再來,每一個 Tab 點進去之後就是資料了,每一行每一行的資料,一行代表一筆記錄嘛,所以每一列,每一個 column 都代表一筆特定的資料。

直接附一張截圖讓你看一下資料庫長怎樣:

http://ithelp.ithome.com.tw/upload/images/20161225/20091346RFByRuSmvu.png

你就想成是 Excel 就好。以上面來說,就是一張叫做 users 的 Table,然後有三個欄位:id, name 還有 phone。

資料庫的存取方式,是靠著指令來進行的。這個指令就叫做:SQL,Structured Query Language。你只要對著資料庫下指令,你想查詢的資料就會迅速地來到你的身邊。

對於資料的存取,最基本的方式就是四種,建立、讀取、更改、刪除,簡稱 CRUD

  1. Create
  2. Read
  3. Update
  4. Delte

假設我們的 table 現在長這樣:
http://ithelp.ithome.com.tw/upload/images/20161225/200913469RQB6lmxMw.png

Create

insert into users(name, phone) values (peter, 1234)
insert into users(name) values (peter)
insert into members(username) values (username)

提供給你三句不一樣的語句,你從裡面可以觀察出一些規律。insert into TABLE_NAME(a,b..) values(a,b..)這個指令是不會變的,變得只有你的 table 名稱以及你要新增資料的欄位。上面的第一句insert into users(name, phone) values (peter, 1234),翻譯成白話文就是:「插入一筆 name 是 peter, phone 是 1234 的資料到 users 這個 table 裡面去。」

Read

select phone from users
select name, phone from users
select * from users
select phone from users where name=peter

一樣給你幾句,所以你一樣可以從這幾句裡面很聰明地找出一些規律,不變的就是select...from,我可以把每一句翻成白話文給你聽:

  1. select phone from users,讀出 users 這個 table 裡面所有的 phoen 這個欄位
  2. select name, phone from users,讀出 users 這個 table 裡面所有的 name 跟 phone 這兩個欄位
  3. select * from users,讀出 users 這個 table 裡面所有的欄位(*是特殊符號,代表所有的意思)
  4. select phone from users where name=peter,讀出 users 這個 table 裡面,符合條件name=peter的一筆資料的 phone 這個欄位

Update

update users set phone=123
update users set phone=123 where name=peter
  1. 把 users 裡面的所有資料的 phone 更新成 123
  2. 把 users 裡面符合name=peter這筆資料的 phone 更新成 123

實務上在做事情的時候,在用第一種類型的語句時絕對要千千萬萬分注意。因為你一個不小心忘記加上where的話,資料庫裡面所有的資料都會被你更新...這是一件很可怕的事情。

Delete

delete from users where name=peter
delete from users where name=peter and phone=123
  1. 把 users 裡面所有符合name=peter的資料刪除
  2. 把 users 裡面所有符合name=peter而且phone=123的資料刪除

這個指令跟上面那個更新一樣,要用的時候絕對要非常小心。

上面的這些指令都是最基本的用法,但很多時候你會需要更多更多不同的指令才能組合出你想要的資料。

有興趣的朋友可以到codecademy去練習,或者是參考我個人強力推薦的一系列教學:MySQL 超新手入門

SQL 的介紹就到這邊差不多了。可是別忘記了,我們還有另外一個東西沒有講,叫做 NoSQL。再提到它之前我們先來一個簡單的名詞解惑,那就是 MySQL 跟 SQL 有什麼不一樣?

首先,SQL 就是一個拿來查詢資料庫的語言。因為他只是一個語言,所以你沒辦法說「我的程式是用 SQL 當資料庫」。SQL 並不是一個資料庫系統,MySQL 才是。現在比較多人用的資料庫系統一般就三個:MySQL, PostgreSQL 還有 Microsoft SQL Server。共通點就是名字裡面都有 SQL。

其實這三套用起來的感覺差不多,因為你都可以用我們剛剛學到的 SQL 語言來下語法,只是在不同的資料庫系統,可能有些指令會不太一樣,或者是有些資料庫系統會再擴充自己專屬的指令方便你查詢。

任何一種以 SQL 為基礎的資料庫系統,都有差不多的特性,例如說他們必須事先定義好 Schema,你可以想成是資料庫的規格書。就是資料庫裡面要有哪些欄位、每一個欄位的資料型態是什麼。你在建立一張 Table 的時候,也是要用資料庫指令去新建的:

CREATE TABLE users(
  id int,
  name char(50),
  phone  char(20)
);

會先把每一個欄位的名稱跟型態都先固定住。這個就是 SQL 的一個特點。還有另外一個特點是「關聯式資料庫」,這是什麼意思呢?就是因為要讓資料儲存跟取得容易,所以會用「關聯」的方式把一些東西切開來。

舉例來說好了,你現在要寫一個部落格系統,於是你需要一個可以儲存文章的 Table,欄位的部分你可能會這樣設計:

id, author, content, create_time

接著你要加入一個可以在文章底下留評論的功能,你就需要另外一張 Comments 的 Table。因為你必須知道這個評論是屬於哪一篇留言的評論,所以你要在裡面新增一個欄位叫做post_id,才能把某篇文章跟這一堆評論「關聯」起來。所以文章跟評論的關係就是「一對多」,一篇文章可以有很多個評論。

id, post_id, content, create_time

如果你想撈出文章 id 是 123 的所有評論,你只要 select * from comments where post_id=123 這樣就好了。當然這個是屬於比較簡單的範例,還有更複雜的場景以及更複雜的關係。這些你在我上面提供的那個超新手入門應該都看得懂,我就先不講了。

鋪陳了這麼久,終於可以來講 NoSQL,這個名詞只是為了強調他跟上面我們講的那些關聯式資料庫系統不太一樣,所以用了 NoSQL 這個詞。其中最大的差別大概就是 NoSQL 沒有 schema 這種東西,所以你不必事先知道你要存哪些資料。這樣的好處當然就是比較彈性,可是相對的你在查詢資料的時候速度也會比較慢一點。而且這些 NoSQL 系統,儲存資料的格式通常都是 JSON。

以上面那個文章跟評論的系統為例,如果你把資料存在 NoSQL 的資料庫裡面,可能就會長這樣:

{
  id: 1,
  author: 'huli',
  content: '大家好',
  create_time: 12345,
  comments: [
    {
      id: 1,
      content: 'comment 1',
      create_time: ...
    }, {
      id: 2,
      content: 'comment2',
      create_time: ...
  }
  ]
}

有沒有發現哪邊不一樣?他把評論直接跟文章本身存在一起了!這點是 SQL 做不到的事情。(其實硬要做也是可以啦,但你會發現非常麻煩而且根本沒必要,查詢的時候也很不方便。你可以想想看怎麼做。不過最近 MySQL, postgreSQL 提供了資料格式是 JSON 的欄位,這又是另外一回事了)。

根據我個人的使用經驗來說,NoSQL 最適合的一點是搜集數據。例如說現在很多手機 App 其實會偷偷搜集你資料傳回去,做一些數據分析之類的。他可能會搜集:手機廠牌、型號、作業系統版本、安裝過的 App 等等的。這時候如果你是用一般傳統的 SQL 資料庫,你要怎麼定義 Schema?你的欄位會有超級多個,而且一旦你想要儲存新的追蹤資訊的時候,你就必須去改一次資料庫,這是很麻煩的行為。這時候用 NoSQL 就很方便了,你只要直接把資料存進去就好,什麼都不用想。你不必知道到底有多少項的追蹤資訊。

其實我寫到這邊,突然發現現在講這些可能會有點早,怕大家消化不良。但既然都講了,大家就先聽聽吧。可以不用完全弄懂,至少知道有這個概念就好。為了怕我講的不清不楚,附上幾篇文章給大家參考:

  1. NoSQL 與 SQL
  2. 關於NoSQL與SQL的區別
  3. 了解NoSQL不可不知的5項觀念

最後來個總結。

SQL 跟 NoSQL 並不是互斥的概念,你可以在你的系統裡面用 SQL 類的資料庫系統儲存文章、評論,同時也用 NoSQL 類的資料庫來搜集使用者資訊。這些本來就是根據你的業務不同而定的。最慘的是那種根本不知道為什麼要用的,或者是盲目追求潮流的。再強調一遍,你要根據你的業務來選擇適合的技術棧。沒有最好的技術棧,只有最適合自己的。就算 NoSQL 聽起來比較潮,但是適合用 SQL 的地方,就乖乖用 SQL 就好。

然後這一篇會講到資料庫系統是因為,上一篇我們成功地利用檔案以及自己規劃的規範完成了「長久的儲存資料」這件事情,可是發現還有一些問題沒有處理好(例如說覆蓋資料、速度太慢等等),所以我們需要專業的協助。而這個協助當然就是資料庫系統了,人家就是設計出來專門讓你儲存資料的。效率什麼的一定比自己實作的好太多了,而且又是大家的標準。上一篇只是讓你體驗一下,原來不需要資料庫系統也可以自己設計出一套儲存資料的方式,只是不夠好而已。不過,「先求有再求好」,一直是我秉持的原則。

下一篇,我們就要來實戰了。


上一篇
想~簡簡單單愛:超簡單留言板
下一篇
沒那麼簡單~的留言板
系列文
Half-Stack Developer 養成計畫30

1 則留言

0
djcs
iT邦新手 5 級 ‧ 2016-12-29 07:23:11

Good

我要留言

立即登入留言