在 MySQL 8 中索引 JSON 列

cho*_*cki 2 mysql database indexing mysql-8.0

所以我正在试验 json 列。Mysql 8.0.17 应该使用多值 JSON 索引,如下所示:

CREATE INDEX data__nbr_idx ON a1( (CAST(data->'$.nbr' AS UNSIGNED ARRAY)) )

我有这样的 JSON 列类别 ["books", "clothes"]。我需要从“书籍”类别中获取所有产品。我可以使用“json_contains”或新的“成员”。

SELECT * FROM products WHERE JSON_CONTAINS(categories, '\"books\"')
SELECT * FROM products WHERE "books" MEMBER OF(categories)
Run Code Online (Sandbox Code Playgroud)

它有效。问题是当然 EXPLAIN 会显示有查询正在进行全表扫描,因此它很慢。

所以我需要一些索引。

我通过将“无符号”类型替换为“char(32)”来更改索引示例,因为我的类别是字符串而不是数字。我在谷歌中找不到任何示例,所以我认为 char() 会很好,但不是。

这是我的索引查询:

CREATE INDEX categories_index ON products((CAST(categories AS CHAR(32) ARRAY)))
Run Code Online (Sandbox Code Playgroud)

也试过

CREATE INDEX categories_index ON products((CAST(categories->'$' AS CHAR(32) ARRAY)))
Run Code Online (Sandbox Code Playgroud)

但选择仍在进行全表扫描。我做错了什么?如何在不使用虚拟列的情况下正确索引 json 列?

Sol*_*are 5

对于多值 json 索引,json 路径必须匹配,因此使用索引

CREATE INDEX categories_index 
ON products((CAST(categories->'$' AS CHAR(32) ARRAY)))
Run Code Online (Sandbox Code Playgroud)

您的查询还必须使用路径->'$'(或等效的json_extract(...,'$')

SELECT * FROM products WHERE "books" MEMBER OF(categories->'$')
Run Code Online (Sandbox Code Playgroud)

使其一致,它应该可以工作。

似乎没有显式路径的索引无法按预期工作,因此您必须指定->'$'是否要使用整个文档。这可能是一个错误,但也可能是将或自动转换为数组的预期行为。如果您指定路径,您将处于安全状态。