我在MySQL中有以下表格:
CREATE TABLE `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,
`value` text CHARACTER SET utf8mb4 COLLATE utf8mb4_bin,
`value_type` varchar(40) COLLATE utf8mb4_unicode_ci DEFAULT NULL,
`value_count` bigint(20) DEFAULT NULL,
`alarm_status` varchar(40) COLLATE utf8mb4_unicode_ci DEFAULT NULL,
`alarm_severity` varchar(40) COLLATE utf8mb4_unicode_ci DEFAULT NULL,
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 DEFAULT CHARSET=latin1;
matching_pv_names
表包含唯一events.pv_name
值的子集。
使用“松散索引扫描”优化运行以下查询:
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;
是否可以通过将events.pv_name
值限制为matching_pv_names
表中的值而不会丢失'松散索引扫描'优化来改善此查询的时间?
答案 0 :(得分:0)
尝试使用以下查询之一将输出限制为matching_pv_names
中找到的匹配值。
查询1:
SELECT e.pv_name, MAX(e.time_stamp) AS time_stamp
FROM events e
INNER JOIN matching_pv_names pv ON e.pv_name = pv.pv_name
WHERE e.time_stamp <= time_stamp_in
GROUP BY e.pv_name;
查询2:
SELECT e.pv_name, MAX(e.time_stamp) AS time_stamp
FROM events e
WHERE e.time_stamp <= time_stamp_in
AND EXISTS ( select 1 from matching_pv_names pv WHERE e.pv_name = pv.pv_name )
GROUP BY e.pv_name;
我在这里引用manual,因为我认为它适用于你的情况(大胆强调我的):
如果WHERE子句包含范围谓词(...),则松散索引扫描会查找每个组的第一个键 满足范围条件,并再次读取最少 可能的键数。这可以在以下情况下进行 条件:
查询位于单个表格。
知道这一点,我相信查询1将无法使用松散的索引扫描,但可能第二个查询可以做到这一点。如果情况仍然如此,您还可以尝试使用派生表的第三种方法。
查询3:
SELECT e.*
FROM (
SELECT e.pv_name, MAX(e.time_stamp) AS time_stamp
FROM events e
WHERE e.time_stamp <= time_stamp_in
GROUP BY e.pv_name
) e
INNER JOIN matching_pv_names pv ON e.pv_name = pv.pv_name;
答案 1 :(得分:0)
您的查询非常有效。你可以通过这样做来“证明”它:
FLUSH STATUS;
SELECT ...;
SHOW SESSION STATUS LIKE 'Handler%';
大多数数字指的是索引或数据中的“触摸行”。你会看到非常低的数字。如果最大的一个是关于返回的行数,那就非常好了。 (我尝试了类似的查询,得到了大约2倍;我不知道为什么。)
接触了几行,然后
加速跳跃的唯一方法是以某种方式将所需的行移到彼此旁边。这对这个查询来说似乎是不合理的。
至于与另一张桌子玩游戏 - 也许吧。 JOIN会显着减少要查看的事件数量吗?然后也许吧。否则,我说“通过增加复杂性,一个非常有效的查询不会变得更快”。