MySQL + JSON = King Fried. .

Relational structured storage has certain drawbacks, because it needs to pre-define all columns and their corresponding types. However, in the process of business development, it may be necessary to expand the description function of a single column. At this time, if the JSON data type can be used well, it can open up the boundary between the storage of relational and non-relational data, and provide better business services. architecture choice.

Of course, many students will encounter various problems when using the JSON data type. The most common mistake is to simply understand the type JSON as a string type . But when you read this article, you will really realize the power of the JSON data type to better store unstructured data in practice.

JSON data type


JSON (JavaScript Object Notation) is mainly used for data exchange between Internet application services. MySQL supports the JSON specification defined by RFC 7159, which mainly includes two types: JSON object and JSON array . The following is the JSON object, which is mainly used to store the relevant information of the picture:

{
 "Image": {
   "Width": 800,
   "Height": 600,
   "Title": "View from 15th Floor",
   "Thumbnail": {
     "Url": "http://www.example.com/image/481989943",
     "Height": 125,
     "Width": 100
   },
 "IDs": [116, 943, 234, 38793]
 }
}

As you can see, the JSON type can describe the relevant content of the data well, such as the width, height, title, etc. of this image (the types used here include integer and string types).

In addition to supporting string, integer, and date types, JSON objects also support array types for embedded fields in JSON, such as the IDs field in the above code.

Another JSON data type is an array type, such as:

[
   {
     "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"
   }
 ]

The above example demonstrates a JSON array with 2 JSON objects.

So far, many students may regard JSON as a large field string type. On the surface, there is nothing wrong. But in essence, JSON is a new type with its own storage format. It can also create indexes on each corresponding field and perform specific optimizations, which cannot be achieved by traditional field strings. Another benefit of the JSON type is that there is no need to predefine fields , and fields can be extended infinitely. However, the columns of traditional relational databases need to be defined in advance. If you want to expand, you need to perform heavy operations such as ALTER TABLE ... ADD COLUMN ... .

It should be noted that the JSON type is a feature supported since MySQL version 5.7, and version 8.0 solves the log performance bottleneck of updating JSON. If you want to use the JSON data type in a production environment, MySQL version 8.0 is strongly recommended.

At this point, you already have an understanding of the basic concepts of JSON types. Next, let's enter the practical part: how to make good use of JSON types in business?

Business table structure design practice


User login design

In the database, the JSON type is more suitable for storing some relatively static data with less modification. For example, the storage of user login information is as follows:

DROP TABLE IF EXISTS UserLogin;

CREATE TABLE UserLogin (
    userId BIGINT NOT NULL,
    loginInfo JSON,
    PRIMARY KEY(userId)
);

Since the current business login methods are becoming more and more diverse, for example, the same account supports mobile phone, WeChat, and QQ account login, so the login information can be stored in JSON type here.

Next, insert the following data:

SET @a = '
{
   "cellphone" : "13918888888",
   "wxchat" : "破产码农",
   "QQ" : "82946772"
}
';

INSERT INTO UserLogin VALUES (1,@a);

SET @b = '
{  
  "cellphone" : "15026888888"
}
';

INSERT INTO UserLogin VALUES (2,@b);

As can be seen from the above example, there are three ways for user 1 to log in: mobile phone verification code login, WeChat login, and QQ login, while user 2 only has mobile phone verification code to log in.

If the JSON data type is not used, the table should be built in the following way:

SELECT
    userId,
    JSON_UNQUOTE(JSON_EXTRACT(loginInfo,"$.cellphone")) cellphone,
    JSON_UNQUOTE(JSON_EXTRACT(loginInfo,"$.wxchat")) wxchat
FROM UserLogin;
+--------+-------------+--------------+
| userId | cellphone   | wxchat       |
+--------+-------------+--------------+
|      1 | 13918888888 | 破产码农     |
|      2 | 15026888888 | NULL         |
+--------+-------------+--------------+
2 rows in set (0.01 sec)

Of course, it is very troublesome to write JSON_EXTRACT and JSON_UNQUOTE every time. MySQL also provides ->> expression, which has exactly the same effect as the above SQL:

SELECT 
    userId,
    loginInfo->>"$.cellphone" cellphone,
    loginInfo->>"$.wxchat" wxchat
FROM UserLogin;

When the amount of JSON data is very large and users want to efficiently retrieve JSON data, they can use MySQL's function index function to index a field in JSON.

For example, in the user login example above, assuming that the user must bind a unique mobile phone number and wish to use the mobile phone number for user retrieval in the future, the following index can be created:

ALTER TABLE UserLogin ADD COLUMN cellphone VARCHAR(255) AS (loginInfo->>"$.cellphone");

ALTER TABLE UserLogin ADD UNIQUE INDEX idx_cellphone(cellphone);

The above SQL first creates a virtual column cellphone, which is calculated by the function loginInfo->>"$.cellphone". Then create a unique index idx_cellphone on this virtual column. At this time, query through the virtual column cellphone, and you can see that the optimizer will use the newly created idx_cellphone index:

EXPLAIN SELECT  *  FROM UserLogin 
WHERE cellphone = '13918888888'\G
*************************** 1. row ***************************
           id: 1
  select_type: SIMPLE
        table: UserLogin
   partitions: NULL
         type: const
possible_keys: idx_cellphone
          key: idx_cellphone
      key_len: 1023
          ref: const
         rows: 1
     filtered: 100.00
        Extra: NULL
1 row in set, 1 warning (0.00 sec)

Of course, we can complete the creation of virtual columns and functional indexes when we first create the table. The column cellphone created in the following table corresponds to the content in JSON and is a virtual column; uk_idx_cellphone is the index created on the virtual column cellphone.

CREATE TABLE UserLogin (
    userId BIGINT,
    loginInfo JSON,
    cellphone VARCHAR(255) AS (loginInfo->>"$.cellphone"),
    PRIMARY KEY(userId),
    UNIQUE KEY uk_idx_cellphone(cellphone)
);

User portrait design

Some businesses need to do user portraits (that is, to tag users), and then make corresponding product recommendations through data mining technology based on user tags. for example:

  • In the e-commerce industry, according to the user's clothing preferences, the corresponding products are recommended;
  • In the music industry, according to the music style that users like and the singers they often listen to, the corresponding songs are recommended;
  • In the financial industry, according to the user's risk preference and investment experience, the corresponding financial products are recommended.

Here, I strongly recommend that you use JSON type to store user portrait information in the database, and combine the characteristics of JSON array type and multi-value index for efficient query. Suppose there is a picture definition table:

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 | 爱网购       |
|    12 | 爱外卖       |
+-------+--------------+

It can be seen that the table Tags is a portrait definition table, which is used to describe how many tags are currently defined, and then tag each user, such as user David, whose tags are post-80s, highly educated, petty bourgeoisie, have a house, I often watch movies; user Tom, born in the 90s, often watches movies, and loves takeout food.

If you don't use the JSON data type for tag storage, you usually use the user tag to pass a string and add a separator to access all the user's tags in a field:

+-------+---------------------------------------+
|用户    |标签                                   |
+-------+---------------------------------------+
|David  |80后 ; 高学历 ; 小资 ; 有房 ;常看电影   |
|Tom    |90后 ;常看电影 ; 爱外卖                 |
+-------+---------------------------------------

The disadvantage of this is that it is not easy to search for users with specific portraits, and the separator is also a self-convention. In fact, other data can be stored arbitrarily in the database, which will eventually generate dirty data.

This problem can be solved nicely with the JSON data type:

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]');

Among them, the tags stored in userTags are those tag values ​​defined in the table Tags, which are only stored in JSON array type.

MySQL 8.0.17 version began to support Multi-Valued Indexes, which is used to create indexes on JSON arrays and quickly retrieve index data through functions member of, json_contains, and json_overlaps. So you can create Multi-Valued Indexes on table UserTag:

ALTER TABLE UserTag
ADD INDEX idx_user_tags ((cast((userTags->"$") as unsigned array)));

If you want to query the user profile as a user who often watches movies, you can use the function MEMBER OF:

EXPLAIN SELECT * FROM UserTag 
WHERE 10 MEMBER OF(userTags->"$")\G
*************************** 1. row ***************************
           id: 1
  select_type: SIMPLE
        table: UserTag
   partitions: NULL
         type: ref
possible_keys: idx_user_tags
          key: idx_user_tags
      key_len: 9
          ref: const
         rows: 1
     filtered: 100.00
        Extra: Using where
1 row in set, 1 warning (0.00 sec)

SELECT * FROM UserTag 
WHERE 10 MEMBER OF(userTags->"$");
+--------+---------------+
| userId | userTags      |
+--------+---------------+
|      1 | [2, 6, 8, 10] |
|      2 | [3, 10, 12]   |
+--------+---------------+
2 rows in set (0.00 sec)

If you want to query users whose portraits are post-80s and who often watch movies, you can use the function JSON_CONTAINS:

EXPLAIN SELECT * FROM UserTag 
WHERE JSON_CONTAINS(userTags->"$", '[2,10]')\G
*************************** 1. row ***************************
           id: 1
  select_type: SIMPLE
        table: UserTag
   partitions: NULL
         type: range
possible_keys: idx_user_tags
          key: idx_user_tags
      key_len: 9
          ref: NULL
         rows: 3
     filtered: 100.00
        Extra: Using where
1 row in set, 1 warning (0.00 sec)

SELECT * FROM UserTag 
WHERE JSON_CONTAINS(userTags->"$", '[2,10]');
+--------+---------------+
| userId | userTags      |
+--------+---------------+
|      1 | [2, 6, 8, 10] |
+--------+---------------+
1 row in set (0.00 sec)

If you want to query users who are born in the 1980s and 1990s and often watch movies, you can use the function JSON_OVERLAP:

EXPLAIN SELECT * FROM UserTag 
WHERE JSON_OVERLAPS(userTags->"$", '[2,3,10]')\G
*************************** 1. row ***************************
           id: 1
  select_type: SIMPLE
        table: UserTag
   partitions: NULL
         type: range
possible_keys: idx_user_tags
          key: idx_user_tags
      key_len: 9
          ref: NULL
         rows: 4
     filtered: 100.00
        Extra: Using where
1 row in set, 1 warning (0.00 sec)

SELECT * FROM UserTag 
WHERE JSON_OVERLAPS(userTags->"$", '[2,3,10]');
+--------+---------------+
| userId | userTags      |
+--------+---------------+
|      1 | [2, 6, 8, 10] |
|      2 | [3, 10, 12]   |
+--------+---------------+
2 rows in set (0.01 sec)

Summarize


The JSON type is a new data type in MySQL 5.7. Using the JSON data type can effectively solve many practical problems in business. Finally, I summarize today's highlights:

  • Using JSON data type, MySQL 8.0.17 or later is recommended, which has better performance and also supports Multi-Valued Indexes;
  • The advantage of the JSON data type is that there is no need to define columns in advance, and the data itself is very descriptive;
  • Do not store data with obvious relationship in JSON, such as user balance, user name, user ID, etc. These are all data that each user must contain;
  • The JSON data type is recommended for static data storage that is not frequently updated.

Copyright statement: This article is an original article by the blogger and follows the CC 4.0 BY-SA copyright agreement. Please attach the original source link and this statement for reprinting.

Link to this article: https://blog.csdn.net/java_pfx/article/details/116594654

Recommended recent hot articles:

1. 1,000+ Java interview questions and answers (2022 latest version)

2. Madden! Java coroutines are coming. . .

3. Spring Boot 2.x tutorial, so complete!

4. Don't write the full screen explosion class, try the decorator mode, this is the elegant way! !

5. "Java Development Manual (Songshan Edition)" is the latest release, download it quickly!

If you think it's good, don't forget to like + retweet!

Guess you like

Origin blog.csdn.net/youanyyou/article/details/123685889