我在MySQL中有以下表格和查询:
CREATE TABLE IF NOT EXISTS `events` (
`pv_name` varchar(60) COLLATE utf8mb4_unicode_ci NOT NULL,
`time_stamp` bigint(20) unsigned NOT NULL,
`event_type` varchar(40) COLLATE utf8mb4_unicode_ci NOT NULL,
`data` json,
PRIMARY KEY (`pv_name`,`time_stamp`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci ROW_FORMAT=COMPRESSED;
CREATE TEMPORARY TABLE matching_pv_names (
pv_name varchar(60) NOT NULL,
PRIMARY KEY (pv_name)
) ENGINE=Memory;
SELECT events.pv_name, MAX(events.time_stamp) AS time_stamp
FROM events
WHERE events.time_stamp <= @time_stamp_in
GROUP BY events.pv_name;
现在的查询可以高效运行&#39;使用索引进行分组排序&#39;。是否可以对其进行修改以将其分组的pv_names集合限制为matching_pv_names
表中的那些pv_names,并仍然保持&#39;使用索引进行分组排序&#39;优化?例如,以下查询不再使用此优化:
SELECT events.pv_name, MAX(events.time_stamp) AS time_stamp
FROM events
WHERE events.time_stamp <= @time_stamp_in
AND events.pv_name IN (SELECT matching_pv_names.pv_name FROM matching_pv_names)
GROUP BY events.pv_name;
还有另一种方法来编写它吗?
答案 0 :(得分:1)
您的第一个SQL可以从GROUP BY
优化中受益,因为它仅使用一个表,而您用于GROUP BY
的列具有索引,并且您使用的唯一聚合函数是MAX()
。并在WHERE子句中使用常量。
在查询中添加另一个表后,无法应用GROUP BY optimization。
答案 1 :(得分:0)
您询问了具体的优化问题,但不是关于效率的真正的问题?
了解这是如何运作的:
SELECT e.pv_name, MAX(e.time_stamp) AS time_stamp
FROM events AS e
JOIN matching_pv_names AS m USING(pv_name)
WHERE e.time_stamp <= @time_stamp_in
GROUP BY e.pv_name;
比较两个查询的效率的一种方法是
,即使表很小也是如此FLUSH STATUS;
SELECT ...;
SHOW SESSION STATUS LIKE 'Handler%';
从历史上看,这种结构的优化程度很低:IN ( SELECT ... )
。 (我不知道你的版本中的查询是否效果不佳。)