自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

MySQL5.7之Json Column和Generated Column

開發(fā) 開發(fā)工具
JSON的值包含單個值、數(shù)組、元組、標注的Json格式等幾種格式。

MySQL5.7新增兩種字段類型:Json和Generated,Generated型的產(chǎn)生和Json的關系密不可分,如果沒有Generated類型,Json類型在強大,生產(chǎn)中可能也無法使用,因為Json不支持索引,但是如果要查詢Json里的數(shù)據(jù),沒有索引就是全表掃描,在執(zhí)行效率上肯定是不能用于生產(chǎn)環(huán)境的,但是有了Generated類型就不同了,Generated類型簡單地說是一個虛擬字段,值是不可更新的,值來源其他字段或者字段間計算或是轉化而來的,這種類型是可以創(chuàng)建索引,利用Generated的特性,就可以間接的給Json類型中的key創(chuàng)建索引,解決Json不能創(chuàng)建索引的問題。簡而言之, Generated類型的產(chǎn)生,為Json類型在索引方面的問題提供了支持。JSON的值包含單個值、數(shù)組、元組、標注的Json格式等幾種格式。

客觀地說,Json類型的出現(xiàn),為研發(fā)提供了便利,提供了類似NoSQL的支持,但是走DBA運維的角度來看,也許是一個麻煩,這個麻煩和text等大字段的麻煩是一致的,json可能在實際的生產(chǎn)中會成為text字段的變種,望DBA在以后5.7的使用中密切關注這個類型。

一、創(chuàng)建帶有JSON字段的表

1、直接創(chuàng)建一張測試帶JSON字段的表

  1. CREATE TABLE json_test ( 
  2. id int(11) NOT NULL AUTO_INCREMENT, 
  3. group_name varchar(20) DEFAULT NULL
  4. user_info json DEFAULT NULL
  5. PRIMARY KEY (id) 
  6. ) ENGINE=InnoDB DEFAULT CHARSET=utf8; 

2、在表中添加一個JSON類型的字段

ALTER TABLE json_test ADD COLUMN user_info JSON DEFAULT NULL;

3、插入數(shù)據(jù)

二、JSON字段相關查詢

1、查詢全部結果

2:JSON_EXTRACT查詢

JSON_EXTRACT這個函數(shù)主要用作精確匹配,如查找user_info中age=21的記錄或者查詢name=’wangwei’的記錄,或者name like ‘%wangwei%’模糊查詢:

  1. SELECT * FROM json_test WHERE JSON_EXTRACT(user_info,'$.age')=21; 

在值為數(shù)組的時候,數(shù)組的起始位置值為0,同時,MySQL在5.5.9的版本增加了->,提供了等價于JSON_EXTRACT另外一種寫:

  1. SELECT * FROM json_test WHERE user_info->"$.age"=21; 

 

3、JSON_SEARCH查詢

JSON_SEARCH字符串查找函數(shù),查找json所有key中值為字符串’wangwei’的記錄,為精確匹配;加上%的話有點like的意思:

  1. SELECT * FROM json_test WHERE JSON_SEARCH(user_info,'all','wangwei'IS NOT NULL
  2.  
  3. SELECT * FROM json_test WHERE JSON_SEARCH(user_info,'all','wangwei%'IS NOT NULL
  4.  
  5. SELECT * FROM json_test WHERE JSON_SEARCH(user_info,'all','%wangwei%'IS NOT NULL

4、JSON_CONTAINS判斷key是否包含指定的值

JSON_CONTAINS判斷key是否包含指定的值,返回值為0或1或者是null,對應的情況為不包含、包含、和指定的key不存在集中情況:

5、JSON_CONTAINS_PATH判斷key在字段中是否存在

JSON_CONTAINS_PATH判斷key在字段中是否存在,返回值為0和1,格式為JSON_CONTAINS_PATH(json_doc, one_or_all, path[, path] ...),如果為one的時候,代表path中只要有一個在就為1,反之為0;如果為all的話必須全部包含,返回為1,反之為0:

6、JSON_LENGTH長度查詢

JSON_LENGTH是用來計算JSON字段的長度:

7:JSON_DEPTH層級查詢

JSON_DEPTH這個主要是用來查詢Json字段的層級,空的為1,所以正常情況下Json字段類型不為空,這個值的查詢出的結果應該大于等于2:

8:JSON_TYPE查詢Json字段中key值的數(shù)據(jù)類型

JSON_TYPE主要用于查詢Json字段類型中key值的數(shù)據(jù)類型,顯示的類型按照分類如下:

Purely JSON types:

OBJECT: JSON objects;ARRAY: JSON arrays;BOOLEAN: The JSON true and false literals;NULL: The JSON null literal

Numeric types:

INTEGER: MySQL TINYINT, SMALLINT, MEDIUMINT and INT and BIGINT scalars;DOUBLE: MySQL DOUBLE FLOAT scalars;DECIMAL: MySQL DECIMAL and NUMERIC scalars

Temporal types:

DATETIME: MySQL DATETIME and TIMESTAMP scalars;DATE: MySQL DATE scalars;TIME: MySQL TIME scalars

String types:

STRING: MySQL utf8 character type scalars;CHAR, VARCHAR, TEXT, ENUM, and SET

Binary types:

BLOB: MySQL binary type scalars;BINARY, VARBINARY, BLOB;BIT: MySQL BIT scalars

All other types:

OPAQUE (raw bits)

9、JSON_UNQUOTE去掉前后特殊字符

JSON_UNQUOTE主要是用來去掉前后的特殊字符,格式化值,目前支持一下幾種字符:

三、JSON字段相關寫操作

1、JSON_ARRAY_APPEND數(shù)組類的追加

這個用法主要是處理JSON字段中值數(shù)組型的數(shù)據(jù),主要是追加值,不是標準數(shù)組類型的,這個函數(shù)會自動轉化為數(shù)組形式,把之前的值作為數(shù)組的***個元素然后進行追加,有批量追加方法:

  1. mysql> SET @j = '["a", ["b", "c"], "d"]'

在字段中第二個數(shù)值的數(shù)組中追加一個元素1:

  1. mysql> SELECT JSON_ARRAY_APPEND(@j, '$[1]', 1); 
  2. +----------------------------------+ 
  3. | JSON_ARRAY_APPEND(@j, '$[1]', 1) | 
  4. +----------------------------------+ 
  5. | ["a", ["b""c", 1], "d"]         | 
  6. +----------------------------------+ 

在字段中***個數(shù)值的數(shù)組中追加一個元素2,如果不是數(shù)組形式的單個值會改變其為數(shù)組并追加:

  1. mysql> SELECT JSON_ARRAY_APPEND(@j, '$[0]', 2); 
  2. +----------------------------------+ 
  3. | JSON_ARRAY_APPEND(@j, '$[0]', 2) | 
  4. +----------------------------------+ 
  5. | [["a", 2], ["b""c"], "d"]      | 
  6. +----------------------------------+ 

在字段中第二個數(shù)值的***個數(shù)組中追加一個元素3,如果不是數(shù)組形式的單個值會改變其為數(shù)組并追加:

  1. mysql> SELECT JSON_ARRAY_APPEND(@j, '$[1][0]', 3); 
  2. +-------------------------------------+ 
  3. | JSON_ARRAY_APPEND(@j, '$[1][0]', 3) | 
  4. +-------------------------------------+ 
  5. | ["a", [["b", 3], "c"], "d"]         | 
  6. +-------------------------------------+ 

在字段中key為”b”的value數(shù)組中追加一個元素”x”:

  1. mysql> SET @j = '{"a": 1, "b": [2, 3], "c": 4}'
  2. mysql> SELECT JSON_ARRAY_APPEND(@j, '$.b''x'); 
  3. +------------------------------------+ 
  4. | JSON_ARRAY_APPEND(@j, '$.b''x')  | 
  5. +------------------------------------+ 
  6. | {"a": 1, "b": [2, 3, "x"], "c": 4} | 
  7. +------------------------------------+ 

在字段中key為”c”的value數(shù)組中追加一個元素”y”:

  1. mysql> SELECT JSON_ARRAY_APPEND(@j, '$.c''y'); 
  2. +--------------------------------------+ 
  3. | JSON_ARRAY_APPEND(@j, '$.c''y')    | 
  4. +--------------------------------------+ 
  5. | {"a": 1, "b": [2, 3], "c": [4, "y"]} | 
  6. +--------------------------------------+ 

如果JSON字段為標準的JSON類型,使用這個函數(shù)則會把其變化數(shù)組形式,并追加值:

  1. mysql> SET @j = '{"a": 1}'
  2. mysql> SELECT JSON_ARRAY_APPEND(@j, '$''z'); 
  3. +---------------------------------+ 
  4. | JSON_ARRAY_APPEND(@j, '$''z') | 
  5. +---------------------------------+ 
  6. | [{"a": 1}, "z"]                    | 
  7. +---------------------------------+ 

如果JSON字段為標準的JSON類型,批量追加:

  1. mysql> SELECT JSON_ARRAY_APPEND(@j, '$''z','$''w'); 
  2. +---------------------------------+ 
  3. | JSON_ARRAY_APPEND(@j, '$''z') | 
  4. +---------------------------------+ 
  5. | [{"a": 1}, "z""w"]              | 
  6. +---------------------------------+ 

2、JSON_ARRAY_INSERT數(shù)組類的插入

這個用法主要是處理JSON字段中值數(shù)組型的數(shù)據(jù),主要是插入,不是標準數(shù)組類型的,這個函數(shù)會自動轉化為數(shù)組形式,把之前的值作為數(shù)組的***個元素然后進行追加:

  1. mysql> SET @j = '["a", {"b": [1, 2]}, [3, 4]]'

在數(shù)組第1個值后面插入字符’x’ 元素:

  1. mysql> SELECT JSON_ARRAY_INSERT(@j, '$[1]''x'); 
  2. +------------------------------------+ 
  3. | JSON_ARRAY_INSERT(@j, '$[1]''x') | 
  4. +------------------------------------+ 
  5. | ["a""x", {"b": [1, 2]}, [3, 4]]  | 

在數(shù)組第1個值前面插入字符’x’ 元素:

  1. mysql> SELECT JSON_ARRAY_INSERT(@j, '$[0]''x'); 
  2. +------------------------------------+ 
  3. | JSON_ARRAY_INSERT(@j, '$[1]''x') | 
  4. +------------------------------------+ 
  5. | ["x","a", {"b": [1, 2]}, [3, 4]]  | 
  6. +------------------------------------+ 

在數(shù)組第100個值后面插入字符’x’ 元素,如果超長,則在***一個值后面插入:

  1. mysql> SELECT JSON_ARRAY_INSERT(@j, '$[100]''x'); 
  2. +--------------------------------------+ 
  3. | JSON_ARRAY_INSERT(@j, '$[100]''x') | 
  4. +--------------------------------------+ 
  5. | ["a", {"b": [1, 2]}, [3, 4], "x"]    | 
  6. +--------------------------------------+ 

在數(shù)組第1個值中key為’b’的value數(shù)組第1個值前面入字符元素’x’:

  1. mysql> SELECT JSON_ARRAY_INSERT(@j, '$[1].b[0]''x'); 
  2. +-----------------------------------------+ 
  3. | JSON_ARRAY_INSERT(@j, '$[1].b[0]''x') | 
  4. +-----------------------------------------+ 
  5. | ["a", {"b": ["x", 1, 2]}, [3, 4]]       | 
  6. +-----------------------------------------+ 

在數(shù)組第2個值后面數(shù)組第1個值后面入字符元素’y’:

  1. mysql> SELECT JSON_ARRAY_INSERT(@j, '$[2][1]''y'); 
  2. +---------------------------------------+ 
  3. | JSON_ARRAY_INSERT(@j, '$[2][1]''y') | 
  4. +---------------------------------------+ 
  5. | ["a", {"b": [1, 2]}, [3, "y", 4]]     | 
  6. +---------------------------------------+ 

數(shù)組元素的批量插入:

  1. mysql> SELECT JSON_ARRAY_INSERT(@j, '$[0]''x''$[2][1]''y'); 
  2. +----------------------------------------------------+ 
  3. | JSON_ARRAY_INSERT(@j, '$[0]''x''$[2][1]''y') | 
  4. +----------------------------------------------------+ 
  5. | ["x""a", {"b": [1, 2]}, [3, 4]]                      | 
  6. +----------------------------------------------------+ 

3、JSON_INSERT標準JSON值的插入

如果這個key已經(jīng)存在,則不會去覆蓋舊值,不存在的插入:

  1. mysql> SET @j = '{ "a": 1, "b": [2, 3]}'
  2. mysql> SELECT JSON_INSERT(@j, '$.a', 10, '$.c''[true, false]'); 
  3. +----------------------------------------------------+ 
  4. | JSON_INSERT(@j, '$.a', 10, '$.c''[true, false]') | 
  5. +----------------------------------------------------+ 
  6. | {"a": 1, "b": [2, 3], "c""[true, false]"}          | 
  7. +----------------------------------------------------+ 

4、JSON_MERGE合并操作

JSON_MERGE這個主要用于合并:如果兩個是數(shù)組的,則合并為一個數(shù)組;如果兩個是JSON的,則合并為一個JSON,如果兩個JSON有相同的key,則value合并為數(shù)組;如果是兩個單值的,則合并為一個數(shù)組;如果是一個數(shù)組,一個是JSON,則合并為一個數(shù)組:

  1. mysql> SELECT JSON_MERGE('[1, 2]''[true, false]'); 
  2. +---------------------------------------+ 
  3. | JSON_MERGE('[1, 2]''[true, false]') | 
  4. +---------------------------------------+ 
  5. | [1, 2, truefalse]                       | 
  6. +---------------------------------------+ 
  7. mysql> SELECT JSON_MERGE('{"name": "x"}''{"id": 47}'); 
  8. +-------------------------------------------+ 
  9. | JSON_MERGE('{"name": "x"}''{"id": 47}') | 
  10. +-------------------------------------------+ 
  11. | {"id": 47, "name""x"}                       | 
  12. +-------------------------------------------+ 
  13. mysql> SELECT JSON_MERGE('{"id": "x"}''{"id": 47}'); 
  14. +-------------------------------------------+ 
  15. | JSON_MERGE('{"id": "x"}''{"id": 47}') | 
  16. +-------------------------------------------+ 
  17. | {"id": ["x",47]}                             | 
  18. +-------------------------------------------+ 
  19. mysql> SELECT JSON_MERGE('1''true'); 
  20. +-------------------------+ 
  21. | JSON_MERGE('1''true') | 
  22. +-------------------------+ 
  23. | [1, true]                  | 
  24. +-------------------------+ 
  25. mysql> SELECT JSON_MERGE('[1, 2]''{"id": 47}'); 
  26. +------------------------------------+ 
  27. | JSON_MERGE('[1, 2]''{"id": 47}') | 
  28. +------------------------------------+ 
  29. | [1, 2, {"id": 47}]                    | 
  30. +------------------------------------+ 

5、JSON_REMOVE刪除操作

JSON_REMOVE刪除操作,這個比較簡單,刪除字段中某個值,數(shù)組的或是JSON格式的都可以:

  1. mysql> SET @j = '["a", ["b", "c"], "d"]'
  2. mysql> SELECT JSON_REMOVE(@j, '$[1]'); 
  3. +-------------------------+ 
  4. | JSON_REMOVE(@j, '$[1]') | 
  5. +-------------------------+ 
  6. | ["a""d"]                 | 
  7. +-------------------------+ 
  8. mysql> SET @j = '{"name": "x","id": 47}'
  9. mysql> SELECT JSON_REMOVE(@j, '$.id'); 
  10. +-------------------------+ 
  11. | JSON_REMOVE(@j, '$.id') | 
  12. +-------------------------+ 
  13. | {"name""x"}              | 
  14. +-------------------------+ 
  15. mysql> SELECT JSON_REMOVE(@j, '$.id''$.name'); 
  16. +-----------------------------------+ 
  17. | JSON_REMOVE(@j, '$.id''$.name') | 
  18. +-----------------------------------+ 
  19. | {}                                       | 
  20. +-----------------------------------+ 
  21. mysql> SET @j = '{"name": "x","id": [47,48]}'
  22. mysql> SELECT JSON_REMOVE(@j, '$.id[1]'); 
  23. +-------------------------+ 
  24. | JSON_REMOVE(@j, '$.id') | 
  25. +-------------------------+ 
  26. | {"id": [47],"name""x"} | 
  27. +-------------------------+ 

6、JSON_REPLACE操作

JSON_REPLACE替換操作,有則替換,無則忽略。

  1. mysql> SET @j = '{ "a": 1, "b": [2, 3]}'
  2. mysql> SELECT JSON_REPLACE(@j, '$.a', 10, '$.c''[true, false]'); 
  3. +-----------------------------------------------------+ 
  4. | JSON_REPLACE(@j, '$.a', 10, '$.c''[true, false]') | 
  5. +-----------------------------------------------------+ 
  6. | {"a": 10, "b": [2, 3]}                                    | 
  7. +-----------------------------------------------------+ 
  8. mysql> SELECT JSON_REPLACE(@j, '$.a', 10, '$.b[1]',99); 
  9. +-----------------------------------------------------+ 
  10. | JSON_REPLACE(@j, '$.a', 10, '$.b[1]',99') | 
  11. +-----------------------------------------------------+ 
  12. | {"a": 10, "b": [2, 99]}                                    | 
  13. +-----------------------------------------------------+ 

7、JSON_SET操作

JSON_SET操作為更新和插入操作,已經(jīng)存在的去更新;不存在則插入,以下是JSON_SET、JSON_INSERT、JSON_REPLACE執(zhí)行結果的區(qū)別:

四、JSON字段索引以及Generated字段

JSON字段類型在當前的版本中自身沒有索引,那么在生產(chǎn)中是非??膳碌?,JSON字段的增、刪、改、查效率可想而知,基本沒法用,也許是基于此,MySQL5.7中提供了Generated字段類型,網(wǎng)上有叫生成列或是計算列的。這里先來了解一下什么是Generated Column。

1、Generated Column介紹

Generated Column是MySQL 5.7.6引入的新特性,所謂Cenerated Column,就是數(shù)據(jù)庫中這一列由其他列計算而得。引用官方參考手冊中的例子予以說明:

  1. CREATE TABLE triangle ( 
  2.   sidea DOUBLE
  3.   sideb DOUBLE
  4.   sidec DOUBLE AS (SQRT(sidea * sidea + sideb * sideb)) 
  5. ); 
  6. INSERT INTO triangle (sidea, sideb) VALUES(1,1),(3,4),(6,8); 
  7. mysql> SELECT * FROM triangle; 
  8. +-------+-------+--------------------+ 
  9. | sidea | sideb | sidec              | 
  10. +-------+-------+--------------------+ 
  11. |     1 |     1 | 1.4142135623730951 | 
  12. |     3 |     4 |                  5     | 
  13. |     6 |     8 |                 10     | 
  14. +-------+-------+--------------------+ 

Generated Column有兩種,即Virtual Generated Column和Stored Generated Column,前者只將Generated Column保存在數(shù)據(jù)字典中(表的元數(shù)據(jù)),并不會將這一列數(shù)據(jù)持久化到磁盤上;后者會將Generated Column持久化到磁盤上,而不是每次讀取的時候計算所得。很明顯,后者存放了可以通過已有數(shù)據(jù)計算而得到的數(shù)據(jù),需要更多的磁盤空間,與Virtual Column相比并沒有優(yōu)勢,因此,MySQL 5.7中,不指定Generated Column的類型,默認是Virtual Column。雖然一般情況下都應該使用Virtal Generated Column,但是,目前使用Virtual Generated Column還有很多限制:不能用作主鍵、不能作為主鍵、不能創(chuàng)建全文索引和空間索引等,但是在后續(xù)的版本中可能支持,所以如果使用Generated Column字段做索引的話,還是使用Stored Generated Column吧,在使用Generated Column做索引上,JSON字段索引的解決方案,官方也是推薦使用Stored Generated Column。使用Stored Generated Column建表語句如下,只是在加了個單詞:

  1. CREATE TABLE triangle ( 
  2.   sidea DOUBLE
  3.   sideb DOUBLE
  4.   sidec DOUBLE AS (SQRT(sidea * sidea + sideb * sideb) STORED) 
  5. ); 

2、Generated Column注意事項

Generated Column是不能進行寫操作的,它是自動生成的;在創(chuàng)建的時候要考慮這個列的計算公式是否合理,不合理的話創(chuàng)建的時候不會報錯,使用時插入值就會報錯;Generated Column依賴的列在刪除的時候會提示報錯,必須先刪除Generated Column才能再去刪除它依賴的列;Generated Column定義不合法,如我們將generated column定義為 "x列+y列",很明顯,x列或y列都是數(shù)值型,如果我們將x列或y列定義(或修改)為字符型,則預期會報錯,但實際上我們可以正常創(chuàng)建,但是在插入的時候是會報錯的。

3、利用Generated Column給JSON字段添加索引

正常情況下,JSON字段的相關查詢是掃描全表的,因為JSON字段本身不能創(chuàng)建索引的,我們利用Generated Column特性,對JSON字段中相關key作為Generated Column來做生成列,然后對Generated Column做索引:

  1. ALTER TABLE json_test ADD COLUMN age INT AS (JSON_EXTRACT(user_info,'$.age')) STORED, ADD KEY idx_age (age); 

前后對比圖如下: 

可以很明顯的看出,使用Generated Column并添加索引后,查詢JSON字段中的值使用索引。

五、結束語

MySQL5.7中Generated Column和JSON Column的出現(xiàn),使一些場景替代MongoDB等NoSQL提供了可能,雖然整體上還沒有MongoDB等做的那么強大,但相信以后使用這兩種類型的場景會越來越多, 同時對DBA的挑戰(zhàn)也越來越大,希望密集使用JSON類型業(yè)務使用獨立的MySQL實例來運行,以免JSON成為大字段(存儲在JSON文檔的大小JSON 列被限制為值 max_allowed_packet的系統(tǒng)變量)時對其他業(yè)務帶來影響。

【本文是51CTO專欄作者王偉的原創(chuàng)文章,轉載請聯(lián)系作者本人獲取授權】

戳這里,看該作者更多好文

責任編輯:武曉燕 來源: 51CTO博客
相關推薦

2009-09-29 17:00:08

Hibernate c

2023-05-31 08:54:14

MySQL邏輯備份

2022-02-17 09:12:55

MySQL數(shù)據(jù)庫設置變量

2015-04-15 13:33:23

2010-10-25 12:17:48

oracle wm_c

2020-05-13 12:10:16

MYSQL特性數(shù)據(jù)庫

2021-07-29 10:39:50

MySQLMySQL5.7MySQL8

2020-12-31 05:35:53

MySQL 8.0MySQL 5.7JSON

2020-11-03 14:30:02

MySQL5.7MyS8.0數(shù)據(jù)庫

2021-01-11 16:19:45

MySQL數(shù)據(jù)庫服務器

2019-09-24 13:53:19

MySQLMySQL 8.0數(shù)據(jù)庫

2022-06-14 08:32:01

SQLOracleMySQL 8.0

2020-11-03 14:50:18

CentOSMySQL 8.0數(shù)去庫

2022-09-09 08:32:14

SQLMySQL數(shù)據(jù)庫

2023-02-28 00:01:53

MySQL數(shù)據(jù)庫工具

2023-11-02 08:44:58

2010-06-02 17:39:49

MySQL數(shù)據(jù)讀取

2009-11-20 17:17:08

Oracle函數(shù)索引
點贊
收藏

51CTO技術棧公眾號