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”