[英]mysql udf json_extract in where clause - how to improve performance
[英]MySQL JSON_EXTRACT performance
我們有一個日志表,該表隨着新事件的發生而增長。 目前,我們存儲了約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字段來過濾某個特定應用程序的信息,例如:
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天之后,停止查詢是有用的,因為所有其他條目都更舊了。
如果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;
我已經減少了行數的內部選擇可以將查詢時間從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;
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.