MySQL8.0 Generated Column 函數索引(四 ) —— JSON列的Generated Column 索引

在Innodbr中JSON 列使用函數索引

JSON類型的列不能直接創建索引,但可以間接創建索引,可以定義一個 Generated Column列,該列提取JSON字段的部分信息,然後在Generated Column列上創建索引,如以下示例所示:

mysql> CREATE TABLE jemp (
    ->     c JSON,
    ->     g INT GENERATED ALWAYS AS (c->"$.id")),
    ->     INDEX i (g)
    -> );
Query OK, 0 rows affected (0.28 sec)

mysql> INSERT INTO jemp (c) VALUES
     >   ('{"id": "1", "name": "Fred"}'), ('{"id": "2", "name": "Wilma"}'),
     >   ('{"id": "3", "name": "Barney"}'), ('{"id": "4", "name": "Betty"}');
Query OK, 4 rows affected (0.04 sec)
Records: 4  Duplicates: 0  Warnings: 0

mysql> SELECT c->>"$.name" AS name
     >     FROM jemp WHERE g > 2;
+--------+
| name   |
+--------+
| Barney |
| Betty  |
+--------+
2 rows in set (0.00 sec)

mysql> EXPLAIN SELECT c->>"$.name" AS name
     >    FROM jemp WHERE g > 2\G
*************************** 1. row ***************************
           id: 1
  select_type: SIMPLE
        table: jemp
   partitions: NULL
         type: range
possible_keys: i
          key: i
      key_len: 5
          ref: NULL
         rows: 2
     filtered: 100.00
        Extra: Using where
1 row in set, 1 warning (0.00 sec)

mysql> SHOW WARNINGS\G
*************************** 1. row ***************************
  Level: Note
   Code: 1003
Message: /* select#1 */ select json_unquote(json_extract(`test`.`jemp`.`c`,'$.name'))
AS `name` from `test`.`jemp` where (`test`.`jemp`.`g` > 2)
1 row in set (0.00 sec)

當對包含->或->>運算符的SELECT語句或其他SQL語句使用EXPLAIN時,這些表達式將使用JSON_EXTRACT和JSON_UNQUOTE(如果需要)轉換爲等價表達式,如此EXPLAIN語句後面的SHOW WARNINGS的輸出所示:

mysql> EXPLAIN SELECT c->>"$.name"
     > FROM jemp WHERE g > 2 ORDER BY c->"$.name"\G
*************************** 1. row ***************************
           id: 1
  select_type: SIMPLE
        table: jemp
   partitions: NULL
         type: range
possible_keys: i
          key: i
      key_len: 5
          ref: NULL
         rows: 2
     filtered: 100.00
        Extra: Using where; Using filesort
1 row in set, 1 warning (0.00 sec)

mysql> SHOW WARNINGS\G
*************************** 1. row ***************************
  Level: Note
   Code: 1003
Message: /* select#1 */ select json_unquote(json_extract(`test`.`jemp`.`c`,'$.name')) AS
`c->>"$.name"` from `test`.`jemp` where (`test`.`jemp`.`g` > 2) order by
json_extract(`test`.`jemp`.`c`,'$.name')
1 row in set (0.00 sec)

此技術還可用於提供間接引用其他類型(例如幾何列)的列的索引。

在NDB Cluster中JSON 列使用函數索引

還可以在MySQL NDB集羣中使用JSON列的間接索引,條件如下:

  • NDB在內部將JSON列作爲BLOB處理。這意味着,任何具有一個或多個JSON列的NDB表都必須有主鍵,否則無法將其記錄在二進制日誌中。
  • NDB存儲引擎不支持對 Generated Column列的索引。由於生成列的默認值爲VIRTUAL,因此必須顯式指定generated column 列的類型爲STORED ,然後再創建索引。

這裏用於創建表jempn的CREATE TABLE語句是前面創建jemp表的一個版本,通過修改使其與NDB引擎兼容:

CREATE TABLE jempn ( a BIGINT(20) NOT NULL AUTO_INCREMENT PRIMARY KEY, c JSON DEFAULT NULL, g INT GENERATED ALWAYS AS (c->"$.name") STORED, INDEX i (g) ) ENGINE=NDB;

我們可以使用以下INSERT語句填充此表:

INSERT INTO jempn (a, c) VALUES (NULL, '{"id": "1", "name": "Fred"}'), (NULL, '{"id": "2", "name": "Wilma"}'), (NULL, '{"id": "3", "name": "Barney"}'), (NULL, '{"id": "4", "name": "Betty"}');

現在NDB可以使用索引i,如下所示:

mysql> EXPLAIN SELECT c->>"$.name" AS name FROM jempn WHERE g > 2\G *************************** 1. row *************************** id: 1 select_type: SIMPLE table: jempn partitions: p0,p1 type: range possible_keys: i key: i key_len: 5 ref: NULL rows: 3 filtered: 100.00 Extra: Using where with pushed condition (`test`.`jempn`.`g` > 2) 1 row in set, 1 warning (0.00 sec) mysql> SHOW WARNINGS\G *************************** 1. row *************************** Level: Note Code: 1003 Message: /* select#1 */ select json_unquote(json_extract(`test`.`jempn`.`c`,'$.name')) AS `name` from `test`.`jempn` where (`test`.`jempn`.`g` > 2) 1 row in set (0.00 sec)

Stored 類型的Generated Column列 使用DataMemory,此類型列上的索引使用IndexMemory。

 

 

https://dev.mysql.com/doc/refman/8.0/en/create-table-secondary-indexes.html#json-column-indirect-index

發佈了94 篇原創文章 · 獲贊 74 · 訪問量 5萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章