資料庫表結構設計常見的資料庫管理系統
一、資料場景
1、表結構簡介
任何工具類的東西都是為了解決某個場景下的問題,比如Redis快取系統熱點資料,ClickHouse解決海量資料的實時分析,MySQL關係型資料庫儲存結構化資料。資料的儲存則需要設計對應的表結構,清楚的表結構,有助於快速開發業務,和理解系統。表結構的設計通常從下面幾個方面考慮:業務場景、設計規範、表結構、欄位屬性、資料管理。
2、使用者場景
例如儲存使用者基礎資訊資料,通常都會下面幾個相關表結構:使用者資訊表、單點登入表、狀態管理表、支付賬戶表等。
使用者資訊表
儲存使用者三要素相關資訊:姓名,手機號,身份證,登入密碼,郵箱等。
CREATE TABLE `ms_user_center` (
`id` int(11) NOT NULL AUTO_INCREMENT COMMENT '使用者ID',
`user_name` varchar(20) NOT NULL COMMENT '使用者名稱',
`real_name` varchar(20) DEFAULT NULL COMMENT '真實姓名',
`pass_word` varchar(32) NOT NULL COMMENT '密碼',
`phone` varchar(20) NOT NULL COMMENT '手機號',
`email` varchar(32) DEFAULT NULL COMMENT '郵箱',
`head_url` varchar(100) DEFAULT NULL COMMENT '使用者頭像URL',
`card_id` varchar(32) DEFAULT NULL COMMENT '身份證號',
`user_sex` int(1) DEFAULT '1' COMMENT '使用者性別:0-女,1-男',
`create_time` datetime DEFAULT NULL COMMENT '建立時間',
`update_time` datetime DEFAULT NULL COMMENT '更新時間',
`state` int(1) DEFAULT '1' COMMENT '是否可用,0-不可用,1-可用',
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='使用者表';
單點登入表
用意是在多個業務系統中,使用者登入一次就可以訪問所有相互信任的業務子系統,是聚合業務平臺常用的解決方案。
CREATE TABLE `ms_user_sso` (
`user_id` int(11) NOT NULL COMMENT '使用者ID',
`sso_id` varchar(32) NOT NULL COMMENT '單點資訊編號ID',
`sso_code` varchar(32) NOT NULL COMMENT '單點登入碼,唯一核心標識',
`log_ip` varchar(32) DEFAULT NULL COMMENT '登入IP地址',
`create_time` datetime DEFAULT NULL COMMENT '建立時間',
`update_time` datetime DEFAULT NULL COMMENT '更新時間',
`state` int(1) DEFAULT '1' COMMENT '是否可用,0-不可用,1-可用',
PRIMARY KEY (`user_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='使用者單點登入表';
狀態管理表
系統使用者在使用時候可能出現多個狀態,例如賬戶凍結、密碼鎖定等,把狀態聚合到一起,可以更加方便的管理和驗證。
CREATE TABLE `ms_user_status` (
`user_id` int(11) NOT NULL COMMENT '使用者ID',
`account_status` int(1) DEFAULT '1' COMMENT '賬戶狀態:0-凍結,1-未凍結',
`real_name_status` int(1) DEFAULT '0' COMMENT '實名認證狀態:0-未實名,1-已實名',
`pay_pass_status` int(1) DEFAULT '0' COMMENT '支付密碼是否設定:0-未設定,1-設定',
`wallet_pass_status` int(1) DEFAULT '0' COMMENT '錢包密碼是否設定:0-未設定,1-設定',
`wallet_status` int(1) DEFAULT '1' COMMENT '錢包是否凍結:0-凍結,1-未凍結',
`email_status` int(1) DEFAULT '0' COMMENT '郵箱狀態:0-未啟用,1-啟用',
`message_status` int(1) DEFAULT '1' COMMENT '簡訊提醒開啟:0-未開啟,1-開啟',
`letter_status` int(1) DEFAULT '1' COMMENT '站內信提醒開啟:0-未開啟,1-開啟',
`emailmsg_status` int(1) DEFAULT '0' COMMENT '郵件提醒開啟:0-未開啟,1-開啟',
`create_time` datetime DEFAULT NULL COMMENT '建立時間',
`update_time` datetime DEFAULT NULL COMMENT '更新時間',
`state` int(1) DEFAULT '1' COMMENT '是否可用,0-不可用,1-可用',
PRIMARY KEY (`user_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='使用者狀態表';
支付賬戶表
使用者交易的核心表,儲存使用者相關的賬戶資金資訊。
CREATE TABLE `ms_user_wallet` (
`wallet_id` int(11) NOT NULL AUTO_INCREMENT COMMENT '錢包ID',
`user_id` int(11) NOT NULL COMMENT '使用者ID',
`wallet_pwd` varchar(32) DEFAULT NULL COMMENT '錢包密碼',
`total_account` decimal(20,2) DEFAULT '0.00' COMMENT '賬戶總額',
`usable_money` decimal(20,2) DEFAULT '0.00' COMMENT '可用餘額',
`freeze_money` decimal(20,2) DEFAULT '0.00' COMMENT '凍結金額',
`freeze_time` datetime DEFAULT NULL COMMENT '凍結時間',
`thaw_time` datetime DEFAULT NULL COMMENT '解凍時間',
`create_time` datetime DEFAULT NULL COMMENT '建立時間',
`update_time` datetime DEFAULT NULL COMMENT '更新時間',
`state` int(1) DEFAULT '1' COMMENT '是否可用,0-不可用,1-可用',
PRIMARY KEY (`wallet_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='使用者錢包';
二、設計規範
1、涉及模組
透過上面幾個表設計的案例,可以看到表設計關聯到資料庫的各個方面知識:資料型別,索引,編碼,儲存引擎等。表設計是一個很大的命題,不過也遵循一個基本規範:三正規化。
2、三正規化
基礎概念
一正規化
表的列的具有原子性,不可再分解,即列的資訊,不能分解,關係型資料庫MySQL、Oracle等自動的滿足。
二正規化
每個事實的資料記錄只會出現一次, 不會冗餘, 通常設計一個主鍵來實現。
三正規化
要求一個表中不包含已經存在於其它表的非主鍵資訊,例如部門和員工的資訊,員工表包含部門表的主鍵ID,則可以關聯獲取相關資訊,沒必要在員工表儲存相關資訊。
優缺點對比
正規化化設計
正規化化結構設計通常更新快,因為冗餘資料較少,表結構輕巧,也更好的寫入記憶體中。但是查詢起來涉及到關聯,代價非常高,非常損耗查詢效能。
反正規化化設計
所有的資料都在一張表中,避免關聯查詢,索引的有效性更高,但是資料的冗餘性極高。
建議結論
上述的兩種設計方式在實際開發中都是不存在的,在實際開發中都是混合使用。比如彙總統計,快取資料,都會基於反正規化化的設計。
三、欄位屬性
合適的欄位型別對於高效能來說非常重要,基本原則如下:簡單的型別佔用資源更少;在可以正確儲存資料的情況下,選最小的資料型別。
1、資料型別選擇
整數型別
TINYINT、SMALLINT、MEDIUMINT、INT、BIGINT,根據資料型別範圍合理選擇即可。
實數型別
FLOAT、DOUBLE、DECIMAL,建議資金貨幣相關型別使用高精度DECIMAL儲存,或者把資料成倍擴大為整數,採用BIGINT儲存,不過處理相對麻煩。
字元型別
CHAR、VARCHAR,長度不確定建議採用VARCHAR儲存,不過VARCHAR型別需要額外開銷記錄字串長度。CHAR適合儲存短字元,或者定長字串,例如MD5的加密結構。
時間型別
DATETIME、TIMESTAMP,DATETIME儲存大範圍的值,精度秒。TIMESTAMP以時間戳的格式,範圍相對較小,效率也相對較高,所以通常情況建議使用。
MySQL的欄位型別有很多種,可以根據資料特性選擇合適的,這裡只描述常見的幾種型別。
2、基礎用法操作
資料型別
修改欄位型別
ALTER TABLE ms_user_sso MODIFY state CHAR(1) DEFAULT '0' ;
ALTER TABLE ms_user_sso
MODIFY state INT(1) DEFAULT '1' COMMENT '狀態:0不可用,1可用';
修改名稱位置
ALTER TABLE ms_user_sso
CHANGE log_ip login_ip VARCHAR(32) AFTER update_time ;
索引使用
索引型別:主鍵索引,普通索引,唯一索引,組合索引,全文索引。這裡演示普通索引的操作。MySQL的核心模組,後續詳說。
新增索引
ALTER TABLE ms_user_wallet ADD INDEX user_id_index(user_id) ;
CREATE INDEX state_index ON ms_user_wallet(state) ;
檢視索引
SHOW INDEX FROM ms_user_wallet;
刪除索引
DROP INDEX state_index ON ms_user_wallet ;
修改索引
不具有真正意義上的修改,可以把原有的索引刪除之後,再次新增索引。
外來鍵關聯
用處:外來鍵關聯的作用保證多個資料表的資料一致性和完整性,建表時先有主表,後有從表;刪除資料表,需要先刪從表,再刪主表。複雜場景不建議使用,實際開發中用的也不多。
新增外來鍵
ALTER TABLE ms_user_wallet
ADD CONSTRAINT user_id_out_key FOREIGN KEY(user_id) REFERENCES ms_user_center(id) ;
刪除外來鍵
ALTER TABLE ms_user_wallet DROP FOREIGN KEY user_id_out_key ;
四、表結構管理
1、檢視結構
DESC ms_user_status ;
SHOW CREATE TABLE ms_user_status ;
2、欄位結構
新增欄位
ALTER TABLE ms_user_status
ADD `delete_time` datetime DEFAULT NULL COMMENT '刪除時間' ;
刪除欄位
ALTER TABLE ms_user_status DROP COLUMN delete_time ;
3、修改表名
ALTER TABLE ms_user_center RENAME ms_user_info ;
4、儲存引擎
儲存引擎
SELECT VERSION() ; SHOW ENGINES ;
MySQL 5.6 支援的儲存引擎有InnoDB、MyISAM、Memory、Archive、CSV、BLACKHOLE等。一般預設使用InnoDB,支援事務管理。該模組MySQL核心,後續詳解。
修改引擎
資料量大的場景下,儲存引擎修改是一個難度極大的操作,容易會導致表的特性變動,引起各種後續反應,後續會詳說。
ALTER TABLE ms_user_sso ENGINE = MyISAM ;
5、修改編碼
表字符集預設使用utf8,通用,無亂碼風險,漢字3位元組,英文1位元組,utf8mb4是utf8的超集,有儲存4位元組例如表情符號時使用。
檢視編碼
SHOW VARIABLES LIKE 'character%';
修改編碼
ALTER TABLE ms_user_sso DEFAULT CHARACTER SET utf8mb4;
五、資料管理
1、增刪改查
新增資料
INSERT INTO ms_user_sso (
user_id,sso_id,sso_code,create_time,update_time,login_ip,state
)
VALUES
(
'1','SSO7637267','SSO78631273612',
'2019-12-24 11:56:57','2019-12-24 11:57:01','127.0.0.1','1'
);
更新資料
UPDATE ms_user_sso SET
user_id = '1',sso_id = 'SSO20191224',sso_code = 'SSO20191224',
create_time = '2019-11-24 11:56:57',update_time = '2019-11-24 11:57:01',
login_ip = '127.0.0.1',state = '1'
WHERE user_id = '1';
查詢資料
一般情況下都是禁止使用 select* 操作。
SELECT user_id,sso_id,sso_code,create_time,update_time,login_ip,state
FROM ms_user_sso WHERE user_id = '1';
刪除資料
DELETE FROM ms_user_sso WHERE user_id = '2' ;
不帶where條件,就是刪除全部資料。原則上不允許該操作,最佳化篇會詳解。TRUNCATE TABLE也是清空表資料,但是佔用的資源相對較少。
2、資料安全
不可逆加密
這類加密演算法,多用來做資料驗證操作,比如常見的密碼驗證。
SELECT MD5('cicada')='94454b1241ad2cfbd0c44efda1b6b6ba' ;
SELECT SHA('cicada')='0501746a2e4fd34e1d14015fc4d58309585edc7d';
SELECT PASSWORD('smile')='*B4FB95D86DCFC3F33A3852714DC742C77504479D' ;
可逆加密
安全性要求高的系統,需要做三級等保,對資料的安全性極高,資料在儲存時必須加密入庫,取出時候需要解密,這些就需要可逆加密。
SELECT DECODE(ENCODE('123456','key_salt'),'key_salt') ;
SELECT AES_DECRYPT(AES_ENCRYPT('cicada','salt123'),'salt123');
上述資料安全的管理,也可以基於應用系統的服務(程式碼)層進行處理,相對專業的流程是從資料生成源頭處理,規避資料傳遞過程洩露,造成不必要的風險。
版權宣告:
作者:Julie Selby
連結:https://sh100k.com/zi-liao-ku-biao-jie-gou-she-ji-chang-jian-de-zi-liao-ku/
來源:SH100K – 生活百科
文章版權歸作者所有,未經允許請勿轉載。