Successfully reported this slideshow.
We use your LinkedIn profile and activity data to personalize ads and to show you more relevant ads. You can change your ad preferences anytime.

JSON array indexes in MySQL

251 views

Published on

Pre FOSDEM MySQL Days 2020

Published in: Software
  • Be the first to comment

JSON array indexes in MySQL

  1. 1. Copyright © 2019 Oracle and/or its afliates.1 JSON array indexes in MySQL Dag H. Wanvik Senior database engineer MySQL Optimizer Team pre FOSDEM MySQL days 2020 New in 8.0.17
  2. 2. Copyright © 2019 Oracle and/or its afliates.2 Safe harbor statement The following is intended to outline our general product direction. It is intended for information purposes only, and may not be incorporated into any contract. It is not a commitment to deliver any material, code, or functionality, and should not be relied upon in making purchasing decisions. The development, release, timing, and pricing of any features or functionality described for Oracle’s products may change and remains at the sole discretion of Oracle Corporation.
  3. 3. Copyright © 2019 Oracle and/or its afliates.3 Program agenda 1 What is it? 2 How do I use it? 3 Demo
  4. 4. Copyright © 2019 Oracle and/or its afliates.4 What is it?  Index of a JSON array – A functional index over a JSON expression – The expression evaluates to an array  Several index entries per row – One index entry per array element – General mechanism, (a.k.a. multi-valued index) currently used for JSON arrays  Used to speed up array lookups – JSON_CONTAINS(…) – JSON_OVERLAPS(…) – MEMBER OF (…)
  5. 5. Copyright © 2019 Oracle and/or its afliates.5 Until 8.0.16  Index a JSON column using a generated expression – A index over a generated expression extracted from a JSON column ALTER TABLE lottery ADD COLUMN (id_int INT GENERATED ALWAYS AS (data->'$.id')); CREATE UNIQUE INDEX id_idx ON lottery(id_int); – But what about contents of JSON arrays?
  6. 6. Copyright © 2019 Oracle and/or its afliates.6 In 8.0.17  Index contents of a JSON array using a multi valued index – A functional index over a JSON expression CREATE UNIQUE INDEX <idxname> ON <table> ((CAST(<column>->'<json path>' AS UNSIGNED INT ARRAY)));
  7. 7. Copyright © 2019 Oracle and/or its afliates.7 Table Multi-valued index [1] [2,22] [3,33,333] [4,44,444,4444] 2 22 N-1 index JSON column
  8. 8. Copyright © 2019 Oracle and/or its afliates.8 JSON array index as part of a composite index ALTER TABLE customers ADD INDEX comp ( id, modifed, (CAST(custinfo->'$.zipcode' AS UNSIGNED ARRAY)) ); - Only one multi-valued key part can be used in a composite index: avoid combinatorial explosion - The multi-valued key part may be used anywhere in the key parts list
  9. 9. Copyright © 2019 Oracle and/or its afliates.9 Further features  Can faten and index nested arrays – CAST(json->'$.the_array[*][*]' AS UNSIGNED INT ARRAY)  Can it be UNIQUE: Yes – If defned as a unique key, atempting to insert a value already present in the multi- valued index returns a duplicate key error. – If duplicate values are already present, atempting to add a unique multi-valued index fails – But: a single row's array(s) may have duplicates: [1, 2, 3, 2] is OK  Can it be PRIMARY: No
  10. 10. Copyright © 2019 Oracle and/or its afliates.10 Limitations  JSON null not allowed in arrays to be indexed mysql> insert into lotery values ('{"id":1, "name":"Alice", "lotery_tickets": [null]}'); ERROR 3903 (22018): Invalid JSON value for CAST for functional index 'ticket_idx'.
  11. 11. Copyright © 2019 Oracle and/or its afliates.11 Limitations  JSON null not allowed in arrays to be indexed: mysql> insert into lotery values ('{"id":1, "name":"Alice", "lotery_tickets": [null]}'); ERROR 3903 (22018): Invalid JSON value for CAST for functional index 'ticket_idx'.  JSON null not allowed in path of array to be indexed: mysql> insert into lotery values ('{"id":1, "name":"Alice", "lotery_tickets": null}'); ERROR 3903 (22018): Invalid JSON value for CAST for functional index 'ticket_idx'.
  12. 12. Copyright © 2019 Oracle and/or its afliates.12 Limitations  JSON null not allowed in arrays to be indexed: mysql> insert into lotery values ('{"id":1, "name":"Alice", "lotery_tickets": [null]}'); ERROR 3903 (22018): Invalid JSON value for CAST for functional index 'ticket_idx'.  JSON null not allowed in path of array to be indexed: mysql> insert into lotery values ('{"id":1, "name":"Alice", "lotery_tickets": null}'); ERROR 3903 (22018): Invalid JSON value for CAST for functional index 'ticket_idx'.  SQL null is allowed for JSON data: mysql> insert into lotery(data) values (null);
  13. 13. Copyright © 2019 Oracle and/or its afliates.13 How do I use it? CREATE TABLE <table> (<column> JSON); CREATE INDEX <index> ON <table> ((CAST(<column>->'$[*] AS <type> ARRAY))); <type> ::= SIGNED [INT] | UNSIGNED [INT] | DATE | DATETIME | TIME | CHAR [(N)] [charset_info] | DECIMAL [(M [, D])]
  14. 14. Copyright © 2019 Oracle and/or its afliates.14 How do I use it? CREATE TABLE lotery (data JSON); CREATE INDEX ticket_idx ON lotery ((CAST(data->'$.lotery_tickets' AS UNSIGNED INT ARRAY))); Cast to array is only available when creating a functional index Type of array element
  15. 15. Copyright © 2019 Oracle and/or its afliates.15 How do I use it? CREATE TABLE lotery (data JSON); CREATE INDEX ticket_idx ON lotery ((CAST(data->'$.lotery_tickets' AS UNSIGNED INT ARRAY))); Note: extra parens needed
  16. 16. Copyright © 2019 Oracle and/or its afliates.16 How do I use it? CREATE TABLE lotery (data JSON); CREATE INDEX ticket_idx ON lotery ((CAST(data->'$.lotery_tickets' AS UNSIGNED INT ARRAY) )); Syntax: CREATE [UNIQUE] INDEX <index_name> [<index_type>] ON <tbl_name> (<key_part>,...) .... <key_part>: { <col_name> [ (<length>) ] | (<expr>) } ... Note: extra parens needed
  17. 17. Copyright © 2019 Oracle and/or its afliates.17 How do I use it? CREATE TABLE lotery (data JSON); CREATE UNIQUE INDEX ticket_idx ON lotery ((CAST(data->'$.lotery_tickets' AS UNSIGNED INT ARRAY))); INSERT INTO lotery VALUES ('{"id":1, "name":"Alice", "lotery_tickets": [1]}'), ('{"id":2, "name":"Bob", "lotery_tickets": [2,22]}'), ('{"id":3, "name":"Carol", "lotery_tickets": [3,33,333]}'), ('{"id":4, "name":"Dan", "lotery_tickets": [4,44,444,4444]}'), ('{"id":5, "name":"Erin", "lotery_tickets": [5,55,555,5555,55555]}');
  18. 18. Copyright © 2019 Oracle and/or its afliates.18 How do I use it? JSON functions recap: JSON_CONTAINS (arg1, arg2) “AND”: true if arg2 document is contained within the arg1 JSON document JSON_OVERLAPS (arg1, arg2) “OR”: true if the two document have any key-value pairs or array elements in common value MEMBER OF (json-array)
  19. 19. Copyright © 2019 Oracle and/or its afliates.19 How do I use it? Find winner Find all rows where the array contains a given value (only one here): SELECT data FROM lotery WHERE JSON_CONTAINS(data->'$.lotery_tickets', CAST(22 AS JSON)); Or '22' instead of CAST
  20. 20. Copyright © 2019 Oracle and/or its afliates.20 How do I use it? Find winner Find all rows where the array contains a given value (only one here): SELECT data FROM lotery WHERE JSON_CONTAINS(data->'$.lotery_tickets', CAST(22 AS JSON)); or SELECT data FROM lotery WHERE 22 MEMBER OF (data->'$.lotery_tickets'); Or '22' instead of CAST
  21. 21. Copyright © 2019 Oracle and/or its afliates.21 How do I use it? Find several winners Find all rows that contain one or more of the given values SELECT data FROM lotery WHERE JSON_OVERLAPS(data->'$.lotery_tickets', CAST('[22,44]' AS JSON)); Find everyone with at least one winning ticket
  22. 22. Copyright © 2019 Oracle and/or its afliates.22 Demo
  23. 23. Copyright © 2019 Oracle and/or its afliates.23 WL#8955, WL#8763 https://dev.mysql.com/doc/refman/8.0/en/ create-index.html#create-index-multi- valued
  24. 24. Copyright © 2019 Oracle and/or its afliates.27 Feature descriptions and design details directly from the source https://mysqlserverteam.com/
  25. 25. Copyright © 2019 Oracle and/or its afliates.28 Thank you! Dag H. Wanvik Senior Database Developer MySQL Optimizer Team

×