我的数据库有一个具有以下结构的临时表:
CREATE TABLE featureMappings (
id bigint(20) NOT NULL AUTO_INCREMENT,
visitId bigint(20) NOT NULL,
featureId bigint(20) NOT NULL,
textValue text DEFAULT NULL,
hashTextValue char(32) GENERATED ALWAYS AS (MD5(textValue)) VIRTUAL,
PRIMARY KEY (id));
ALTER TABLE featureMappings
ADD INDEX fsHashTextValue (featureId, hashTextValue)
在典型的运行中,该表大约有 40 - 1 亿行。有很多重复的文本值,因此我使用 hashTextValue 键能够在此列上建立索引。
以下查询运行大约需要 25 秒:
CREATE TEMPORARY TABLE temp AS
SELECT
featureId,
hashTextValue
FROM
featureMappings
GROUP BY featureId, hashTextValue
问题
我想提取 textValue
列以及 featureId
和 hashTextValue
列中的值。
我尝试了两种方法。这两者都极大地增加了查询时间,因此我正在寻找更好的解决方案。
慢速选项 1 - 将 textValue
添加到查询
对查询运行 belo 更改时,处理时间从 25 秒缩短到大约 10 分钟。我试图用谷歌搜索在不使用聚合函数时如何检索 textValue
,但找不到明确的答案。
CREATE TEMPORARY TABLE temp AS
SELECT
featureId,
hashTextValue,
textValue # I also tried MIN(textValue)
FROM
featureMappings
GROUP BY featureId, hashTextValue
复杂选项 2:迭代更新
我的首选方法是迭代第一个查询的唯一组合,然后对以下查询运行循环:
SELECT featureId, hashTextValue INTO @fid, @htv
FROM temp
WHERE textValue is NULL and hashTextValue IS NOT NULL
LIMIT 1;
SELECT textValue
INTO @textValue
FROM featureMappings
WHERE featureId = @fid and hashTextValue = @htv
LIMIT 1;
UPDATE temp
SET textValue = @textValue
WHERE featureId = @fid AND hashTextValue = @htv;
服务器配置
它正在基于 Mysql 5.7 的 AWS RDS Aurora 上运行。服务器的内存有限 (2GB),并且通常可用内存少于表上的索引大小。
最佳答案
A 计划:加载时进行重复数据删除。通过将 featureMappings
的 PK 设为 PRIMARY KEY(featureId, hashTextValue)
并在加载临时表时使用 INSERT IGNORE
即可轻松完成此操作。
B 计划:(假设有一些因素阻碍 A 计划)更改具有这些索引的表。
PRIMARY KEY (featureId, hashTextValue, id),
INDEX(id)
这仍然有重复,但我不清楚接下来需要发生什么。
进一步...
SELECT featureId, hashTextValue INTO @fid, @htv
FROM temp
WHERE textValue is NULL and hashTextValue IS NOT NULL
LIMIT 1;
这会带来一个问题,当你吃掉匹配的元素时,速度会变得越来越慢。最好添加显式的 PRIMARY KEY
并遍历 temp
。事实上,它会快一个数量级(如果 temp
很大)。假设id
是PK;那么:
SELECT @id := id, @fid := featureId, @htv := hashTextValue INTO
FROM temp
WHERE textValue is NULL and hashTextValue IS NOT NULL
AND id > @id -- this picks up 'where you left off'
LIMIT 1;
(使用SET @id := 0;
初始化)
现在您有了id
,UPDATE
变得更简单、更快。
关于mysql - 使用哈希时获取行的单个示例的有效方法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54407340/