通过mysql上的json字段性能改进顺序

时间:2017-12-05 01:53:14

标签: mysql json

我有这张桌子:

CREATE TABLE `mytable` (
  `session_id` mediumint(8) UNSIGNED NOT NULL,
  `data` json NOT NULL,
  `jobname` varchar(100) COLLATE utf8_unicode_ci GENERATED ALWAYS AS
    (json_unquote(json_extract(`data`,'$.jobname'))) VIRTUAL
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci
PARTITION BY HASH (session_id)
PARTITIONS 10;

ALTER TABLE `mytable`
  ADD KEY `session` (`session_id`),
  ADD KEY `jobname` (`jobname`);

它有200万行。

执行此查询时,大约需要23秒才能获得结果。

SELECT JSON_EXTRACT(f.data, '$.jobdesc') AS jobdesc
FROM mytable f 
WHERE f.session_id = 1
ORDER BY jobdesc DESC 

我知道它很慢,因为jobdesc字段没有索引。 在数据列中,我有12个字段。我想让用户能够对所有字段进行排序。如果我为每个字段添加索引,这是好方法吗? 有没有办法改善它?

我正在使用MYSQL 5.7.13。

1 个答案:

答案 0 :(得分:0)

如果您希望用户可以选择排序,则必须为12个字段中的每个字段创建一个带有索引的虚拟列。

CREATE TABLE `mytable` (
  `session_id` mediumint(8) UNSIGNED NOT NULL,
  `data` json NOT NULL,
  `jobname` varchar(100) AS (json_unquote(json_extract(`data`,'$.jobname'))),
  `jobdesc` varchar(100) AS (json_unquote(json_extract(`data`,'$.jobdesc'))),
  ...other extracted virtual fields...
  KEY (`jobname`),
  KEY (`jobdesc`),
  ...other indexes on virtual columns...
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci
PARTITION BY HASH (session_id)
PARTITIONS 10;

这让我想知道:为什么要使用JSON呢?为什么不直接使用索引声明12个传统的非虚拟列?

CREATE TABLE `mytable` (
  `session_id` mediumint(8) UNSIGNED NOT NULL,
  ...no `data` column needed...
  `jobname` varchar(100),
  `jobdesc` varchar(100),
  ...
  KEY (`jobname`),
  KEY (`jobdesc`),
  ...
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci
PARTITION BY HASH (session_id)
PARTITIONS 10;

当您将JSON视为单个原子文档时,JSON最好,并且不要尝试在其中的字段上使用SQL操作。如果您经常需要访问JSON中的字段,请将它们放入常规列中。