我有一个查询,我很节俭地花了很长时间。我在具有50万行的表的单个分区上运行它。
查询如下:
select col0 from <table> where partition=<partition> and <col1>=<val>
我是这样col1 != val
,所以查询返回0行。
此查询大约需要30秒(如果使用select *
,则是一分钟)。
当我运行完全相同的查询但使用select count(col0)
时,需要2秒钟。
使用select col
而不使用select count(col)
可能导致查询花费很长时间吗?
这是解释的查询
explain select col0 from table where `partition` = partition and col=val;
*项目[col0#607]
+-*过滤器(isnotnull(col1#607)&&(col1#607 = aaaa))
+-* FileScan实木复合地板
表[col1#607,partition#611]
批处理:true,
格式:镶木地板,
位置:PrunedInMemoryFileIndex [...,
分区数:23,
分区过滤器:[isnotnull(partition#611),
(cast(partition#611 as int)= partition_name)],
PushedFilters:[IsNotNull(col1),
EqualTo(col1,aaaa)],
ReadSchema:结构
explain select count(col0) from table where `partition` = partition and col=val;
* HashAggregate(keys = [],functions = [count(col0#625)])
+-交换SinglePartition
+-* HashAggregate(keys = [],functions = [partial_count(col0#625)])
+-*项目[col0#625]
+-*过滤器(isnotnull(col1#625)&&(col1#625 = aaaa))
+-* FileScan实木复合地板
表[col1#625,partition#629] 批处理:true,
格式:镶木地板,
位置:PrunedInMemoryFileIndex [...,
分区数:23,
分区过滤器:[isnotnull(partition#629),
(cast(partition#629 as int)= partition_name)],
PushedFilters:[IsNotNull(col1),
EqualTo(col1,aaaa)],
ReadSchema:结构
据我所知,该过程完全相同,只有count
查询具有更多步骤。那怎么快15倍呢?
修改:
我在日志中发现了一个有趣的块:
计数:
18/06/28 11:42:55 INFO TaskSetManager:在阶段2509.0中启动任务0.0(TID 8092,ip-123456,执行程序36,分区0,RACK_LOCAL,5521个字节)
18/06/28 11:42:55 INFO TaskSetManager:在阶段2509.0中启动任务1.0(TID 8093,ip-123456,执行程序35,分区1,RACK_LOCAL,5521个字节)
18/06/28 11:42:55 INFO TaskSetManager:在阶段2509.0中启动任务2.0(TID 8094,ip-123456,执行程序36,分区2,RACK_LOCAL,5521个字节)
18/06/28 11:42:55 INFO TaskSetManager:在阶段2509.0中启动任务3.0(TID 8095,ip-123456,执行程序35,分区3,RACK_LOCAL,5521个字节)
18/06/28 11:42:55 INFO TaskSetManager:在阶段2509.0中启动任务4.0(TID 8096,ip-123456,执行程序36,分区4,RACK_LOCAL,5521个字节)
18/06/28 11:42:55 INFO TaskSetManager:在阶段2509.0中启动任务5.0(TID 8097,ip-123456,执行程序35,分区5,RACK_LOCAL,5521个字节)
18/06/28 11:42:55 INFO TaskSetManager:在阶段2509.0中启动任务6.0(TID 8098,ip-123456,执行程序36,分区6,RACK_LOCAL,5521个字节)
18/06/28 11:42:55 INFO TaskSetManager:在阶段2509.0中启动任务7.0(TID 8099,ip-123456,执行程序35,分区7,RACK_LOCAL,5521个字节)
18/06/28 11:42:55 INFO TaskSetManager:在阶段2509.0中启动任务8.0(TID 8100,ip-123456,执行程序36,分区8,RACK_LOCAL,5521个字节)
18/06/28 11:42:55 INFO TaskSetManager:在阶段2509.0中启动任务9.0(TID 8101,ip-123456,执行程序35,分区9,RACK_LOCAL,5521个字节)
18/06/28 11:45:32 INFO TaskSetManager:在阶段2512.0中启动任务0.0 (TID 8136,ip-10-117-49-97.eu-west-1.compute .internal,执行程序37,分区1,RACK_LOCAL,5532字节)
18/06/28 11:45:32 INFO BlockManagerInfo:在IP-10-117-49-97.eu-west-1.compute.internal:40489的内存中添加了broadcast_2352_piece0(大小:12.6 KB,可用空间:11.6 GB)
18/06/28 11:45:32 INFO TaskSetManager:在ip上以667 ms在ip-10-117-49-97.eu-west-1.compute.internal(执行器37)上完成了阶段2512.0(TID 8136)中的任务0.0 (1/1)
18/06/28 11:45:32 INFO YarnScheduler:从池中删除了任务已全部完成的TaskSet 2512.0
18/06/28 11:45:32信息DA调度程序:ResultStage 2512(OperationManager.java:220中的getNextRowSet)在0.668 s中完成
18/06/28 11:45:32 INFO DAGS计划程序:作业2293已完成:OperationManager.java:220中的getNextRowSet,耗时0.671740 s
18/06/28 11:45:32 INFO SparkContext:开始作业:OperationManager.java中的getNextRowSet:220
18/06/28 11:45:32信息DAscheduler:获得作业2294(OperationManager.java:220中的getNextRowSet)具有1个输出分区
18/06/28 11:45:32 INFO DAGS计划程序:最后阶段:ResultStage 2513(OperationManager.java:220上的getNextRowSet)
18/06/28 11:45:32 INFO DAGS日程表:最后阶段的父母:List()
18/06/28 11:45:32 INFO DAGS日程表:父母失踪:List()
18/06/28 11:45:32信息DAScheduler:提交ResultStage 2513(在AccessController.java:0上运行时运行MapPartitionsRDD [312]),没有丢失的父级
18/06/28 11:45:32 INFO MemoryStore:阻止广播_2353作为值存储在内存中(估计大小66.6 KB,可用12.1 GB)
18/06/28 11:45:32 INFO MemoryStore:块广播_2353_piece0作为字节存储在内存中(估计大小为12.6 KB,可用的12.1 GB)
18/06/28 11:45:32 INFO BlockManagerInfo:在10.117.48.68:41493的内存中添加了broadcast_2353_piece0(大小:12.6 KB,可用空间:12.1 GB)
18/06/28 11:45:32 INFO SparkContext:从DAGScheduler.scala:1047
的广播创建广播2353 18/06/28 11:45:32信息DAScheduler:从ResultStage 2513提交1个丢失的任务(MapPartitionsRDD [312]在AccessController.java:0上运行)(前15个任务用于分区
Vector(2)) 18/06/28 11:45:32 INFO YarnScheduler:添加包含1个任务的任务集2513.0
18/06/28 11:45:32 INFO TaskSetManager:在阶段2513.0中启动任务0.0 (TID 8137,ip-10-117-49-97.eu-west-1.compute.internal,执行程序37,分区2,RACK_LOCAL,5532个字节)
18/06/28 11:45:33 INFO BlockManagerInfo:在IP-10-117-49-97.eu-west-1.compute.internal:40489的内存中添加了broadcast_2353_piece0(大小:12.6 KB,可用空间:11.6 GB)
18/06/28 11:45:38 INFO TaskSetManager:在ip-10-117-49-97.eu-west-1.compute.internal(执行器37)上5238 ms的阶段2513.0(TID 8137)中完成了任务0.0 (1/1)
18/06/28 11:45:38 INFO YarnScheduler:从池中删除了任务已全部完成的TaskSet 2513.0
18/06/28 11:45:38信息DA调度程序:ResultStage 2513(OperationManager.java:220上的getNextRowSet)在5.238 s中完成
18/06/28 11:45:38信息DAS计划程序:作业2294已完成:OperationManager.java:220上的getNextRowSet,耗时5.242084 s
18/06/28 11:45:38 INFO SparkContext:开始作业:OperationManager.java上的getNextRowSet:220
18/06/28 11:45:38信息DAscheduler:获得了2295个作业(OperationManager.java:220中的getNextRowSet)和1个输出分区
18/06/28 11:45:38 INFO DAGS计划程序:最后阶段:ResultStage 2514(OperationManager.java:220上的getNextRowSet)
18/06/28 11:45:38 INFO DAGS日程表:最后阶段的父母:List()
18/06/28 11:45:38 INFO DAGS日程表:父母失踪:List()
18/06/28 11:45:38信息DAScheduler:提交ResultStage 2514(在AccessController.java:0上运行时运行MapPartitionsRDD [312]),没有丢失的父级
18/06/28 11:45:38 INFO MemoryStore:阻止广播_2354作为值存储在内存中(估计大小66.6 KB,可用12.1 GB)
18/06/28 11:45:38 INFO MemoryStore:块广播_2354_piece0作为字节存储在内存中(估计大小12.6 KB,可用12.1 GB)
18/06/28 11:45:38 INFO BlockManagerInfo:在10.117.48.68:41493的内存中添加了broadcast_2354_piece0(大小:12.6 KB,可用:12.1 GB)
18/06/28 11:45:38 INFO SparkContext:从DAGScheduler.scala:1047
的广播创建广播2354 18/06/28 11:45:38信息DAScheduler:从ResultStage 2514(在AccessController.java:0上运行时运行MapPartitionsRDD [312])提交1个丢失的任务(前15个任务用于分区Vector(3))
(即,它重复执行此块,看起来像在计数情况下,它顺序地运行任务而不是并行运行)
我也尝试执行“ order by”,实际上使查询运行2倍更快
使用spark而不是节俭方法对相同数据运行相同的查询要快得多。
我在AWS Emr-5.11.1上运行节俭
配置单元2.3.2
火花2.2.1
节俭0.11.0
答案 0 :(得分:1)
发现了问题。我有这个标志
spark.sql.thriftServer.incrementalCollect=true
thriftserver中的。它按顺序收集每个工作人员的输出,这就是造成大量开销的原因。删除标志可解决此问题。我猜它被优化为在做“计数”时不按顺序执行,因为它不一定会有很多数据。