使用MySQL,請用好 JSON 這張牌!
互聯(lián)網(wǎng)架構師后臺回復 2T 有特別禮包
JSON(JavaScript Object Notation)主要用于互聯(lián)網(wǎng)應用服務之間的數(shù)據(jù)交換。MySQL 支持RFC 7159定義的 JSON 規(guī)范,主要有 JSON 對象 和 JSON 數(shù)組 兩種類型。下面就是 JSON 對象,主要用來存儲圖片的相關信息:
{"Image": {"Width": 800,"Height": 600,"Title": "View from 15th Floor","Thumbnail": {"Url": "http://www.example.com/image/xx9943","Height": 125,"Width": 100},"IDs": [116, 943, 234, 38793]}}
[{"precision": "zip","Latitude": 37.7668,"Longitude": -122.3959,"Address": "","City": "SAN FRANCISCO","State": "CA","Zip": "94107","Country": "US"},{"precision": "zip","Latitude": 37.371991,"Longitude": -122.026020,"Address": "","City": "SUNNYVALE","State": "CA","Zip": "94085","Country": "US"}]
用戶登錄設計
DROP TABLE IF EXISTS UserLogin;CREATE TABLE UserLogin (userId BIGINT NOT NULL,loginInfo JSON,PRIMARY KEY(userId));
由于當前業(yè)務的登錄方式越來越多樣化,如同一賬戶支持手機、微信、QQ 賬號登錄,所以這里可以用 JSON 類型存儲登錄的信息。
SET @a = '{"cellphone" : "1","wxchat" : "碼農","77" : "1"}';INSERT INTO UserLogin VALUES (1,@a);SET @b = '{"cellphone" : "1188"}';INSERT INTO UserLogin VALUES (2,@b);
SELECTuserId,JSON_UNQUOTE(JSON_EXTRACT(loginInfo,"$.cellphone")) cellphone,JSON_UNQUOTE(JSON_EXTRACT(loginInfo,"$.wxchat")) wxchatFROM UserLogin;+--------+-------------+--------------+| userId | cellphone | wxchat |+--------+-------------+--------------+| 1 | 11| 碼農 || 2 | 11| NULL |+--------+-------------+--------------+2 rows in set (0.01 sec)
SELECTuserId,loginInfo->>"$.cellphone" cellphone,loginInfo->>"$.wxchat" wxchatFROM UserLogin;
ALTER TABLE UserLogin ADD COLUMN cellphone VARCHAR(255) AS (loginInfo->>"$.cellphone");ALTER TABLE UserLogin ADD UNIQUE INDEX idx_cellphone(cellphone);
EXPLAIN SELECT * FROM UserLoginWHERE cellphone = '11'\G*************************** 1. row ***************************id: 1select_type: SIMPLEtable: UserLoginpartitions: NULLtype: constpossible_keys: idx_cellphonekey: idx_cellphonekey_len: 1023ref: constrows: 1filtered: 100.00Extra: NULL1 row in set, 1 warning (0.00 sec)
CREATE TABLE UserLogin (userId BIGINT,loginInfo JSON,cellphone VARCHAR(255) AS (loginInfo->>"$.cellphone"),PRIMARY KEY(userId),UNIQUE KEY uk_idx_cellphone(cellphone));
用戶畫像設計
在電商行業(yè)中,根據(jù)用戶的穿搭喜好,推薦相應的商品; 在音樂行業(yè)中,根據(jù)用戶喜歡的音樂風格和常聽的歌手,推薦相應的歌曲; 在金融行業(yè),根據(jù)用戶的風險喜好和投資經(jīng)驗,推薦相應的理財產品。
CREATE TABLE Tags (tagId bigint auto_increment,tagName varchar(255) NOT NULL,primary key(tagId));SELECT * FROM Tags;+-------+--------------+| tagId | tagName |+-------+--------------+| 1 | 70后 || 2 | 80后 || 3 | 90后 || 4 | 00后 || 5 | 愛運動 || 6 | 高學歷 || 7 | 小資 || 8 | 有房 || 9 | 有車 || 10 | 常看電影 || 11 | 愛網(wǎng)購 || 12 | 愛外賣 |+-------+--------------+
若不用 JSON 數(shù)據(jù)類型進行標簽存儲,通常會將用戶標簽通過字符串,加上分割符的方式,在一個字段中存取用戶所有的標簽:
+-------+---------------------------------------+|用戶 |標簽 |+-------+---------------------------------------+|David |80后 ;高學歷 ;小資 ;有房 ;常看電影 ||Tom |90后 ;常看電影 ;愛外賣 |+-------+---------------------------------------
DROP TABLE IF EXISTS UserTag;CREATE TABLE UserTag (userId bigint NOT NULL,userTags JSON,PRIMARY KEY (userId));INSERT INTO UserTag VALUES (1,'[2,6,8,10]');INSERT INTO UserTag VALUES (2,'[3,10,12]');
ALTER TABLE UserTagADD INDEX idx_user_tags ((cast((userTags->"$") as unsigned array)));
EXPLAIN SELECT * FROM UserTagWHERE 10 MEMBER OF(userTags->"$")\G*************************** 1. row ***************************id: 1select_type: SIMPLEtable: UserTagpartitions: NULLtype: refpossible_keys: idx_user_tagskey: idx_user_tagskey_len: 9ref: constrows: 1filtered: 100.00Extra: Using where1 row in set, 1 warning (0.00 sec)SELECT * FROM UserTagWHERE 10 MEMBER OF(userTags->"$");+--------+---------------+| userId | userTags |+--------+---------------+| 1 | [2, 6, 8, 10] || 2 | [3, 10, 12] |+--------+---------------+2 rows in set (0.00 sec)
如果想要查詢畫像為 80 后,且常看電影的用戶,可以使用函數(shù) JSON_CONTAINS:搜索公眾號互聯(lián)網(wǎng)架構師回復“2T”,送你一份驚喜禮包。
EXPLAIN SELECT * FROM UserTagWHERE JSON_CONTAINS(userTags->"$", '[2,10]')\G*************************** 1. row ***************************id: 1select_type: SIMPLEtable: UserTagpartitions: NULLtype: rangepossible_keys: idx_user_tagskey: idx_user_tagskey_len: 9ref: NULLrows: 3filtered: 100.00Extra: Using where1 row in set, 1 warning (0.00 sec)SELECT * FROM UserTagWHERE JSON_CONTAINS(userTags->"$", '[2,10]');+--------+---------------+| userId | userTags |+--------+---------------+| 1 | [2, 6, 8, 10] |+--------+---------------+1 row in set (0.00 sec)
EXPLAIN SELECT * FROM UserTagWHERE JSON_OVERLAPS(userTags->"$", '[2,3,10]')\G*************************** 1. row ***************************id: 1select_type: SIMPLEtable: UserTagpartitions: NULLtype: rangepossible_keys: idx_user_tagskey: idx_user_tagskey_len: 9ref: NULLrows: 4filtered: 100.00Extra: Using where1 row in set, 1 warning (0.00 sec)SELECT * FROM UserTagWHERE JSON_OVERLAPS(userTags->"$", '[2,3,10]');+--------+---------------+| userId | userTags |+--------+---------------+| 1 | [2, 6, 8, 10] || 2 | [3, 10, 12] |+--------+---------------+2 rows in set (0.01 sec)
使用 JSON 數(shù)據(jù)類型,推薦用 MySQL 8.0.17 以上的版本,性能更好,同時也支持 Multi-Valued Indexes
不要將有明顯關系型的數(shù)據(jù)用 JSON 存儲,如用戶余額、用戶姓名、用戶身份證等,這些都是每個用戶必須包含的數(shù)據(jù);
JSON 數(shù)據(jù)類型推薦使用在不經(jīng)常更新的靜態(tài)數(shù)據(jù)存儲。
正文結束
1.心態(tài)崩了!稅前2萬4,到手1萬4,年終獎扣稅方式1月1日起施行~

評論
圖片
表情
