「不是工程師」後端服務的根基,淺談SQL關連式資料庫 RDBMS
你知道資料庫是什麼嗎?什麼又是SQL語法呢?會用ORM系統了還要學習SQL嗎?
「等等,讓我下個SQL去資料庫裡面看一下」
相信這句話一定最可以代表後端工程師的一句心聲,
但究竟資料庫是什麼,什麼又是SQL語法呢?
「不是工程師」後端服務的根基,淺談SQL關連式資料庫 RDBMS
「不是工程師」關聯式資料庫正規化是什麼? 先從第一正規化(1NF)開始吧!
「不是工程師」外鍵Foreign key(FK)是什麼?從第二正規化(2NF)去除冗余資料談起吧!
「不是工程師」可以邏輯推斷出來就不要多加欄位?淺談資料庫第三正規化(3NF)
最多人用的關聯性資料庫 - MySQL 相關文章:
MySQL要怎麼念?淺談MySQL資料庫與MariaDB的歷史緣由
延伸閱讀:
SQL 語法好難背不起來?關聯式資料庫苦無對策?或許你該試試 ORM 函式庫!
這要稍微往一般人使用電腦的邏輯去想,基本上我們使用電腦幾乎一定會有一個儲存的動作,無論是你在寫報告使用Word,或是你在玩遊戲儲存記錄或是虛擬人物資訊裝備等。以遊戲來說,同時上線人數1萬人,如果每個玩家的資料都用Word檔去存在硬碟,當需要使用資料的時候應該是不太容易找到,而且硬碟的讀寫速度其實並不是那麼快,所以一般作業系統會使用讀寫速度比較快的RAM(快閃記憶體)來處理。簡單的說,作業系統會先把資料從硬碟完整的搬到RAM,再讓CPU使用RAM來執行程式。當執行完了以後再回寫進硬碟。
那這樣會有什麼問題呢?就目前來講,「個人級」頂規的電腦的RAM也大概才配到32GB,但是硬碟卻有可能是3TB,幾乎是100倍。即使是伺服器主機,其實也差不多(Linode 1 CPU, 2GB RAM, 50 GB SSD 租金 10美金/月,AWS只會更貴而已)。因此你不太可能把所有的內容放進去RAM以後才開始執行。
延伸閱讀:學習VPS的重要性與各大Linux VPS 比較(Linode, DigitalOcean, Vultr, AWS Lightsail)
比較容易理解的解決方案是當某位玩家上線的時候,才把他的資料讀進RAM,當他下線以後,我們再回存。但其實這也有很多問題,比方說打到一半電腦跳電,那資料就不見了。或是這個玩家玩了10年,資料量超大,但是其實他已經玩膩了只是開上來聊天的,很多他的資料其實用不著在一開始的時候讀取,不然一堆老玩家一起上線,RAM就被吃光了。所以程式邏輯其實會相當複雜,有讀取策略、回寫硬碟策略等。到現在發展起來,連資料存法都有很多種不同的架構。
通常事情複雜就會需要解決,而「資料庫概念」就是一種解決方案。讓一個獨立的程式去管理你的資料,他在管理資料的時候會考量到ACID:
基元性(atomicity)
一致性(consistency)
隔離性(isolation)
持續性(durability)
因為這是淺談,所以就不解釋這四個名詞,不過簡單來說就是保證資料的正確性,當然這中間包含了大量的程式邏輯。不過以使用者來說,只要正確使用資料庫的話就可以保證非常高程度的資料正確,尤其是同步處理大量使用者的情況。因此寫任何型態的應用程式邏輯上是不一定需要資料庫的,但是說實在的,自己撰寫處理資料幾乎可以說100%不會比使用資料庫來的好(全世界大量的使用者、2~30年以上的驗證)。所以只要跟資料有關的運用,多半都會建議使用資料庫。
不過雖然上面說的好像很複雜,但是因為已經標準化了很久。所以「資料庫」對一般後端開發者來說,就是把資料存在資料庫(Database,
一般來說資料庫最基本的功能就是提供「新增 Create」、「查詢 Read」、「更新 Update」、「刪除 Delete」等資料維護,可以簡稱為 CRUD。資料庫你可以想成是一個大型檔案夾,每當有CRUD時,
舉例而言,像電商服務的訂單成立,或是社群網站的動態發布等等,
而現今主流的「資料庫類型」可分為兩種,一種是關聯式資料庫(
資料庫本身,雖然前面以Word舉例,但是其實他比較像一個巨大的Excel表格,
同理,以電商系統來說,如果所有的資訊都記錄一起,
例如商品條碼號為987654321,上架打錯成123456789
無效率設計:一個資料表
訂單編號 | 訂購者 | 商品名稱 | 商品條碼號 | 數量 |
Order001 | 王大明 | iPhone 2000 | 123456789 | 1 |
Order002 | 李小明 | iPhone 2000 | 123456789 | 2 |
這樣的好處是看起來直覺,但是如果今天有1000筆資料錯誤,就要改1000次
較有效率設計:拆成兩個資料表
商品編號 | 商品名稱 | 商品條碼號 | 剩餘數量 |
Product001 | iPhone 2000 | 123456789 | 10000 |
Product002 | Macbook Pro 2200 15" | 220078987 | 2000 |
訂單編號 | 訂購者 | 商品編號 | 數量 |
Order001 | 王大明 | Product001 | 1 |
Order002 | 李小明 | Product001 | 2 |
這樣的壞處是要看完整資料比較麻煩,要取得王大明到底買了什麼需要先抓到他買的商品編號(Product001),再利用商品編號去找出商品名稱,有點像「連連看」。但是今天如果商品條碼號錯誤,只需要改一個值就好(只出現1次),方便很多。
此外,可能大家會想說「無效率版」總共只有10格資料欄位(不含標題)。但是「有效率版」用掉了16格資料欄位,感覺比較浪費空間。但其實那是因為只有2筆訂單的關係。如果用1000筆訂單來看。
「無效率版」,每筆訂單耗掉5格,1000筆就是5000格
「有效率版」,每筆訂單耗掉4格,1000筆就是4000格 + 商品欄位的 8格 = 4008格。所以其實只要量大到一定,下面消耗的格數就會比較少,而格數就可以想成是記憶體空間。
你也可以用簡單的數學來計算這個問題。
請問 Row 最小等於多少時,這個式子成立。
答案是 Row 9 以上,所以在這樣的設計下只要有9筆訂單就會比較節省空間。
(真實情況要看你的欄位怎麼設計,一般不會設計的這麼簡單。)
所以一但今天資料變得巨量,意味著在進行新增、修改、刪除、
所以回顧一下關連式資料庫,
所以即使是SQL已經相當成熟的現在,用同樣的SQL語句在資料庫A可以執行,但是在資料庫B還是可能會報錯。或是在資料庫A、B都可以執行,但是出來的結果不同還是有可能的(不過可以放心,常用語句大多都會相同)。
所謂的ORM 系統就是像Ruby on Rails裡面的 Active Record, PHP Laravel 裡面的 Equlent。
在這些ORM系統裡面你多半不用直接撰寫SQL語句,而是用一般應用程式的語法來撰寫。
比方說如果你想要讓你的網頁讀取資料庫裡面的資料呈現,假設為Products 資料表
純SQL的寫法會是:
SELECT * from Products
然後要包裝成程式語句用字串的方式送出
DBconnect.excute("SELECT * from Products")
其中DBconnect.excute是虛擬碼,代表與資料庫通訊的API
但是如果以ORM 來說的話會是下面的寫法:
Ruby on Rails:
Product.all()
Laravel:
Product::all()
所以會發現簡單很多而且明確。不過ORM系統並不是有什麼額外管道可以從資料庫讀取資料,只是ORM系統會在內部執行的時候把 Product.all() 換成類似 DBconnect.excute("SELECT * from Products") 去執行罷了。因此很多情況如果ORM 系統效率不好的時候,還是要去研究它究竟幫我們轉換出了什麼語句,這時候SQL語法與資料庫知識就很重要了。
相信在以上的介紹之後,大家對資料庫應該都有了基本上的概念了,
延伸閱讀:
[不是工程師] 讓網站速度飛快的秘密,你了解什麼是網頁快取(Cache)嗎?
但資料庫的結構化卻是一個必然的趨勢,在結構愈趨複雜的狀況下,
最後廣告一下,如果對資料庫設計和網站架設有興趣的話,可以考慮參加我們課程:
從零開始的SQL語法與資料庫設計 - 以MySQL來攻略 是MySQL的初階至中階課程,除了基本SQL語法的教學外,也包含資料庫設計理念與實作。對於一直搞不懂資料庫的同學會有相當的幫助喔!
快速開發,從頭教起的Ruby on Rails後端之旅 是後端網站APP課程開發課程,課程中包含詳細的購物網站架設與資料庫設計教學,內容涵蓋SQLite, MySQL, PostgreSQL,以及最後的募資平台(含資料表設計),可以參考看看喔!
最後,如果你喜歡我們的文章,別忘了到我們的FB粉絲團按讚喔!!