eorm icon indicating copy to clipboard operation
eorm copied to clipboard

分库分表:结果集处理---distinct

Open juniaoshaonian opened this issue 1 year ago • 2 comments

仅限中文

使用场景

  1. 去除重复数据 SELECT DISTINCT country FROM users;
  2. 与聚合函数结合 SELECT COUNT(DISTINCT country)FROM users
  3. 多个列去重 SELECT DISTINCT order_id,customer_id from orders; 本issue先不讨论和聚合函数结合的情况。

可行方案

如果你有设计思路或者解决方案,请在这里提供。你可以提供多个方案,并且给出自己的选择

  • 如果后面没有携带orderby子句,需要像之前处理group by一样,将数据全部从sql.Rows中全部取出,然后去重。这样处理的问题很明显,如果数据量太多的话会导致内存使用量较多。
  • 如果后面携带了order by子句就可以做一定优化。比如有sql.Rows1,sql.Rows2 ,sql.Rows3 类似之前排序的做法我们将 每个sql.Rows的第一个数据拿出来放到 堆中进行排序。我们保证堆中的数据不是重复的。那么从堆中拿出最小值a,如果这个值来自sql.Rows1。sql.Rows1就没有a了。sql.Rows2的值 > a 。sql.Rows3的值也是 > a 这样我们每次拿出来的值都是唯一的且后面相同的值。 注意点:在使用 DISTINCT 关键字时,ORDER BY 子句需要包含所有distinct的字段。

其它

任何你觉得有利于解决问题的补充说明

你使用的是 eorm 哪个版本?

你设置的的 Go 环境?

上传 go env 的结果

juniaoshaonian avatar May 23 '23 15:05 juniaoshaonian

这里,即便不包含所有的字段,是不是也可以进行优化?我思考了一下,ORDER BY 只包含部分字段是可以优化的,举例来说,如果要是 DISTINCT 包含了三个字段 col1, col2, col3,在 ORDER BY 里面包含了 col1,那么可以在去重的过程中,先确定 col1 的值,而后将 sql.Rows 里面的所有等于 col1 的列取出来,进行部分去重。这样也不需要在一开始就把所有的数据取过来。

但是 ORDER BY 对字段是有要求的,即要求 ORDER BY 中的前面几个列是 DISTINCT 列才能用上,例如 ORDER BY col2, col1 是可以的,但是 ORDER BY col4, col1 是不行的。

那么如果 ORDER BY 恰好包含所有的 DISTINCT 字段(或者更多),就仅仅是一种特殊的情况。

甚至于可以用一种实现,支撑住有 ORDER BY 或者没有 ORDER BY 的情况。但是不清楚这里难度会不会很高。如果不行的话,就可以考虑分为多个实现,然后拆成多个合并请求。

flycash avatar May 26 '23 06:05 flycash

我想了一下不是很高,大致的思路就是,将数据保存在两个地方,heap中还是保存着我们的排序列,全量数据我们保存在treemap中key就是我们的sortcols,value保存的还是treemap只不过此时的key变成了剩余的列。 注意点:排序列为a ,去重列为abc,我们在实现Next方法时需要将a相同的数据都拿出来,做剩余列的去重。这样我们Next取到的那个值后面才不会有相同的

juniaoshaonian avatar May 27 '23 13:05 juniaoshaonian