好的設計讓你上天堂,爛的設計讓你下地獄。
如果公司有專門的 DBA,後端工程師就可以把心力放在資料邏輯的處理上;但筆者詢問周圍的朋友,似乎有不少公司都是讓後端工程師兼任 DBA...
筆者在這塊也並非專家,主要是分享自己實作中會注意的基礎細節,避免犯下一些原則性錯誤
。
設計資料庫時會考量哪些點?
回答問題所需具備的知識
衍伸問題
履歷資訊
中表明擅長多種資料庫(Database)
履歷資訊
中還表明有優化資料庫的經驗。
在決定要使用什麼資料庫前,我會先分析專案的應用場景
:
商城
會有金流,所以資料穩定性與 Transaction 機制是很重要的。地圖平台
,就會選擇對 GIS 支援度高的資料庫。在設計資料庫時會畫 ER Model
來分析資料間的關聯與屬性;在優化方面,為了要提高搜尋效率會在 Table 建立 Index
,同時也會依據實際業務設計欄位適合的長度及 Type
。
我們知道在 Table 建立 Index 可以增加搜尋效率,但你知道自己建立的 Index 有沒有派上用場嗎?筆者將在這個小節透過實作,帶大家了解 Coverage Index (覆蓋索引)
的意義。
SETP 1:建立測試用的 tmp_user Table
create table tmp_user (
id bigint(20) not null auto_increment ,
name varchar(255) not null,
password varchar(255) ,
index index_name (name),
primary key (id))
engine=innodb
default character set=utf8 collate=utf8_general_ci;
insert into tmp_user (name, password) values ("寶寶不說","123");
SETP 2:下 SQL 指令了解是否使用 Index
觀察最後「Extra」欄位的資訊有否有
Using index
explain select id from user_table where name= '寶寶不說';
name
有建立 index,所以在查詢到 name
後可以直接與 id
對應返回結果;因為 name 已經覆蓋了查詢資料的需求,所以稱為 「Coverage Index」。explain select password from user_table where name= '寶寶不說';
name
找到「寶寶不說」對應的 id
,但接著要透過 id 這個 primary key
,在 Table 重新輪詢才能取得這一列的完整資料。SETP 3:建立 Coverage Index 優化 SQL B
先將資料庫 drop 掉:drop table tmp_user;
重新建立測試資料以及「Coverage Index」
為了避免用 primary key 再次從 Table 查詢的耗能,我們可以把 select 與 where 用到的欄位(name、password)做聯合索引
,這樣就能夠直接使用索引查詢,而不需用 primary key 重新比對,這就是「Coverage Index」的應用。
create table tmp_user (
id bigint(20) not null auto_increment ,
name varchar(255) not null,
password varchar(255) ,
primary key (id))
engine=innodb
default character set=utf8 collate=utf8_general_ci;
insert into tmp_user (name, password) values ("寶寶不說","123");
alter table tmp_user add index name_password(name,password);
再次執行 SQL B:explain select password from tmp_user where name = '寶寶不說';
本次的查詢就可以在「Extra」欄位看到 Using index
嚕~
使用 ER Model 做規畫
在需求規格出來後,我們可以先透過 ER Model 整理資料間的關聯性,然後以此為基礎設計資料庫;向新人說明 Table 間的關聯時,它也是一個非常棒的輔助工具。
設計合適的文字欄位
避免使用 TEXT/BLOB
這類的 Type,它們在查詢時會消耗更多的效能。減少 SQL 寫入次數
以 Insert 來做舉例,假設有 1000 筆資料要寫入 Table;一次插入 1000 筆的執行時間會遠遠小於分 1000 次插入的時間。
適當的增加冗餘欄位
在設計資料庫時要盡量符合三大正規化;但 Table 間的關聯越複雜也會導致查詢效率的下降
,因此有時會適當的增加冗餘欄位,用犧牲磁碟空間的方式換取更高的查詢效率。
定期審視資料庫的規劃
如果沒有專門的 DBA,那資料庫通常會有以下問題需要修正:
欄位長度開到最大
。新增許多無用欄位
。沒有整理
不符合實際業務需求的檢視表(View)
。許多 Index 並沒有發揮作用
。MySQL
是世界上最流行的資料庫之一,世界上有非常多的 Web Application 都採用它作為解決方案;但在被收購後分出了非常多的版本,有免費也有收費的
;而 PostgreSQL
基於 BSD/MIT 的 linecense,為完全開源的資料庫
。
PostgreSQL 的優勢
整合關聯式資料與非關聯式資料
。支持「二維、三維、曲線」的空間類型
,並有豐富的空間操作函數。聯合資料庫
。MySQL 的優勢
在招募工程師時更容易
,遇到問題時也有豐富的社群資源提供解答。PostgreSQL 可以搭配 Connection Pool 的外掛解決這個問題,但架構上就會變更複雜。
應用場景
其實在 DB 的選擇上,除了考慮專案適用的場景外,還要考量到
團隊內的工程師對哪個比較擅長;思考萬一發生意外時有誰可以救場
,不然災難復原是一場惡夢。
考點:了解 Index 對資料庫效能的影響
Index 的數量太多,會影嚮 DML(Insert、Update、Delete)的效能,因為 Table 資料更新時也要連帶更新 Index
。
考點:確認求職者的 SQL 基本功
回傳固定筆數
(ex:limit)。只抓取需要的欄位
。Index
來做搜尋。避免使用不兼容的型態
做比較,像是 FLOAT 跟 INT、CHAR 跟 VARCHAR。考點:確認求職者對 NoSQL 的認知
即便你的履歷中沒有寫自己會 NoSQL,還是會遇到這類考題,所以建議至少有基礎的認知。
MongoDB
這類的 NoSQL,就可以很靈活的對欄位進行調整。Redis
這類記憶體資料庫,單一節點就能應付每秒 10 萬次的讀寫請求。水平擴充
能力,只要增加新的伺服器節點就能擴充資料庫容量;且對於伺服器的性能要求較低,可使用較便宜
的電腦進行擴充。考點:確認求職者是否有評估的能力與經驗
我會考慮的點有資料量多寡、併發量、實時性、資料一致性、未來擴充性、資料穩定性、維護成本
。
以企業內部管理系統來說,因為資料量少、併發數少、未來擴充需求較低,所以會選擇關連式資料庫;如果是遊戲的排行榜頁面,因為資料量大、併發數高、且要求高的更新頻率,所以我會考慮使用記憶體資料庫(ex:Redis)。
感謝大家的閱讀,如果喜歡我的文章可以訂閱
接收通知;如果有幫助到你,按Like
可以讓我更有寫文的動力,我們明天見~
我在 Medium 平台 也分享了許多技術文章
❝ 主題涵蓋「MIS & DEVOPS、資料庫、前端、後端、MICROSFT 365、GOOGLE 雲端應用、自我修煉」希望可以幫助遇到相同問題、想自我成長的人。❞
在許多人的幫助下,本系列文章已成功出版,除了添加新的篇章,更完善了每個案例的應對進退;如果對現在的職涯感到迷茫,也許這本書能帶給你不一樣的觀點~