限制按列分组
Posted
技术标签:
【中文标题】限制按列分组【英文标题】:restriction on group by column 【发布时间】:2016-11-07 21:39:40 【问题描述】:我在 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;
当前的查询通过“使用索引进行分组”有效地运行。是否可以对其进行修改以将其分组的 pv_names 集限制为 matching_pv_names
表中的 pv_names 集,并且仍然保留“使用索引进行分组”优化?例如,以下查询不再使用此优化:
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;
有没有别的写法?
【问题讨论】:
【参考方案1】:您的第一个 SQL 可以从 GROUP BY
优化中受益,因为它只使用一个表,并且您用于 GROUP BY
的列上有索引,并且您使用的唯一聚合函数是 MAX()
。并且在 WHERE 子句中使用常量。
在查询中添加另一个表后,GROUP BY optimization 将无法应用。
【讨论】:
我认为你是对的。我希望有办法解决,因为我可以在查询中添加WHERE events.pv_name LIKE
并保留优化。
您不应该争取获得特定的优化,而应该争取“最佳”优化。
我相信这是最好的优化,无论是在文档中还是在对我的数据集进行测试时。【参考方案2】:
您询问了具体的优化问题,但真正的问题不是关于效率吗?
看看效果如何:
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 ... )
。 (我不知道在您的版本中它是否对您的查询效果不佳。)
【讨论】:
以上是关于限制按列分组的主要内容,如果未能解决你的问题,请参考以下文章