where子句中的mysql udf json_extract - 如何提高性能

Posted

技术标签:

【中文标题】where子句中的mysql udf json_extract - 如何提高性能【英文标题】:mysql udf json_extract in where clause - how to improve performance 【发布时间】:2014-12-27 11:58:40 【问题描述】:

如何在mysql数据库中高效搜索json数据?

我从 labs.mysql.com 安装了 extract_json udf,并使用了一个包含 2.750.000 个条目的测试表。

CREATE TABLE `testdb`.`JSON_TEST_TABLE` (
   `AUTO_ID` INT UNSIGNED NOT NULL AUTO_INCREMENT,
   `OP_ID` INT NULL,
   `JSON` LONGTEXT NULL,
PRIMARY KEY (`AUTO_ID`)) $$

示例 JSON 字段如下所示:

"ts": "2014-10-30 15:08:56 (9400.223725848107) ", "operation": "1846922"

我发现将 json_extract 放入 select 语句中几乎没有性能影响。 IE。以下选择(几乎)具有相同的性能:

SELECT * FROM JSON_TEST_TABLE where OP_ID=2000000 LIMIT 10;

SELECT OP_ID, json_extract(JSON, "ts") ts, json_extract(JSON, "operation") operation FROM JSON_TEST_TABLE where OP_ID=2000000 LIMIT 10; 

但是,一旦我将 json_extract 表达式放入 where 子句,执行时间就会增加 10 倍或更多(我从 2.5 秒增加到 30 秒):

SELECT OP_ID, json_extract(JSON, "ts") ts, json_extract(JSON, "operation") operation FROM JSON_TEST_TABLE where json_extract(JSON, "operation")=2000000 LIMIT 10;

此时我在想,我需要在插入时将我想要搜索的所有信息提取到单独的列中,如果我真的必须在 json 数据中搜索,我需要先缩小行数被其他标准搜索,但我想确保我没有遗漏任何明显的东西。 例如。我可以以某种方式索引 json 字段吗?还是我的 select 语句写的效率低?

【问题讨论】:

我认为如果您对查询执行 EXPLAIN,您会看到 MySQL 进行了全表扫描,这仅仅是因为您的查询是在未编入索引的术语上。 【参考方案1】:

其实在执行过程中

SELECT * FROM JSON_TEST_TABLE where OP_ID=2000000 LIMIT 10;

json_extract() 最多执行 10 次。

在此期间

SELECT OP_ID, json_extract(JSON, "ts") ts, json_extract(JSON, "operation") operation FROM JSON_TEST_TABLE where json_extract(JSON, "operation")=2000000 LIMIT 10;

json_extract() 将对每一行执行,结果限制为 10 条记录,因此速度损失。 索引也无济于事,因为处理时间用完了,而不是外部代码而不是 MySQL 的。 恕我直言,在这种情况下最好的选择是优化 UDF。

【讨论】:

感谢您的澄清,但是......这个问题已经快 3 年了! ;-) 我最终将数据转储到弹性搜索实例中......问题解决了。【参考方案2】:

你可以试试这个: http://www.percona.com/blog/2015/02/17/indexing-json-documents-for-efficient-mysql-queries-over-json-data/

用于 MySQL 的 Flexviews 物化视图用于使用 JSON_EXTRACT 从 JSON 中提取数据到另一个可以索引的表中。

【讨论】:

以上是关于where子句中的mysql udf json_extract - 如何提高性能的主要内容,如果未能解决你的问题,请参考以下文章

where子句中的mysql udf json_extract - 如何提高性能

为啥在 CTE 中的 WHERE 子句之前执行 UDF 调用?

SQLite - WHERE 子句和 UDF

where子句mysql中的MAX函数[重复]

where子句mysql中的MAX函数[重复]

#1054 - MySQL 中“where 子句”中的未知列“proximite”