Удаление дубликатов с помощью DISTINCT vs GROUP BY в Spark SQL

#apache-spark #apache-spark-sql

#apache-spark #apache-spark-sql

Вопрос:

spark-sql Я использую Spark-sql 2.4.

У меня есть вопрос, который не дает мне покоя уже довольно давно — использовать ли DISTINCT OR GROUP BY (без каких-либо агрегаций) для эффективного удаления дубликатов из таблицы с лучшей производительностью запросов.

При DISTINCT этом я бы использовал следующее —

 select distinct 
       id, 
       fname, 
       lname, 
       age
from emp_table;
 

Для GROUP BY я просто использую :

 select id,
       fname,
       lname,
       age
from emp_table
group by 1, 2, 3, 4;
 

Я где-то читал о Spark-SQL том, что это Distinct следует использовать, только если значение cardinality набора данных велико, в противном случае используйте Group By . Однако в моей повседневной работе я видел, что Duplicate это работает лучше, чем Group By даже в сценариях, где мощность низкая.

Итак, мой вопрос в том, какой из них будет работать лучше в каких сценариях.

Может кто-нибудь, пожалуйста, просветите меня по этому вопросу. В каких условиях запрос с будет выполняться лучше, чем в каких сценариях. Distinct Group By

Спасибо

Комментарии:

1. попробуйте .explain и расскажите нам о своих выводах.

Ответ №1:

Они функционально эквивалентны и будут генерировать один и тот же план запроса. Для наглядности используйте distinct.

Ответ №2:

Вот планы запросов для двух запросов. Как сказал @thebluephantom, они идентичны, поэтому не должно быть никакой разницы в производительности.

 create table t1 (a int, b int, c int, d int);

explain select a,b,c,d from t1 group by 1,2,3,4;
== Physical Plan ==
*(2) HashAggregate(keys=[a#14, b#15, c#16, d#17], functions=[])
 - Exchange hashpartitioning(a#14, b#15, c#16, d#17, 200), true, [id=#33]
    - *(1) HashAggregate(keys=[a#14, b#15, c#16, d#17], functions=[])
       - Scan hive default.t1 [a#14, b#15, c#16, d#17], HiveTableRelation `default`.`t1`, org.apache.hadoop.hive.serde2.lazy.LazySimpleSerDe, [a#14, b#15, c#16, d#17], Statistics(sizeInBytes=8.0 EiB)
 
 explain select distinct a,b,c,d from t1;
== Physical Plan ==
*(2) HashAggregate(keys=[a#23, b#24, c#25, d#26], functions=[])
 - Exchange hashpartitioning(a#23, b#24, c#25, d#26, 200), true, [id=#58]
    - *(1) HashAggregate(keys=[a#23, b#24, c#25, d#26], functions=[])
       - Scan hive default.t1 [a#23, b#24, c#25, d#26], HiveTableRelation `default`.`t1`, org.apache.hadoop.hive.serde2.lazy.LazySimpleSerDe, [a#23, b#24, c#25, d#26], Statistics(sizeInBytes=8.0 EiB)
 

Расширенное объяснение показывает, что запрос стал идентичным после их оптимизации:

 explain extended select a,b,c,d from t1 group by 1,2,3,4;
== Parsed Logical Plan ==
'Aggregate [1, 2, 3, 4], ['a, 'b, 'c, 'd]
 - 'UnresolvedRelation [t1]

== Analyzed Logical Plan ==
a: int, b: int, c: int, d: int
Aggregate [a#41, b#42, c#43, d#44], [a#41, b#42, c#43, d#44]
 - SubqueryAlias spark_catalog.default.t1
    - HiveTableRelation `default`.`t1`, org.apache.hadoop.hive.serde2.lazy.LazySimpleSerDe, [a#41, b#42, c#43, d#44], Statistics(sizeInBytes=8.0 EiB)

== Optimized Logical Plan ==
Aggregate [a#41, b#42, c#43, d#44], [a#41, b#42, c#43, d#44]
 - HiveTableRelation `default`.`t1`, org.apache.hadoop.hive.serde2.lazy.LazySimpleSerDe, [a#41, b#42, c#43, d#44], Statistics(sizeInBytes=8.0 EiB)

== Physical Plan ==
*(2) HashAggregate(keys=[a#41, b#42, c#43, d#44], functions=[], output=[a#41, b#42, c#43, d#44])
 - Exchange hashpartitioning(a#41, b#42, c#43, d#44, 200), true, [id=#108]
    - *(1) HashAggregate(keys=[a#41, b#42, c#43, d#44], functions=[], output=[a#41, b#42, c#43, d#44])
       - Scan hive default.t1 [a#41, b#42, c#43, d#44], HiveTableRelation `default`.`t1`, org.apache.hadoop.hive.serde2.lazy.LazySimpleSerDe, [a#41, b#42, c#43, d#44], Statistics(sizeInBytes=8.0 EiB)
 
 explain extended select distinct a,b,c,d from t1;
== Parsed Logical Plan ==
'Distinct
 - 'Project ['a, 'b, 'c, 'd]
    - 'UnresolvedRelation [t1]

== Analyzed Logical Plan ==
a: int, b: int, c: int, d: int
Distinct
 - Project [a#50, b#51, c#52, d#53]
    - SubqueryAlias spark_catalog.default.t1
       - HiveTableRelation `default`.`t1`, org.apache.hadoop.hive.serde2.lazy.LazySimpleSerDe, [a#50, b#51, c#52, d#53], Statistics(sizeInBytes=8.0 EiB)

== Optimized Logical Plan ==
Aggregate [a#50, b#51, c#52, d#53], [a#50, b#51, c#52, d#53]
 - HiveTableRelation `default`.`t1`, org.apache.hadoop.hive.serde2.lazy.LazySimpleSerDe, [a#50, b#51, c#52, d#53], Statistics(sizeInBytes=8.0 EiB)

== Physical Plan ==
*(2) HashAggregate(keys=[a#50, b#51, c#52, d#53], functions=[], output=[a#50, b#51, c#52, d#53])
 - Exchange hashpartitioning(a#50, b#51, c#52, d#53, 200), true, [id=#133]
    - *(1) HashAggregate(keys=[a#50, b#51, c#52, d#53], functions=[], output=[a#50, b#51, c#52, d#53])
       - Scan hive default.t1 [a#50, b#51, c#52, d#53], HiveTableRelation `default`.`t1`, org.apache.hadoop.hive.serde2.lazy.LazySimpleSerDe, [a#50, b#51, c#52, d#53], Statistics(sizeInBytes=8.0 EiB)
 

И на самом деле предполагает, что механизм запросов, похоже, предпочитает group by запрос.

Комментарии:

1. спасибо за ваш ответ. Можете ли вы, пожалуйста, помочь мне понять, почему вы говорите, что group by это предложение предпочтительнее на основе приведенных выше планов запросов.

2. @Matthew извините, если я плохо сформулировал это, я просто имел в виду, что оптимизированный запрос больше похож на неоптимизированный запрос group by, чем на неоптимизированный запрос distinct. Это просто наблюдение, которое не имеет отношения к тому, как на самом деле выполняется запрос. Я бы предложил использовать distinct в вашем реальном запросе для повышения удобства чтения.

3. @thebluephantom не совсем, мне просто интересно это понять — это действительно первый раз, когда я запускаю explain extended

4. нет, я имею в виду вообще? у вас стремительный рост, просто интересно…