我们有一个日志记录表,随着新事件的发生而增长。目前,我们存储了大约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'
Additional_Remarks是一个JSON字段,因为不同的应用程序登录到此表并可以向发生的事件添加更多信息。我不想在这里放任何数据结构,因为这些信息可能不同。例如,一个项目管理应用程序可以记录:
ID, "new task created", "app", NOW(), {"project": {"id": 1}, "creator": {"id": 1}}
虽然其他应用程序没有项目或创建者,但也许他们想要存储在Additional_Remarks字段中的猫和所有者。
查询可以使用Additional_Remarks字段过滤某个特定应用程序的信息,如:
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;
输出EXPLAIN查询:
'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天之后停止查询会很有用,因为所有其他条目都更旧。
答案 0 :(得分:1)
如果对TIME_STAMP编制索引,则DATE函数将不允许使用索引,因为它是不确定的。
WHERE DATE(TIMESTAMP) >= DATE(NOW()) - INTERVAL 30 DAY
可以改写为。
WHERE TIMESTAMP >= UNIX_TIMESTAMP(DATE(NOW()) - INTERVAL 30 DAY)
你知道提高速度的方法吗?
我能看到加速查询的唯一方法是多列索引TIMESTAMP和ORIGIN,如ALTER TABLE EVENTS ADD KEY timestamp_origin (TIME_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;
答案 1 :(得分:0)
我已经减少了行数的内部选择可以将查询时间从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;