MySQL JSON_提取性能
我们有一个日志记录表,它随着新事件的发生而不断增长。目前,我们存储了大约120.000行日志事件 事件表如下所示: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
'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字段的全新策略,比如附加的_注释。在解决了这个问题几个小时后,我找到了一个有效的解决方案!我在这里添加解决方案作为答案。谢谢你的建议,这是最终解决方案的一部分。