MySQL JSON_提取性能

MySQL JSON_提取性能,mysql,nosql,Mysql,Nosql,我们有一个日志记录表,它随着新事件的发生而不断增长。目前,我们存储了大约120.000行日志事件 事件表如下所示: 'CREATE TABLE `EVENTS` ( `ID` int(11) NOT NULL AUTO_INCREMENT, `EVENT` varchar(255) NOT NULL, `ORIGIN` varchar(255) NOT NULL, `TIME_STAMP` TIMESTAMP NOT NULL, `ADDITIONAL_REMARKS` json DEFA

我们有一个日志记录表,它随着新事件的发生而不断增长。目前,我们存储了大约120.000行日志事件

事件表如下所示:

'CREATE TABLE `EVENTS` (
`ID` int(11) NOT NULL AUTO_INCREMENT, 
`EVENT` varchar(255) NOT NULL, 
`ORIGIN` varchar(255) NOT NULL,
`TIME_STAMP` TIMESTAMP NOT NULL, 
`ADDITIONAL_REMARKS` json DEFAULT NULL, 
PRIMARY KEY (`ID`)
) ENGINE=InnoDB AUTO_INCREMENT=137007 DEFAULT CHARSET=utf8'
附加的注释是一个JSON字段,因为不同的应用程序登录到此表中,可以向发生的事件添加更多信息。我不想在这里放置任何数据结构,因为这些信息可能不同。例如,一个项目管理应用程序可以记录:

ID, "new task created", "app", NOW(), {"project": {"id": 1}, "creator": {"id": 1}}
虽然其他应用程序没有项目或创建者,但可能有希望存储在“附加注释”字段中的猫和所有者

查询可以使用“附加备注”字段过滤特定应用程序的信息,如:

SELECT
DISTINCT(ADDITIONAL_REMARKS->"$.project.id") as 'project',
COUNT(CASE WHEN EVENT = 'new task created' THEN 1 END) AS 'new_task'
FROM EVENTS
WHERE DATE(TIMESTAMP) >= DATE(NOW()) - INTERVAL 30 DAY
AND ORIGIN = "app"
GROUP BY project
ORDER BY new_task DESC
LIMIT 10;
输出解释查询:

'1', 'SIMPLE', 'EVENTS', NULL, 'ALL', NULL, NULL, NULL, NULL, '136459', '100.00', 'Using where; Using temporary; Using filesort'
通过这个查询,我得到了过去30天中创建任务最多的前10个项目。工作正常,但随着表的增长,这种查询变得越来越慢。对于120.000行,此查询需要30秒以上


你知道提高速度的方法吗?表中id最高的最新信息比旧条目更重要。通常我只查找在过去X天内发生的条目。在第一个条目比where子句早X天之后停止查询会很有用,因为所有其他条目都比where子句早。

如果时间戳被索引,日期函数将不允许使用索引,因为它是不确定的

WHERE DATE(TIMESTAMP) >= DATE(NOW()) - INTERVAL 30 DAY
可以重写为

 WHERE TIMESTAMP >= UNIX_TIMESTAMP(DATE(NOW()) - INTERVAL 30 DAY)
你知道提高速度的方法吗

我所能看到的加快查询速度的唯一方法是多列索引TIMESTAMP和ORIGIN,比如
altertable事件添加键TIMESTAMP\u ORIGIN(TIME\u STAMP,ORIGIN)和上面的矿山查询调整

编辑

传递的表可以提高查询速度,因为它将使用新的索引

SELECT 
  ADDITIONAL_REMARKS->"$.project.id" AS 'project',
  COUNT(CASE WHEN EVENT = 'new task created' THEN 1 END) AS 'new_task'
FROM ( 

  SELECT 
   *
  FROM EVENTS 
  WHERE
    TIME_STAMP >= UNIX_TIMESTAMP(DATE(NOW()) - INTERVAL 30 DAY)
  AND
    ORIGIN = "app"
) 
 AS events_within_30_days

GROUP BY project
ORDER BY new_task DESC
LIMIT 10;    

我已经减少行数的内部选择可以将查询时间从30秒减少到0.05秒

它看起来像:

SELECT 
ADDITIONAL_REMARKS->"$.project.id" AS 'project',  
COUNT(CASE WHEN EVENT = 'new task created' THEN 1 END) AS 'new_task'
FROM ( 

SELECT *   
   FROM EVENTS    WHERE
   EVENT = 'new task created'
   AND TIME_STAMP >= UNIX_TIMESTAMP(DATE(NOW()) - INTERVAL 30 DAY)   
   AND ORIGIN = "app" )   AS events_within_30_days

GROUP BY project 
ORDER BY new_task DESC 
LIMIT 10;

关于查询性能的问题应该包括一个
SHOW CREATE TABLE EVENTS
,这样我们就可以查看是否有索引。第二,应该包括
EXPLAIN[query]
的输出。感谢您的建议。我在问题中添加了这两个。您忘记在CREATETABLE语句中放置列原点了吗?是的。抱歉,我重命名并删除了一些列以使问题更容易理解。如果没有作为“项目”部分的独特(附加注释->“$.project.id”),查询只需要0.1秒。首先:感谢您的帮助!现在我有了一个关于时间戳和原点的BTREE多列索引。但是查询仍然需要相同的时间。@user1482309没问题,可能没有使用新索引。我已经用一个传递的表更新了我的答案,它应该使用新的索引。传递的表可能会改进查询的执行。。。但是我认为你的查询很难优化,因为你的分组方式和排序方式都是动态的。我试图添加内部选择,添加差异索引策略,还替换了where子句to id>xxx to。没有区别。现在我考虑一个没有JSON字段的全新策略,比如附加的_注释。在解决了这个问题几个小时后,我找到了一个有效的解决方案!我在这里添加解决方案作为答案。谢谢你的建议,这是最终解决方案的一部分。