场景(简化)

现有文章表Article和评论表Comment;
一篇文章可以有多个评论;
文章表Article主要字段(articleId);
评论表Comment主要字段(commentId,articleId,content,createTime,lastChangeTime);

问题描述

发现很多文章下出现了评论内容一样的评论,所以需要对文章的评论进行数据清洗,即同一文章下相同内容的点评只保留修改时间最晚的一条(请忽略是不是同一个用户评论的问题);

解决步骤
  1. 接到需求当下的第一个想法是遍历Article表,然后通过UDF调用线上服务,线上服务再拿articleId去处理评论重复的问题,虽然这个方法简单,但是只适合小数据量,所以得继续观察;
  2. 然后查一下设计清洗的数据量有多少(对于有数据仓库的请不要在生产库查询,防止数据量太大影响线上功能),查询的结果大概是两千万左右,数据量太大,起初的想法不合理,只能换其它的方法;
  3. 询问了一下同事看有没有什么好的解决方案,同事说可以用SQL将需要清洗的数据筛选出来,由于我之前没有写过这么复杂的SQL语句,所以还心存怀疑,但事实证明SQL语句可以,让我知道了SQL的强大,不能因为没写过就质疑,这一点警醒了我;
  4. 开始写SQL(Hive平台支持类SQL语句进行查询),语句如下:
SELECT
	udf_fun ( concat_ws( '&', concat_ws( ',', collect_list ( commentId ) ), concat_ws( ',', collect_list ( lastChangeTime ) ) ) ) 
FROM
	(
SELECT
	articleId,
	content,
	commentId,
	lastChangeTime
FROM
	content 
WHERE
	( articleId, content ) IN (
SELECT
	articleId,
	content 
FROM Comment
GROUP BY
	articleId,
	content 
HAVING
	count( * ) > 1 
	) AS ccc 
GROUP BY
	articleId,
	content
  1. 执行Hive任务,在udf_fun中控制好访问生产环境时间间隔,不要无时间间隔,可能会影响生产环境;
总结

对于4步的SQL其实还可以进行一步完善,但是我嫌麻烦,而且本来就已经产生了几个临时表了,再继续增加临时表可能会拖慢性能,所以选择将commentId和最后修改时间连接成字符串发送给UDF,UDF再排一下序筛选一下这个方案,也是挺快的,当然选择这种方案你得看看你的最长拼接串是多长,如果太长,http请求可能传输不了。